I have a very simple enumeration
my.package.data.util
public enum Mode
{
SQLEXPORT, PREVIEW, PRINT
}
Which is used in another class as enums should be used
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();
}
These two classes are in the same project and are compiled into a jar
file.
A web project is then using this library (placed into the WEB-INF/lib
folder). But, when the time comes to use this library, and most specifically that switch, a NoClassDefFoundError
occurs:
NoClassDefFoundError: my/package/program/ComponentController$1
at my.package.program.ComponentController.doCall(ComponentController.java:278)
This is something I cannot understand on several levels:
$1
). There is no inner class present in ComponentController
, and never has been.my.package.data.util.Mode
class vanishedWhat is happening here?
Further information not in the original question
ComponentController
extends another class, SessionBuilder
. This class also has no inner classesI decompiled the ComponentController
using javap
and tried to find interesting things in the resulting byte code.
It appears that there is indeed an inner class in the 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
This class is used whenever my.package.data.util.Mode
is referenced:
#192 = Class #486 // my/package/program/ComponentController$1
#193 = Utf8
#194 = Utf8 InnerClasses
#195 = Utf8 _mode
#196 = Utf8 Lmy/package/data/util/Mode;
And also, when the switch actually occurs:
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
}
Further investigation into the questions linked by Rich produced something interesting: The built jar
from the library project differ in the local tomcat installation and the one used to produce the jar
for the production server:
Left: jar in WEB-INF/lib
via local tomcat by eclipse, Right: jar
as built by ANT
It now seems like the build process used by eclipse when publishing to a local tomcat differs from what ANT does (which is AFAIK just a simple javac
call)
Alright, now I just copied the jar
created by ANT into the local tomcats WEB-INF/lib
and everything works fine. Of course, this means that after every change in the library project, I have to manually copy the new jar
to my tomcat lib.
I filed this as a bug report at eclipse and will report back with any news.
According to this question:
...Sun's Javac 1.6 creates an additional synthetic class each time you use a switch on an Enum.
And according to this question you aren't alone.
From my experience, the problem is that this new class is not deployed by Eclipse, but it is generated in the build process.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With