我正在开发一个在运行时生成和编译类的应用程序。这有时会产生大量生成的代码。
对于我们的一个测试用例,我从JVM收到错误:
TestClass.java:83865: too many constants
就是这样。我已经看到有关类似错误的其他报告,但在这些情况下,错误消息抱怨常量池。但在这种情况下它没有。
如果这意味着达到了JVM常量池的限制,那意味着什么?我的意思是,在Java代码方面,这些常量是什么?班级方法?场?文字?我没有静态或最终方法也没有字段。
你能给我一些线索吗?
编辑:
将代码拆分为多个类已经在进度中。虽然不是出于这个原因。
我知道恒定池的限制,我的怀疑正是进入的。生成的代码没有超过10000个方法+字段。
我怀疑的是文字是否也会进入常数池,因为这是我看到将这个数字提高到65K的唯一原因。看来是这样。
答案 0 :(得分:10)
http://en.wikipedia.org/wiki/Java_class_file#The_constant_pool
常量池包括数字,字符串,方法名称,字段名称,类名,类和方法的引用......基本上都是。
最多可以有65536个。
答案 1 :(得分:2)
Section 5.1 of the JVM spec确切地定义了常量池的构成(主要是对类/方法和文字的引用)。
答案 2 :(得分:2)
来自:JVM Spec
你可以看到classfile.constant_pool_count
有'u2'类型,将其限制为65535个条目
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
答案 3 :(得分:0)
我不知道这是否非常相关,但对于数组常量,每个字段都会计入其中。 我不太清楚为什么(我的猜测是你实际上没有给出文字,因此运行时必须手动输入每个值,因此需要它们都是常量),但它&#39就像那样,那就是它的样子。
当我将大缓存生成为数组文字时,我发现了这个问题。 由于我不想手工写出1 000 000个常数,我写了一个小程序来为我编写程序。我想看一下从启动时缓存所有内容时程序的速度有多快。
(问题是1.6.1来自"编程挑战" Skiela和Revilla,ISBN 0-387-00163-8)
所以你可能在文字的某个地方有一些数组。这不算作一个常数。它被算作array.length常量。或者array.length + 1个常量。