这些类型的问题来自某些初始化程序代码(通常由编译器生成)超过65536字节字节代码的事实。单个方法所包含的字节码不能超过字节数(由于类文件格式的限制)。
像这样的问题的一个常见来源是像这样的大数组:
byte someBytes = { 1, 2, 3, ..., someBigValue };这里的问题是,此类字段实际上是在生成的初始化程序(构造函数或静态初始化程序)中使用 someBigValue 赋值语句初始化的。
枚举值实际上是以类似的方式初始化的。
给定以下枚举类:
public enum Foo { ConSTANT(1); private Foo(int i) { }}我们查看的输出,
javap -v并看到以下代码块:
static {}; flags: ACC_STATIC Code: stack=5, locals=0, args_size=0 0: new#4 // class Foo 3: dup 4: ldc#7 // String ConSTANT 6: iconst_0 7: iconst_1 8: invokespecial #8 // Method "<init>":(Ljava/lang/String;II)V 11: putstatic #9 // Field CONSTANT:LFoo; 14: iconst_1 15: anewarray #4 // class Foo 18: dup 19: iconst_0 20: getstatic #9 // Field CONSTANT:LFoo; 23: aastore 24: putstatic #1 // Field $VALUES:[LFoo; 27: return如您所见,有很多字节码操作可以
CONSTANT使用正确的值进行实例化。如果您有 许多
这样的枚举值,则该静态初始化程序块的大小可能会轻易超过64k字节的代码,从而使该类不可编译。
一种可能的解决方法是通过减少参数的数量(例如,根据枚举值的索引而不是使用参数来计算传入的数量)来减小初始化代码的大小。那可能只是给您足够的摆动空间,以进一步扩展此范围。
另外,您可以尝试通过实现公共接口将枚举拆分为多个枚举。枚举可以按区域/意图/类别/ …进行分组:
public interface MessageType { int getId();}public enum ConnectionMessage implements MessageType { INIT_ConNECTION(1), LOGIN(2), LOGOUT(3), CLOSE_ConNECTION(4); // getId pre, constructor, ...}public enum FrobnicationMessage implements MessageType { FROBNICATE_FOO(5), FROBNICATE_BAR(6), DEFROB_FOO(7), DEFROB_BAR(8), ... // getId pre, constructor, ...}我假设枚举值实际上是在代码中的某个地方引用的,而不仅仅是纯值持有者,如果它们只保存值,而单个值在您的代码中并未得到不同对待,则将其替换为每个数据项实例化一次的单个类存储在中央资源中可能是最好的方法。



