开发者

When does a dynamically loaded class that references a non-existent classes/methods fail in Java?

Suppose I dynamically load a Java class C, that references non-existent class/开发者_运维技巧methods. Such a case might occur when C was written for a newer version of Java. When will it fail - as soon as C is loaded, or when a method that calls a non-existent class/method is run? Does this change with the VM - including other versions of Java, such as Java ME?


When will it fail?

as soon as C is loaded?

No. Only if when loaded it makes reference to the non existing class ( ie. you have a class attribute of that type )

or when a method that calls a non-existant class/method is run?

Yes. This will be the case.

For instance this runs well.

C:\>more > A.java
class A {}
^C
C:\>more > B.java
class B {
   public void method() {
      A a = new A();
    }
    public void other() {
       System.out.println("Hello there");
    }
    public static void main( String ... args ) {
        B b = new B();
        b.other();
    }
}

C:\>javac A.java B.java

C:\>erase A.class

C:\>java B
Hello there

The class B is loaded by java but since none of the code used method it works well.

As opposed to:

C:\>more > A.java
class A {}

C:\>more > B.java
class B {
   void method() {
      A a = new A();
   }
   public static void main( String ... args ) {
       B b = new B();
       b.method();
   }
}
^C
C:\>javac A.java B.java

C:\>erase A.class

C:\>java B
Exception in thread "main" java.lang.NoClassDefFoundError: A
        at B.method(B.java:3)
        at B.main(B.java:7)
Caused by: java.lang.ClassNotFoundException: A
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 2 more

Fails because B attempted to access A.


On at least regular old Java, I've found that it will fail at the moment where you reference the broken class or method:

Example from my own recent history:

I use a Java editor (written in Java) with a simple plugin system. I had updated the editor, but was using a plugin, compiled with the old version of the editor, that still referenced a class, where for brevity we'll call Foo, that was moved out from being an inner class and into a package by itself.

When I called the plugin, it did not fail until it tried to create an instance of Foo. Since Foo was not in the place the plugin's code said it would be, it threw a NoClassDefFoundError.

On a side note, between at least Java versions like Java 1.5 and Java 1.6, you usually don't have to worry about them removing or moving something, since people will scream bloody murder if you mess with an established API.


This step is called "resolution", loading other classes referenced by this class.

The language spec allows variation on when this step is performed. It can be done most eagerly, at the beginning of VM, recursively resolving all classess referenced directly and indirectly from the main class. Or it can be done most lazily, resolving a class only when absolutely necessary.

My experience with server JVMs is that it's done as late as possible. So as long as no code referencing the missing classes has been executed, no error is seen.

It also depends on how your load your class. java.lang.Classloader.loadClass(name) does not do resolution. However there is a protected method loadClass(name,resolve) which you may use to force resolution at loading time. However its exact behavior isn't well documented.


It will fail to load. This can actually be pretty annoying - but of course it's not enough to be careful. The way to work around this is to dynamically load different classes depending on what other definitions you know are available.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