To put all already mentioned pieces together.
As @Joachim Sauer already said there is a limit for the byte code length of a method. see JLS 4.9.1.
The value of the code_length item must be less than 65536.
Assume a enum as
public enum FooEnum {
NAME_1("1"),
NAME_2("2"),
...
NAME_2442("2442");
private final String value;
FooEnum(String enumValue) {
this.value = enumValue;
}
public String getValue() {
return value;
}
}
Using JDK 8 the generated static initializer would be
static {};
Code:
0: new #4 // class FooEnum
3: dup
4: ldc #8 // String NAME_1
6: iconst_0
7: ldc #9 // String 1
9: invokespecial #10 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
12: putstatic #11 // Field NAME_1:LFooEnum;
...
65499: dup
65500: sipush 2441
65503: getstatic #7334 // Field NAME_2442:LFooEnum;
65506: aastore
65507: putstatic #1 // Field $VALUES:[LFooEnum;
65510: return
declaring enum NAME_2443
would create another 37 bytecodes which then would lead to the compilation error code to large
.
As @Till Brychcy said the Eclipse compiler works around the size limit by generating additional methods, which are invoked in the static initializer.
The static initializer is generated as
static {};
Code:
0: invokestatic #2455 // Method " enum constant initialization$2":()V
3: invokestatic #2458 // Method " enum constant initialization$3":()V
6: sipush 2442
9: anewarray #1 // class FooEnum
12: dup
13: iconst_0
14: getstatic #2461 // Field NAME_1:LFooEnum;
17: aastore
...
the methods enum constant initialization$2
and enum constant initialization$3
initialize a enums NAME_1 till NAME_2000
respective NAME_2001 till NAME_2442
.
To try out yourself create following two files
gen.sh
#!/bin/bash
mkdir -p src/main/java/
rm FooEnum.jdk FooEnum.ecj
(
echo "public enum FooEnum {"
number_of_enums=2442
i=1
while [ $i -lt $number_of_enums ]
do
echo " NAME_${i}(\"${i}\"),"
i=$((i+1))
done
echo " NAME_${i}(\"${i}\");"
cat <<EOF
private final String value;
FooEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
EOF
) > src/main/java/FooEnum.java
mvn clean compile
javap -c -v -p target/classes/FooEnum.class > FooEnum.jdk
mvn clean compile -P ecj
javap -c -v -p target/classes/FooEnum.class > FooEnum.ecj
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sub.optimal</groupId>
<artifactId>ejc-demo</artifactId>
<version>1.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--<maven.compiler.source>1.8</maven.compiler.source>-->
<!--<maven.compiler.target>1.8</maven.compiler.target>-->
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>ecj</id>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<compilerId>eclipse</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.8.4</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>jdk9</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>9</source>
<target>9</target>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
running the script gen.sh
will generate the enum source file FooEnum.java
and then compile it at first with your current JDK and second using the Eclipse compiler for Java. After each compilation the class is disassembled and the disassembled bytecode is stored in file FooEnum.jdk
and FooEnum.ecj
. For your further investigation.