12

I'm developing an application that generates and compiles classes at runtime. This will sometimes create huge amounts of generated code.

With one of our test cases, I'm getting an error from the JVM:

TestClass.java:83865: too many constants

Just this. I've seen other reports about a similar error, but on those cases the error message complains about the constant pool. But in this case it doesn't.

If this means that the limit on the JVM's constant pool was reached, what does it mean? I mean, what kind of constants are these in terms of Java code? Class methods? Fields? Literals? I have no static or final methods nor fields.

Can you give me some leads?

EDIT:

Splitting the code into multiple classes is already in schedule. Although it wasn't for this exact reason.

I' aware of the limits of the constant pool, my doubt was exactly what goes into into. The generated code doesn't have more that about 10000 methods+fields.

My doubt is if literals also go to the constant pool or not, since that's the only reason I see to raise this number up to 65K. It seems so.

halfwarp
  • 1,780
  • 5
  • 24
  • 41
  • what kind of code is it? – Francisco Spaeth Jul 11 '12 at 17:16
  • You may find this link useful to read http://marxsoftware.blogspot.co.uk/2010/01/reproducing-too-many-constants-problem.html – Jon Taylor Jul 11 '12 at 17:17
  • Presumably it means that some limit has been reached. I forget what the limits of the constant pool are, but there are other limits inside the compiler that may be responsible as well. – Hot Licks Jul 11 '12 at 17:18
  • Methods to be compiled. Even without exhausting heap, it raises. – Alfabravo Jul 11 '12 at 17:20
  • 6
    perhaps the fact that your code has 83K+ lines in one file maybe should give you a hint to break it out into multiple classes. – Matt Jul 11 '12 at 17:20
  • (The Java class file model is actually fairly poorly designed in this regard -- it's fairly easy to exceed it's limits. The limit on the method exception table is a biggie.) – Hot Licks Jul 11 '12 at 17:20
  • Splitting the code into multiple classes is already in schedule. Although it wasn't for this exact reason. I aware of the limits of the constant pool, my doubt was exactly what goes into into. The generated code doesn't have more that about 10000 methods+fields. My doubt is if literals also go to the constant pool or not, since that's the only reason I see to raise this number up to 65K. It seems so. – halfwarp Jul 11 '12 at 17:25
  • 1
    Names of methods, and other `String`s accessible via reflection, go into the constant pool. – Louis Wasserman Jul 11 '12 at 17:35
  • The trouble with systems that generate code is that ... they generate code. And they aren't as inefficient as human programmers so they can write zillions of lines of code in seconds. Are you sure you really want to do this? You might be better off investigating an interpretive solution. – user207421 Jul 12 '12 at 00:24
  • Yep, literals go in the constants pool, too. (I tried to paste 400,000 `(byte)0x4D,(byte)0x5A` type literals into the definition for a `byte[]`, googled the error, and found myself here.) – daveloyall May 01 '15 at 19:29

4 Answers4

10

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

The constant pool includes numbers, strings, method names, field names, class names, references to classes and methods...basically everything.

There can be at most 65536 of them.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • So this means that it's not really about the number of fields I have declared in my main class. Even if these fields are declared in other classes, as long as I reference them from the same main class I'll have the same problem, right? – halfwarp Jul 11 '12 at 19:24
  • 1
    The number of different fields, methods, etc. referenced by any one class is limited to 65536, yes, I believe so. – Louis Wasserman Jul 11 '12 at 19:32
  • Louis is correct - the total of all references and definitions, constants, etc.. are limited to ~ that number. Thus you can't even fake it using arrays and constants for indexing as the index #s take up CP slots too. – Trent Gray-Donald Jul 16 '12 at 08:36
2

Section 5.1 of the JVM spec defines exactly what constitutes the constant pool (mostly references to classes/methods and literals).

casablanca
  • 69,683
  • 7
  • 133
  • 150
2

From: JVM Spec

you can see that the classfile.constant_pool_count has a 'u2' type, which limits it to 65535 entries

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];
}
James
  • 9,064
  • 3
  • 31
  • 49
2

I don't know if this is very relevant, but for array constants, EVERY field counts towards it. I'm not quite sure why (my guess is that you don't actually give a literal, and thus the runtime have to put in every value manually, hence needing them all to be constants), but it's like that, and that's the way it is.

I found that problem when I generated a large cache as an array literal. Since I didn't want to write out 1 000 000 constants by hand, I wrote a small program to write the program for me. I wanted to see how fast the program was when everything was cached from startup.

(The problem in question is 1.6.1 from "Programming Challenges" by Skiela and Revilla, ISBN 0-387-00163-8)

So you may have some array somewhere with literals. That is not counted as ONE constant. It's counted as array.length constants. Or array.length + 1 constants.

Haakon Løtveit
  • 1,009
  • 10
  • 18
  • 1
    It's actually every *unique* item in the array that counts towards it. Identical items in the array can use the same index in the constant pool. – RamenChef Nov 15 '20 at 23:01