% javap -c HelloWorld Compiled from HelloWorld.java class HelloWorld extends java.lang.Object { HelloWorld(); public static void main(java.lang.String[]); } Method HelloWorld() 0 aload_0 1 invokespecial #6 >Method java.lang.Object()< 4 return Method void main(java.lang.String[]) 0 getstatic #7 >Field java.io.PrintStream out< 3 ldc #1 >String "Hello World!"< 5 invokevirtual #8 >Method void println(java.lang.String)< 8 return
Platform | |
---|---|
Solaris, Linux | |
Windows |
Binary dump of class file: dump (od -t x1 -t a HelloWorld.class).
4 bytes magic number 4 bytes minor version, major version 2 bytes count of items in constant pool constant pool array 2 bytes access flags mask 2 bytes index into the constant pool for this class 2 bytes index into the constant pool for super class 2 bytes count of direct super interfaces interface array 2 bytes count of methods methods array 2 bytes count of attributes attribute array
A bad class would not normally be formed on purpose, but it might be created malicoiusly altered. We an editor we can change the bytes and see what happens.
A properly formed class file begins with the "magic" number OxCAFEBABE in the first four bytes, has the number of bytes it says it does, all the internal arrays have the proper form, all indices are within bounds etc.
Exception in thread "main" java.lang.NoClassDefFoundError: WrongName (wrong name: HelloWorld)
Exception in thread "main" java.lang.ClassFormatError: HelloWorld (Bad magic number)
Exception in thread "main" java.lang.ClassFormatError: HelloWorld (Extra bytes at the end of the class file)
The verifier also checks:
If we modify the bytecode of HelloWorld.class in various ways and try to run it, the JVM detects it can rejects the class file.
% java -verify HelloWorld Exception in thread "main" java.lang.ClassFormatError: HelloWorld (Bad magic number) % java -verify HelloWorld Exception in thread "main" java.lang.NoClassDefFoundError: jawa/lang/Object % java -verify HelloWorld Exception in thread "main" java.lang.VerifyError: (class: HelloWorld, method: main signature: ([Ljava/lang/String;)V) Incompatible object argument for function call
You may wish to just interpret the bytecode (and not compile) when developing an application in order to get line numbers in stack traces. In this way you can find the course of exceptions easier.
% java -Djava.compiler=NONE Application C:\> java -Djava.compiler=NONE Application
% setenv JAVA_COMPILER NONE C:\> set JAVA_COMPILER=NONE
% setenv JAVA_COMPILER foo C:\> set JAVA_COMPILER=fooor
% java -Djava.compiler=foo myapp C:\> java -Djava.compiler=foo myapp
The letters lib are prepended to "foo" and an .so filename extension is added, so that the virtual machine will search for a JIT compiler named libfoo.so. The search for the alternative compiler is made in the jre/lib/sparc directory and or in the path specified by the sun.boot.library.path property, if it is set. Here is an example using of using the sun.boot.library.path property to specify an alternative JIT path (the example assumes a JIT named libfoo.so is located in directory /java):
java -Dsun.boot.libary.path=/jdk1.2.2/jre/lib/sparc:/java -Djava.compiler=foo MyApp
Under Windows the library is foo.dll.