Bug 331334 - [1.5][compiler] "The code for the static initializer is exceeding the 65535 bytes limit" in enum
Summary: [1.5][compiler] "The code for the static initializer is exceeding the 65535 b...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: 3.7 M5   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-29 08:04 EST by Peter van den Berkmortel CLA
Modified: 2011-01-25 09:14 EST (History)
3 users (show)

See Also:


Attachments
Example enum (105.09 KB, text/plain)
2010-11-29 08:11 EST, Peter van den Berkmortel CLA
no flags Details
Proposed fix (21.41 KB, patch)
2010-12-19 19:52 EST, Olivier Thomann CLA
no flags Details | Diff
Proposed fix + regression test (99.16 KB, patch)
2011-01-05 15:02 EST, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Peter van den Berkmortel CLA 2010-11-29 08:04:30 EST
Build Identifier: 20100917-0705

We use a generated enum to statically reference certain reference data (which we want to be accessible in source code when created in a development environment). Adding or updating the entity causes the source file to be regenerated.
The number of values now exceeds 2,500, which causes a compiler error in eclipse: The code for the static initializer is exceeding the 65535 bytes limit. However, when we build the code in Ant, there is no compile error. Checking the JVM limitations, I would expect a limit of 65,535 entries in an enum (see http://java.sun.com/docs/books/vmspec/html/ClassFile.doc.html#6253) and not a limit of 2,500.
It appears that eclipse handles enum constants identically to static final constants. Imho this is wrong. Enum constants should be handled separately.

There's a similar bug report for static final fields, suggesting that the class should be broken up and constants should be initialized in separate methods. This doesn't work in enums, because enums can not use inheritance.

Reproducible: Always

Steps to Reproduce:
1. Create an enum. Add 2,500+ entries.
2. Compile outside eclipse: compilation succeeds.
3. Compile in eclipse: compilation fails.
Comment 1 Peter van den Berkmortel CLA 2010-11-29 08:11:12 EST
Created attachment 184033 [details]
Example enum

Attached an example enum.
Comment 2 Peter van den Berkmortel CLA 2010-11-29 08:14:41 EST
P.S. we are working on a 64-bit machine. On 32-bit windows the limit would be 5,000.
Comment 3 Chris West (Faux) CLA 2010-11-29 08:27:08 EST
(OpenJDK 6 x64) javac issues exactly the same error after a couple more elements; it's not an avoidable problem as far as I'm aware:

EnumExample.java:15: code too large
Comment 4 Olivier Thomann CLA 2010-11-29 09:22:47 EST
(In reply to comment #0)
> It appears that eclipse handles enum constants identically to static final
> constants. Imho this is wrong. Enum constants should be handled separately.
Please let me know why this would be a problem.

The only way to "fix" this would be to split the initialization call from the clinit into multiple methods.

I'll see what I can do.
Comment 5 Peter van den Berkmortel CLA 2010-11-29 09:31:00 EST
(In reply to comment #3)
> (OpenJDK 6 x64) javac issues exactly the same error after a couple more
> elements; it's not an avoidable problem as far as I'm aware:
> EnumExample.java:15: code too large

Chris, you are absolutely correct. Sun JDK also generates 'code too large' when you add a few more items. The difference with eclipse is negligible.

The issue should be closed. Thanks for the fast reply.
Comment 6 Olivier Thomann CLA 2010-11-29 09:41:52 EST
(In reply to comment #5)
> Chris, you are absolutely correct. Sun JDK also generates 'code too large' when
> you add a few more items. The difference with eclipse is negligible.
> The issue should be closed. Thanks for the fast reply.
I think it is worth investigating if we could simply insert the usage of synthetic methods when the number of constants is high. Might be simple to fix.
In the JLS doesn't mention that limit of 2500+ enum constants.

There is a limit in the code that can be generated for a method body and enum constants initialization must be generated as part of the clinit contents. But as far as I can say, there is nothing that prevents the usage of synthetic methods to initialize enum constants.
Comment 7 Peter van den Berkmortel CLA 2010-11-29 09:58:19 EST
(In reply to comment #6)
> In the JLS doesn't mention that limit of 2500+ enum constants.

I guess the issue arises from some limitations in the JVM (that only a limited amount of memory can be allocated for certain features in a class file). For a programmer it would be very useful if the issue could be avoided by the compiler itself, rather than forcing him/her to refactor the code when you add one item too many.
Comment 8 Olivier Thomann CLA 2010-12-10 13:18:29 EST
(In reply to comment #7)
> I guess the issue arises from some limitations in the JVM (that only a limited
> amount of memory can be allocated for certain features in a class file). For a
> programmer it would be very useful if the issue could be avoided by the
> compiler itself, rather than forcing him/her to refactor the code when you add
> one item too many.
When you have more than 2000 enum constants, I think it is time to refactor :-).
Anyway, I'll investigate if we can create synthetic methods to "factorize" the code automatically.
Comment 9 Olivier Thomann CLA 2010-12-19 19:52:18 EST
Created attachment 185509 [details]
Proposed fix

First draft. This compiles fine the given example. I'll add a regression test for this.
Comment 10 Chris West (Faux) CLA 2010-12-20 07:54:41 EST
While this is a great idea; is there any way to turn back on the Sunracle compiler "bug", for those of us that have to ship Sunracle-compatible code?  In this case it makes minimal difference, but if it's later expanded to do the same for method sizes and the like (there's no reason for it not to do so, except maybe that pesky spec, right?), it might be needed.

Also, 2000 as a magic number twice in the patch. ¬_¬
Comment 11 Olivier Thomann CLA 2011-01-05 12:52:00 EST
I plan to release that patch as it is fixing the problem. I cannot rely on javac implementation to decide whether a fix should be released or not. Since the given example should compile according to the JLS, I treat this as a compiler bug.
As is, it should be fixed since there is no workaround except splitting the enum constants into multiple enum declarations.
Comment 12 Olivier Thomann CLA 2011-01-05 15:02:26 EST
Released for 3.7M5.
Regression test added in:
org.eclipse.jdt.core.tests.compiler.regression.XLargeTest#test0016
Comment 13 Olivier Thomann CLA 2011-01-05 15:02:59 EST
Created attachment 186117 [details]
Proposed fix + regression test

Cleaned patch with regression test.
Comment 14 Ayushman Jain CLA 2011-01-25 09:14:31 EST
Verified for 3.7M5 using build I20110124-1800.