India made 203. England all out for 164!. I really don't know what to say about this match... I like that 434/438 match better!!
I've just read Language wars are so boring and from there went to read Scripting flamewar. Some thoughts on scripting in Java "context"....
For scripting languages for the Java platform - assuming the language allows access to Java classes, then in effect the "primitives" space of the language becomes the entire JDK - the endless primitive extension problem is left to the JDK. For example, JavaScript engine in JRE (included in Mustang) lives in the "context" of Java - Java classes can be accessed and Java interfaces can be implemented in script.
Some of the performance issues around scripting may possibly be addressed by "compiling" scripts to bytecode on-the-fly (a sort of first level "hotspot" for scripts?). That is where invokedynamic or any other possible improvements from JSR 292 could help. The typing/non-typing "dichotomy" may possibly be addressed by pluggable types.
Like many in India, I do like (that is an understatement!) cricket. All too familiar, yet another Indian team seconding innings collapse today
. But, I think England deserved to win this match.
This is continuation of my earlier post.
At runtime, a Java class is uniquely identified by the pair: fully qualifed name and defining loader instance. We denote a class by
<qualified-class-name, defining-loader>
Examples:
<java.lang.Object, null>
<com.acme.MyAppClass, sun.misc.Launcher$AppClassLoader@768812>
When JVM uses a loader Li as initiating loader to load class C, we denote it by
CLi
With both initiating loader Li and defining loader Ld, we denote
<C, Ld>Li
Examples:
<java.awt.Frame, null>sun.misc.Launcher$AppClassLoader@768812&
<com.acme.AppUtil, sun.misc.Launcher$AppClassLoader@768812>sun.misc.Launcher$AppClassLoader@768812&
First one denotes the class with name "java.awt.Frame" defined by null (bootstrap loader). JVM initiated
loading using the application class loader. Second one denotes the class with the name
"com.acme.AppUtil" defined by application class loader and JVM initiated loading using
the application loader itself.
class A {
void func(B b) {
T t = b.f;
// operate on "t"
}
}
class B {
public T f;
}
During compilation, javac verifies that B has a field "f" of same type "T" (or subtype of "T"). Here, "same type" during compilation just means the same fully qualified class name. At runtime, if both A and B are loaded (i.e, defined) by the same class loader, say L, then we have no problem. JVM would use the same class loader "L" as initiating loader to load "T" - the field type. In other words, both class <A, L> and and class <B, L> would have same notion of type "T".
But, what if A and B are loaded (defined) by different loaders? Let us assume <A, L1> and <B, L2> and L1 != L2. In this case, to resolve type "T" from <A, L1>, JVM will use L1 as initiating loader. To resolve type "T" from <B, L2>, JVM will use L2 as initiating loader. Unless care is taken, these two loadClass calls could result in two different classes -- and hence assumption of type equality made during compilation would break! One quick and dirty solution would be this: whenever field is resolved at runtime force class loading for "T" by both L1 and L2 and check equality. But, that means we are leaving lazy loading behind - we are forcing early loading!
Instead of this solution, JVM takes another solution: impose loader constraints.
Now consider case (2) above. Class "A" refers to a method of class "B". Let us say A refers to the method of the following form
class B {
R foo(A1 a1, A2 a2,... An an);
}
class A {
void func(B b) {
b.foo(/* args here */);
}
}
and assume that all Ai=1, n are reference types and R (return type) is also a reference type. Again, during compilation javac would have verified that method "foo" of correct signature exists in class "B". Now again assume class A and B are defined two different loaders L1, L2. While linking this method "foo", JVM would impose the following loader constraints:
Again these constraints are not verified immediately. These are just recorded in an internal data structure. JVM would verify these constraints at subsequent class load attempts.
There is one more case we have ignored so far: class B extends A and overrides method "foo". Again, overriding method B.foo is subsitutable everywhere A.foo can be called (the subtype subsititution).
class A {
R foo(A1 a1, A2 a2... An an) {}
}
class B extends A {
@Override R foo(A1 a1, A2 a2... An an) {}
}
If A and B are defined by two different loaders L1 and L2, then JVM imposes the following
loader constraints at the time of preparation of B.
If all of the above sounds too abstract to you, then let us consider a concrete problem - a bug we faced in a web container. Webcontainers support "application reloading" without restarting of the webserver. A webcontainer used classloaders for application reloading. The container used a different class loader to reload an application. For example, if one of .jsp files of the webapp is modified (detected by filesystem timestamp), then the webcontainer would recompile that particular .jsp and reload the app using a different class loader instance. So far so good - everything worked as expected. But then, someone thought it may not be optimal to load all classes of the webapp just because one particular class - the class corresponding to the modifed jsp - changed. So, he optimized by the following change:
<!-- foo.jsp file fragment -- >
<--newly added part of JSP -->
<%!
class Util {
public void func() {}
}
%>
<%!Util u = new Util();%>
Then, he attempted to "reload" the webapp! He hit the infamous "loader constraint violation"
at the line where "new Util()" is executed! Why? The JSP file is compiled as a Servlet class,
say "FooServlet.class". And his "Util" class became inner class of FooServlet. javac
passes outer instance to inner class constructor. This is how instance variables of
outer class are made accessible from inner class instance.
There are many improvements in Mustang (Java SE 6)'s DTrace support. A recent improvement: Starting from Mustang build 75, DTrace jstack() action prints Java stack trace with method signatures. Because Java methods are overloaded by argument types, it is very useful to view method signatures as part of stack trace output. With this change, the stack trace would look like:
pollsys:entry
libc.so.1`__pollsys+0x4
libc.so.1`poll+0x7c
libjvm.so`__1cIos_sleep6Fxb_i_+0xa28
libjvm.so`__1cCosFsleep6FpnGThread_xb_i_+0x1f0
libjvm.so`JVM_Sleep+0x518
java/lang/Thread.sleep(J)V
java/lang/Thread.sleep(J)V
t.main([Ljava/lang/String;)V
[....]
instead of this:
pollsys:entry
libc.so.1`__pollsys+0x4
libc.so.1`poll+0x7c
libjvm.so`__1cIos_sleep6Fxb_i_+0x8d4
libjvm.so`__1cCosFsleep6FpnGThread_xb_i_+0x204
libjvm.so`JVM_Sleep+0x534
java/lang/Thread.sleep
java/lang/Thread.sleep
t.main
[....]
Are you thinking of writing ClassLoaders? or are you facing "unexpected" ClassCastException or LinkageError with wierd message "loader constraint violation". Then, it is time to take a closer look at Java class loading process.
A Java class is loaded by an instance of java.lang.ClassLoader class. java.lang.ClassLoader itself is an abstract class and so a class loader can only an instance of a concrete subclass of java.lang.ClassLoader. If this is the case, which class loader loads java.lang.ClassLoader class itself? (classic "who will load the loader" bootstrap issue). It turns out that there is a bootstrap class loader built into the JVM. The bootstrap loader loads java.lang.ClassLoader and many other Java platform classes.
To load a specific Java class, say for example com.acme.Foo, JVM invokes loadClass method of a java.lang.ClassLoader (actually, JVM looks for loadClassInternal method - if found it uses that method, or else JVM uses loadClass. And loadClassInternal method calls loadClass). loadClass receives name of the class to load and returns java.lang.Class instance that represent the loaded class. Actually, loadClass method finds the actual bytes of .class file (or URL) and calls defineClass method to construct java.lang.Class out of the byte array. Loader on which loadClass is called is referred as initiating loader (i.e., JVM initiates loading using that loader). But, the initiating loader need not directly find the byte[] for class - instead it may delegate the class loading to another class loader (for example, to it's parent loader) - which itself may delegate to another loader and so on. Eventually some class loader object in delegation chain ends up calling defineClass method to actually load the concerned class (com.acme.Foo). That particular loader is called defining loader of com.acme.Foo. At runtime, a Java class is uniquely identified by the pair - the fully qualified name of the class and the defining loader that loaded it. If the same named (i.e., same fully qualified name) class is defined by two different loaders, these classes are different - even if the .class bytes are same and loaded from the same location (URL).
Even with a good old simple "hello world" Java program, there are atleast 3 class loaders.
Let us assume you are running a "hello world" java program. We will how class loading proceeds. JVM loads main class using the "application class loader". If you run the following program
class Main {
public static void main(String[] args) {
System.out.println(Main.class.getClassLoader());
javax.swing.JFrame f = new javax.swing.JFrame();
f.setVisible(true);
SomeAppClass s = new SomeAppClass();
}
}
it prints something like
sun.misc.Launcher$AppClassLoader@17943a4
Whenever a reference to some other class has to be resolved from Main class, then JVM uses the defining loader of Main class - the application class loader - as initiating loader. In the above example, to load the class javax.swing.JFrame, JVM will use the application class loader as initiating loader. i.e., JVM will call loadClass() (loadClassInternal) on the application class loader. The application class loader delegates that to extension class loader. And the extension class loader checks whether it is a bootstrap class (using a private method - ClassLoader.findBootstrapClass) and the bootstrap loader defines the class by loading it from rt.jar. When reference to SomeAppClass has to be resolved, JVM follows the same process - it uses application class loader as initiating loader for it. The application loader delegates it to extension loader. Extension loader checks with bootstrap loader. Bootstrap loader won't find "SomeAppClass". Then extension loader checks whether "SomeAppClass" is in any of the extension jars and it won't find any. Then application class loader check the .class bytes in application CLASSPATH. If it finds, it defines the same. If not, NoClassDefFoundError will be thrown.
Stay tuned for more discussion on loader constraints and LinkageErrors..
To be continued...
Few errors are so common (Frequently Faced Errors or FFEs?) - asked many times in forums, email lists (internal/external) - and it is frustating to face one of these "starting problems". I am talking about the classloading errors with Java. I'll try to list few common errors and most probable reasons.
Error occurred during initialization of VM java/lang/NoClassDefFoundError: java/lang/ObjectTwo possible reasons:
Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version number in .class file (or) Unsupported major.minor version 49.0Reason: You are trying to run a class compiled with newer version of JDK. For example, you have compiled the class with JDK 5.0 and try to run on JDK 1.4.2. Class file major/minor version evolves with major JDK releases. Each JDK version supports only upto a specific class file major.minor version.
Exception in thread "main" java.lang.NoClassDefFoundError: tmp/t (wrong name: t)Reason: The class name as in .class file is different from what is specified in command line. In the above error scenario, the .class file has the name "t" (in unnamed global package) but user attempted to load it as "tmp.t" (t in tmp package). You have to check package declaration in your source files and confirm that the files are under proper subdirectories (use javac's -d option to put .class files under correct subdirectories). Also you may want to check directory, file name case -- remember to do this on case insensitive file systems as well. It is better to use jar files whenever possible (rather than directories)
Exception in thread "main" java.lang.NoClassDefFoundError: xThis is good (bad?) old error! It is better to check
Yes, typos are quite common