Yesterday I looked at the JDK 1.5 beta that Sun released recently. There appears not to be a complete list of changes to the VM yet and the only things I found were a few new modifier bits (that haven't yet stabilized) and the fact that class literals are finally supported in the VM. This is important for IKVM.NET, because it makes class literals in statically compiled code work better and more efficient.
For a quick refresher of how class literals are currently compiled, let's look at how the following class is compiled:
class ClassLiteral { public static void main(String[] args) { System.out.println(String.class); } }
Compiling this with Jikes 1.19 and then disassembling it (I've left out the default constructor that the compiler generated):
class ClassLiteral extends java/lang/Object static java/lang/Class class$java$lang$String // Unknown attribute : Synthetic// public static main([Ljava/lang/String;)V // attrib length: 53 // max stacks: 3 // max locals: 1 // code length: 25 0 getstatic <Field java/lang/System java/io/PrintStream out> 3 getstatic <Field ClassLiteral java/lang/Class class$java$lang$String> 6 dup 7 ifnonnull 21 10 pop 11 ldc "[Ljava.lang.String;" 13 iconst_0 14 invokestatic <Method ClassLiteral class$(Ljava/lang/String;Z)Ljava/lang/Class;> 17 dup 18 putstatic <Field ClassLiteral java/lang/Class class$java$lang$String> 21 invokevirtual <Method java/io/PrintStream println(Ljava/lang/Object;)V> 24 return static class$(Ljava/lang/String;Z)Ljava/lang/Class; // Unknown attribute : Synthetic // // attrib length: 55 // max stacks: 3 // max locals: 4 // code length: 23 0 aload_0 1 invokestatic <Method java/lang/Class forName(Ljava/lang/String;)Ljava/lang /Class;> 4 iload_1 5 ifne 11 8 invokevirtual <Method java/lang/Class getComponentType()Ljava/lang/Class;> 11 areturn 12 new java/lang/NoClassDefFoundError 15 dup_x1 16 invokespecial <Method java/lang/NoClassDefFoundError <init>()V> 19 invokevirtual <Method java/lang/Throwable initCause(Ljava/lang/Throwable;) Ljava/lang/Throwable;> 22 athrow Exception table: start_pc = 0 end_pc = 12 handler_pc = 12 catch_type = java/lang/ClassNotFoundException
The amount of code generated is pretty bizarre. Note that this isn't Jikes' fault, there just isn't a way to do it better. Now, here is what it looks like compiled with javac from the 1.5 beta (specifying the -target 1.5 option):
class ClassLiteral extends java/lang/Object public static main([Ljava/lang/String;)V // attrib length: 38 // max stacks: 2 // max locals: 1 // code length: 10 0 getstatic <Field java/lang/System java/io/PrintStream out> 3 ldc_w java/lang/String 6 invokevirtual <Method java/io/PrintStream println(Ljava/lang/Object;)V> 9 return
This looks a lot better! No new bytecode instruction was added, instead the ldc instruction was modified to allow referencing a CONSTANT_Class_info . When the VM encounters this it loads the class and pushes the class object on the stack. I added support for this to IKVM.NET (not in cvs yet) in about 15 minutes. When JDK 1.1 was released (the first version to support class literals in the source), I wondered why they didn't add VM support at the same time, but fortunately they finally got around to it.
CONSTANT_Class_info
Trivia
If you looked closely at the Jikes generated code, you may have noticed that Jikes actually loads the string array class ("[Ljava.lang.String;") instead of java.lang.String. Why does it do this? It does this, because it correctly implements the JLS. The JLS says that class literals should not cause a class to be initialized. Doing a Class.forName() initializes the class, but when you initialize an array class you don't initialize the component type class. So this is a clever trick. Javac doesn't do this, so it (incorrectly) causes the class to be initialized.
IKVM.NET
Why does this change help statically compiled code in IKVM.NET? Performance is a bit better, but that's not the most important difference. The real benefit shows up when you statically compile code into multiple assemblies. If one assembly references a class in another assembly via a class literal, you'd better be sure that the referenced assembly is already loaded in the AppDomain, otherwise the IKVM.NET runtime is unable to find the class. In the new (JDK 1.5) way of references class literals, it is no longer opaque to ikvmc, so it can now compile the construct in such a way that the class literal causes the appropriate assembly to be loaded by the .NET runtime when it is executed.
StringBuilder
Something that struck me a funny is the new StringBuilder class that JDK 1.5 includes. It's almost identical to StringBuffer, except that it is not thread safe. If you look at the Rotor source code, you can see that the .NET StringBuilder also started life as StringBuffer. Now if the next version of .NET includes a thread safe version of StringBuilder and name it StringBuffer, we've come full circle
Remember Me
I apologize for the lameness of this, but the comment spam was driving me nuts. In order to be able to post a comment, you need to answer a simple question. Hopefully this question is easy enough not to annoy serious commenters, but hard enough to keep the spammers away.
Anti-Spam Question: What method on java.lang.System returns an object's original hashcode (i.e. the one that would be returned by java.lang.Object.hashCode() if it wasn't overridden)? (case is significant)
Powered by: newtelligence dasBlog 2.3.12105.0
© Copyright 2019, Jeroen Frijters
E-mail