Чтобы сложить все уже упомянутые фрагменты.
Как уже сказал @ Joachim Sauer , существует ограничение длины байтового кода метода.см. JLS 4.9.1 .
Значение элемента code_length должно быть меньше 65536.
Допустим, что перечисление равно
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;
}
}
При использовании JDK 8 сгенерированный статический инициализатор будет
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
объявление enum NAME_2443
создаст еще 37 байт-кодов, что затем приведет к ошибке компиляции code to large
.
Как сказал @ Till Brychcy , компилятор Eclipse работает вокруг ограничения размера, генерируя дополнительные методы, которые вызываются в статическом инициализаторе.
Статический инициализатор генерируется как
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
...
методы enum constant initialization$2
и enum constant initialization$3
инициализируют перечисления NAME_1 till NAME_2000
соответственно NAME_2001 till NAME_2442
.
Чтобы попробовать самостоятельно создать следующие два файла
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>
при запуске сценария gen.sh
сгенерирует исходный файл enum FooEnum.java
и затем скомпилирует его всначала с вашим текущим JDK, а затем с помощью компилятора Eclipse для Java.После каждой компиляции класс разбирается, а дизассемблированный байт-код сохраняется в файлах FooEnum.jdk
и FooEnum.ecj
.Для вашего дальнейшего расследования.