How to catch 'Unsupported major.minor version' error? - java

I understand the issue regarding this type of error. I would like my program to be able to detect the java version running and provide a more elegant message to the user rather than the somewhat cryptic 'Exception in thread "main" bla bla bla' message. I can detect the Java version running, but it appears that my program never gets far enough to run my checking code.
In short... how can my program catch this error, present a message and exit gracefully?

This exception is throwing from ClassLoader, so I could suggest you write your own version of ClassLoader which will backtrace such errors.
UPD: More specifically you can try to override method defineClass, catch there such exception and wrap it in convenient way.
UPD-2: As I mentioned in comments, and as us2012 reformulated my idea (thanks to him), you have to compile your classloader with a -target that is guaranteed to be lower than the user's VM version

So it's java.lang.UnsupportedClassVersionError. It is (evidently a descendant of the Error class in Java) which subclasses java.lang.ClassFormatError which in turn subclasses java.lang.LinkageError (which is a direct subclass of java.lang.Error)). This error is thrown in the cases when the JVM (Java Virtual Machine) attempts to read a class file and finds that the major and minor version numbers in the particular class file are not supported. This happens in the cases when a higher version of Java Compiler is used to generate the class file than the JVM version which is used to execute that class file.
This is quite easier to understand – how can the compiler have the information at the time of compilation about which version of JVM would be used execute the compiled class file? It can't, right? So is the case with other errors as well. This is the reason why all the Errors are unchecked.
Why you even give user the chance to see this error message! This as you say "cryptic" message will only be emitted out when you are using an earlier version of JVM to execute the class file than the corresponding version of compiler you used to compile the source code. Now, why would you do that?

Related

How to modify the size of String Pool in JVM?

I was reading a book on Java and there was an option mentioned to modify the size of the String Pool, and that option was XX:StringTableSize. When I tried this in my command line, I got an error saying this is an invalid flag, I tried both of the following and the same error occurred:
error: invalid flag: -XX1234
error: invalid flag: -XX:1234
What is the error? I couldn't find a solution for this in the Java SE reference, even I did not see any option like "-XX".
What is the reason behind that, did I made a syntactical error or this option is deprecated or something else? I am using JDK 11.
You are probably passing less than the minimum value allowed. For e.g I can successfully run below on OpenJDK 11
java -XX:StringTableSize=16777216 TestClass
You can also refer to excellent link here for summary of different VM options available in different JDK releases.
If I provide less than what is allowed, I get this
java -XX:StringTableSize=10 TestClass
uintx StringTableSize=10 is outside the allowed range [ 128 ... 16777216 ]
Improperly specified VM option 'StringTableSize=10'
In past there has been discussions on the usefulness and correctness of such parameter support. You can read about these here.

javac not displaying compiler errors?

I'm teaching my friend some Java, and we're running into issues trying to run the compiler on her Hello World program. The code had a pretty glaring error (Sysrem.out.println), but otherwise was totally valid Java, but for some reason the compiler didn't report the error. Here's what happened:
When we ran javac Hello.java in Windows Command Prompt, it printed out a blank line and then a new command prompt line, as if the operation had succeeded, but it clearly hadn't - a class file wasn't created, and of course the code had an error so we knew it wouldn't be successful.
When we ran javac -verbose Hello.java, it printed out the gory details of the class files it was loading, but then that was it. While it didn't end by saying it had written a class file, it also didn't print out the error.
After we fixed the error, the program compiled and ran without a problem, so it seems to be that javac just doesn't like printing out compiler errors.
What could be going on here, why isn't the compiler reporting this error like it should?
The complete code:
public class Hello {
public static void main(String[] args) {
Sysrem.out.println("Hello, world!");
}
}
The command prompt:
C:\Users\MyFriendsName\Documents>javac Hello.java
C:\Users\MyFriendsName\Documents>
What this actually boils down to is whether an empty file is a valid Java program. Surprisingly, it is!
Here is the grammar for a CompilationUnit ... which is the technical term that that JLS uses for a Java source file:
CompilationUnit:
OrdinaryCompilationUnit
ModularCompilationUnit
OrdinaryCompilationUnit:
[PackageDeclaration] {ImportDeclaration} {TypeDeclaration}
ModularCompilationUnit:
{ImportDeclaration} ModuleDeclaration
(Reference: JLS 7.3)
Note that the OrdinaryCompilationUnit element allows you to have a source file that consists of:
no package statement
no import statements
no type declarations
In other words, an empty file, or a file that just contains comments.
In short, if you tell javac to compile an empty file, it won't produce any compilation errors ... because it is "valid" Java source code file.
Well, I discovered the issue: Turns out my friend had never hit Save on her file after creating it, and in what I'm assuming is just some unintuitively-designed expected behavior, javac doesn't complain about being fed a blank file!
Here's exactly what happened:
Create the file
Write the buggy code but don't save the file
Attempt to compile the code and hit the issue described in my question
Correct the bug in the code and save the file
Compile and run the code without a problem

