11

我正在开发一个在运行时生成和编译类的应用程序。这有时会产生大量的生成代码。

对于我们的一个测试用例,我从 JVM 收到一个错误:

TestClass.java:83865: too many constants

只是这个。我看过其他关于类似错误的报告,但在这些情况下,错误消息会抱怨常量池。但在这种情况下,它没有。

如果这意味着达到了 JVM 的常量池的限制,那是什么意思?我的意思是,就 Java 代码而言,这些常量是什么类型的?类方法?领域?字面意思?我没有静态或最终方法,也没有字段。

你能给我一些线索吗?

编辑:

将代码拆分为多个类已经在计划中。虽然不是因为这个确切的原因。

我知道常量池的限制,我的疑问正是其中的内容。生成的代码没有超过 10000 个方法+字段。

我怀疑文字是否也进入常量池,因为这是我看到将此数字提高到 65K 的唯一原因。似乎是这样。

4

4 回答 4

10

http://en.wikipedia.org/wiki/Java_class_file#The_constant_pool

常量池包括数字、字符串、方法名、字段名、类名、对类和方法的引用……基本上一切。

最多可以有 65536 个。

于 2012-07-11T17:18:35.227 回答
2

来自:JVM 规范

您可以看到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];
}
于 2012-07-11T17:27:01.133 回答
2

JVM 规范的第 5.1 节准确定义了常量池的构成(主要是对类/方法和文字的引用)。

于 2012-07-11T17:20:12.540 回答
2

我不知道这是否非常相关,但对于数组常量,每个字段都计入它。我不太确定为什么(我的猜测是你实际上并没有给出文字,因此运行时必须手动输入每个值,因此需要它们都是常量),但就是这样,那就是它是这样的。

当我生成一个大缓存作为数组文字时,我发现了这个问题。由于我不想手动写出 1 000 000 个常量,所以我写了一个小程序来为我编写程序。我想看看从启动开始缓存所有内容时程序的速度。

(有问题的问题是 Skiela 和 Revilla 的“编程挑战”中的 1.6.1,ISBN 0-387-00163-8)

所以你可能在某个地方有一些带有文字的数组。这不算作 ONE 常数。它被视为 array.length 常量。或 array.length + 1 个常量。

于 2016-11-06T16:44:44.400 回答