Ich habe eine sehr einfache AufzählungSchalter bewirkt NoClassDefFoundError in tomcat mit undefinierten inneren Klassen
my.package.data.util
public enum Mode
{
SQLEXPORT, PREVIEW, PRINT
}
, die in einer anderen Klasse als Aufzählungen verwendet wird, soll
verwendet werdenmy.package.program.ComponentController
switch (_mode) { // line 278, _mode is of type my.package.data.util.Mode
case PREVIEW:
// Do thing for preview
break;
case SQLEXPORT:
// Do thing for SQL
break;
case PRINT:
// Do thing for print
break;
default:
throw new IllegalArgumentException();
}
Diese beiden Klassen befinden sich im selben Projekt und sind in eine Datei jar
kompiliert.
Ein Webprojekt verwendet dann diese Bibliothek (in den Ordner WEB-INF/lib
platziert). Aber, wenn die Zeit kommt diese Bibliothek zu verwenden, genauer gesagt, dass Schalter, ein NoClassDefFoundError
auftritt:
NoClassDefFoundError: my/package/program/ComponentController$1
at my.package.program.ComponentController.doCall(ComponentController.java:278)
Dies ist etwas, was ich kann nicht auf mehreren Ebenen verstehen:
- Warum Java versucht, einen laden innere Klasse (wie sichtbar durch die
$1
). Es gibt keine innere Klasse inComponentController
und war es nie. - Warum Java wird der Schalter mit dieser internen Klasse als Argument thinkgs
- Wo die
my.package.data.util.Mode
Klasse verschwunden
Was hier geschieht?
Weitere Informationen nicht in der ursprünglichen Frage
ComponentController
erstreckt sich eine andere Klasse,SessionBuilder
. Diese Klasse hat auch keine inneren Klassen
ich die ComponentController
mit javap
dekompilierten und versuchte interessante Dinge in dem resultierenden Byte-Code zu finden.
Es scheint, dass es in der Tat eine innere Klasse in dem Byte-Code:
public class my.package.program.ComponentController extends my.other.package.SessionBuilder
SourceFile: "ComponentController.java"
InnerClasses:
statiC#192 of #2; //class my/package/program/ComponentController$1 of class my/package/program/ComponentController
Diese Klasse wird verwendet, wenn my.package.data.util.Mode
verwiesen wird:
#192 = Class #486 // my/package/program/ComponentController$1
#193 = Utf8
#194 = Utf8 InnerClasses
#195 = Utf8 _mode
#196 = Utf8 Lmy/package/data/util/Mode;
Und auch, wenn der Schalter tatsächlich auftritt:
183: getstatic #102 // Field my/package/program/ComponentController$1.$SwitchMap$my$package$data$util$Mode:[I
186: aload_0
187: getfield #5 // Field _mode:Lmy/package/data/util/Mode;
190: invokevirtual #103 // Method my/package/data/util/Mode.ordinal:()I
193: iaload
194: tableswitch { // 1 to 3
1: 220
2: 335
3: 440
default: 516
}
Weitere Untersuchungen in die von Rich-verknüpfte Fragen produzierten etwas Interessantes: Die eingebauten jar
aus dem Bibliothek-Projekt in der lokalen tomcat Installation unterscheiden und die eine verwendet, um die jar
für den Produktionsserver zu produzieren:
Links: Glas in WEB-INF/lib
über lokale tomcat von eclipse, Rechts: jar
als
Es ist nun von eclipse verwendet Build-Prozess von ANT gebaut scheint, wie die, wenn sie einem lokalen tomcat d Veröffentlichung iffers aus welchem ANT tut (was AFAIK nur einen einfachen javac
Anruf)
Okay, jetzt habe ich nur die von ANT in die lokalen tomcats erstellt jar
kopiert WEB-INF/lib
und alles funktioniert. Das bedeutet natürlich, dass ich nach jeder Änderung im Bibliotheksprojekt das neue jar
manuell in meine Tomcat-Lib kopieren muss.
Ich habe dies als Fehlerbericht bei Eclipse eingereicht und werde mit allen Nachrichten melden.
Wie haben Sie die Tatsache verlinkt, dass dieser Fehler auf diesen Schalter zurückzuführen ist? Ich denke, der Punkt des Interesses an Code, der in Ihrer Frage fehlt, ist die Zeile 278 Ihrer ComponentController-Datei. – benzonico
Weil Zeile 278 'switch (_mode)' ist, werde ich diese Information dem Code in der Frage hinzufügen –
Haben Sie versucht, die .jar zu dekompilieren, um zu sehen, was javac getan hat? Es hört sich an, als hätte Javac das Enum interniert - ist es der einzige Ort, an dem es benutzt wird? – Rich