G-WAN: adding .jar application to CLASSPATH: "try catch not catching exception"

I'm trying to use to G-WAN webserver. So I added a ".jar" application to CLASSPATH in order to call it from java servlet.
The code is running, but it is unable to catch the exception, and the application crashes.
Below you can find the output:
'import site' failed; use -v for traceback
ptrace: Operation not permitted.
No frame selected.
Signal : 11:Address not mapped to object
Signal src : 1:.
errno : 0
Thread : 2
Code Pointer: 7f22eda66ac7 module:libjvm.so function:Arena::set_size_in_bytes(unsigned long) line:0
Access Address: 000000000020
Can you confirm if G-WAN Java examples were running fine in the first place (even with exception handling)?
If so, your loaded .jar is the place to start with - or maybe the way the JVM loaded it from G-WAN's servlet.
That's clearly a JVM class loader issue but investigating it would require using your exact same .jar and settings, and digging into JVM internals.

Java - Solving WindowPeer warning

When I compile my below java code,
Window w = c instanceof Window ? (Window) c : SwingUtilities.getWindowAncestor(c);
WindowPeer peer = (WindowPeer) w.getPeer();
I'm getting below warning message:
warning: WindowPeer is internal proprietary API and may be removed in a future release
Any idea how to solve this issue?
I'm using JDK 1.6 and I tried 1.7 also.
Here are two ways to suppress the warning.
Suppressing the warning is not recommended, though, and the warning message text tells you why.
Approach #1 (the simplest) is to run
javac -XDignore.symbol.file ...
which will compile your program against Sun's internal rt.jar rather than the public-facing symbol file ct.sym.
Approach #2a is to run
javac -XDenableSunApiLintControl -Xlint:-sunapi ...
This still issues a "note" but not a warning.
Approach #2b is to suppress the warning and the note by writing
#SuppressWarnings("sunapi")
in the source code, but this still requires you to run javac as follows:
javac -XDenableSunApiLintControl ...

Java Attach API: changing java.library.path dynamically

When using the com.sun.tools.attach API on my Windows machine, I get the following error when making a call to
VirtualMachine.list()
java.lang.UnsatisfiedLinkError: no attach in java.library.path
The reason is the missing attach.dll. The attach.dll is located in $JRE/bin/. When starting my Java program with -Djava.library.path=[Directory to the attach.dll] everything works out without error output.
Now, I don't want to add every Java program start this ugly JVM parameter. Therefore my questions are:
Is my machine not configured right and the $JRE/bin/ should be in the library path anyway?
If not, how can I add the path dynamically? System.setProperties("java.library.path",StringOfThePathToTheAttach.dll); does not work out. The library path is changed, but the error apperas anyway. Has this something to do with SecurityManager or JVM start up?
Just found a link that might answer your question
"The java.library.path is read only once when the JVM starts up. If you change this property using System.setProperty, it won't make any difference."
http://fahdshariff.blogspot.jp/2011/08/changing-java-library-path-at-runtime.html
Your System.setProperty("java.library.path", StringOfThePathToTheAttach.dll); should work. My guess is that you're calling it too late. In other words, there is an attempt to access the DLL prior to you setting the property.
Can you output the current value for java.library.path after the property is set in code and again before the offending method call?
i.e. If you see "Before attach.dll call" output prior to seeing "After setting property", you know where your problem is.
Edit:
A better way to point to native libraries is to use System.load(StringOfThePathToTheAttach.dll) - again, before the offending line of code.
System.setProperty("java.library.path", System.getProperty("java.library.path") + File.pathSeparator + FOLDER_THAT_CONTAINS_ATTACH_DLL);

Categories

Resources