Ich habe eine ziemlich komplexe Java-Software, die dynamisch eine Klasse laden, ein Objekt erstellen und eine seiner Methoden aufrufen muss. Es stellt sich heraus, dass dies in einigen Situationen eine NoClassDefFoundError
(verursacht durch eine ClassNotFoundException
) verursacht, wenn die geladene Klasse eine andere verweist.Warum funktioniert dieser URLClassLoader manchmal und manchmal nicht?
Sagen wir:
public interface Go {
void go();
}
Sagen Sie, dass die Klasse geladen werden:
package foo;
import static baz.Baz.BAZ;
public class Foo implements Go {
@Override
void go() {
...
something = BAZ;
...
}
}
wo diese Art und Weise wird
package baz;
public class Baz {
public static final int BAZ = 111;
...
}
Sagen Sie, dass die Klasse geladen:
try (final URLClassLoader loader = new URLClassLoader(new URL[] { url })) {
final Class<? extends Foo> clazz =
loader.loadClass("foo.Foo").asSubclass(Go.class);
this.obj = clazz.newInstance();
this.obj.go();
} catch ...
Dann funktioniert alles. Sagen Sie, dass Sie stattdessen Dinge diese andere Art und Weise zu tun:
try (final URLClassLoader loader = new URLClassLoader(new URL[] { url })) {
final Class<? extends Foo> clazz =
loader.loadClass("foo.Foo").asSubclass(Go.class);
this.obj = clazz.newInstance();
//we do not invoke go() now...
} catch ...
//later, in another method...
this.obj.go();
nun der Aufruf von go()
wirft ein NoClassDefFoundError
, beschwert es nicht baz.Baz
laden kann. Natürlich ist die URL die gleiche. Natürlich befinden sich sowohl foo.Foo
als auch baz.Baz
in dem Pfad, der durch url
angegeben ist. Der einzige Unterschied, den ich sehen kann, ist der Moment, wenn die Methode go()
aufgerufen wird.
Was ist hier falsch?
Es fehlen Informationen: Welches Paket ist Go in? Wie wird die URL an den URLClassloader übergeben? Und akzeptiert der Compiler das Laden von Foo als Unterklasse Go und dann Zuweisen von ''? erstreckt sich Foo'''? –