Search code examples
javaurlencode

Program works in Eclipse, but not as a jar


My compiler is set to be compliant with java 1.8. When I run my code, it works and there are no warnings.

When I go to export everything as a runnable jar and execute it, it throws this error:

Exception in thread "main" java.lang.NoSuchMethodError: java.net.URLEncoder.encode(Ljava/lang/String;Ljava/nio/charset/Charset;)Ljava/lang/String;
        at ...

My code needs to convert some user-input String to make an API-call, for which it needs to be URL compliant, e.g. by replacing spaces with '%20'. I am using java.net.URLEncoder.encode for this.

My system has jre version 1.8.0_411 installed so this really shouldn't be happening, right?


Solution

  • There are 3 barely related aspects which all combine into '.. would run on java 1.8':

    • Any updates to the lang spec itself. For example, the concept of 'var' was introduced in java 10. It did not exist in java 9. This isn't a library thing; you don't have to import anything to use var in java. It just.. cannot be used, at all, in java9 and before, and is just there starting in java 10. This is what the --source option is/used to be for.

    • The class file spec is a separate thing, but in practice, it is updated for every java release, and always in an incompatible way. Emitting a class file that a java.exe from java 1.8 can't run trivially means it's not gonna run on java 1.8. Generally, any new source features require the class file format that goes along with that java release. This is what --target is/used to be for.

    • Java ships with a sizable standard library which is updated every java release. Using anything that was added in, say, java 1.9 (i.e. wasn't there in java 1.8) would result in that exact error.

    You can't just tell eclipse 'hey, uh, please, only 1.8 stuff' and expect that final bullet to 'just work' - knowing what is and is not available on java 1.8 is complicated, because the standard library does not actually ship with the 'this has been here since version X' information, so, eclipse can't go: Oh, hey now hold on a second you are using something that wasn't in java 1.8. It seems like it is there (javadoc @since tags) but these aren't guaranteed by the java spec.

    Hence, eclipse needs an actual java 1.8 installation in order to know. You say you have one - okay, great! Tell eclipse about it, and then it can help you.

    The procedure is as follows:

    • In eclipse's settings, use the filterbox to search for 'JRE' and add your java 1.8 path. Eclipse should tell you automatically 'ah, that is a java, at version 1.8'. Note that a JRE is useless here. Get a JDK. Note that JREs as a concept is over 10 years dead, they no longer exist. Get the JDK v1.8, tell eclipse about it.
    • Next, in your project settings, set it all to java 1.8: Lang compatibility, class output, and the JDK to use to compile against - which you can set to 1.8 if you did the previous step.