Re: How do you get full class name (including package) as a string?
According to Jim Janney <jjanney@shell.xmission.com>:
You're right. Compiling with Java 6 I see a single ldc instruction.
Actually Sun's compiler compiled 'Foo.class' to a single ldc instruction
much before the JVM specification was amended to make that usage legal
(this was an obvious specification oversight).
At the same time, the Jikes compiler (from IBM) was trying to closely
follow the JVM specification as published, and as such resorted to a
rather indirect method for obtaining the Class instance without
initializing the class itself. Basically, for the following class:
public class Bar {
public static void main(String[] args)
{
Class c = Foo.class;
System.out.println(c.getName());
}
}
jikes will add a hidden static method to class Bar, the method being
named "class" (like the keyword -- not a problem for the JVM), and
the bytecode will look like this:
**** main (java.lang.String[]) -> void
0: getstatic Bar.class$Foo {java.lang.Class}
3: dup
4: ifnonnull #18
7: pop
8: ldc<String> "[LFoo;"
10: iconst 0
11: invokestatic Bar.class {(java.lang.String, boolean) -> java.lang.Class}
14: dup
15: putstatic Bar.class$Foo {java.lang.Class}
18: astore $1
19: getstatic java/lang/System.out {java.io.PrintStream}
22: aload $1
23: invokevirtual java/lang/Class.getName {() -> java.lang.String}
26: invokevirtual java/io/PrintStream.println {(java.lang.String) -> void}
29: return
**** class (java.lang.String, boolean) -> java.lang.Class
exception table:
0 12 12 java/lang/ClassNotFoundException
0: aload $0
1: invokestatic java/lang/Class.forName {(java.lang.String) -> java.lang.Class}
4: iload $1
5: ifne #11
8: invokevirtual java/lang/Class.getComponentType {() -> java.lang.Class}
11: areturn
12: new java/lang/NoClassDefFoundError
15: dup_x1
16: invokespecial java/lang/NoClassDefFoundError.<init> {() -> void}
19: invokevirtual java/lang/Throwable.initCause {(java.lang.Throwable) -> java.lang.Throwable}
22: athrow
I.e. the code uses Class.forName() to locate not the class Foo, but the
class of "an array of Foo"; this implies loading the Foo class without
intialiazing it, which is precisely what jikes wishes to achieve.
This idiom is convoluted, but it has the benefit of being compatible
with both Java 1.1 and J2ME, both of which being targets for jikes
(Class.forName(String, boolean, ClassLoader) appeared in Java 1.2, and
is not part of J2ME). Note also that the last version of jikes seems
to have been published in 2005, and knows nothing of Java 5.
--Thomas Pornin