2015-03-11 6 views
6

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 werden

my.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:

  1. Warum Java versucht, einen laden innere Klasse (wie sichtbar durch die $1). Es gibt keine innere Klasse in ComponentController und war es nie.
  2. Warum Java wird der Schalter mit dieser internen Klasse als Argument thinkgs
  3. Wo die my.package.data.util.Mode Klasse
  4. 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

JAR Diff

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.

+1

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

+0

Weil Zeile 278 'switch (_mode)' ist, werde ich diese Information dem Code in der Frage hinzufügen –

+0

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

Antwort

6

Nach this Frage:

...Sun's Javac 1.6 creates an additional synthetic class each time you use a switch on an Enum.

Und nach this Frage sind Sie nicht allein.

+0

Okay, ich sehe, wie das gemacht werden könnte. Dann lautet die Frage: Warum funktioniert es in meinem Fall nicht? –

0

Aus meiner Erfahrung besteht das Problem darin, dass diese neue Klasse nicht von Eclipse bereitgestellt wird, sondern im Buildprozess generiert wird.

Verwandte Themen