Tuesday, June 21, 2011

Method Size Limit in Java .!

Most people don’t know this, but you cannot have methods of unlimited size in Java.
Java has a 64k limit on the size of methods.
What happens if I run into this limit?
If you run into this limit, the Java compiler will complain with a message which says something like "Code too large to compile".
You can also run into this limit at runtime if you had an already large method, just below the 64k limit and some tool or library does bytecode instrumentation on that method, adding to the size of the method and thus making it go beyond the 64k limit. In this case you will get a java.lang.VerifyError at runtime.
This is an issue we ran into with the Chronon recorder where most large programs would have atleast a few large methods, and adding instrumentation to them would cause them to blow past the 64k limit, thus causing a runtime error in the program.
Before we look into how we went about solving this problem for Chronon, lets look at under what circumstances people write such large methods in the first place.
Where do these large methods come from?
·         Code generatorsAs it turns out, most humans don’t infact write such gigantic methods. We found that most of these large methods were the result of some code generators, eg the ANTLR parser generator generates some very large methods.
·         Initialization MethodsInitialization methods, especially gui initialization methods, where all the layout and attaching listeners, etc to every component in some in one large chunk of code is a common practise and results in a single large method.
·         Array initializers
If you have a large array initialized in your code, eg:
static final byte largeArray[] = {10, 20, 30, 40, 50, 60, 70, 80, …};
that is translated by the compiler into a method which uses load/store instructions to initialize the array. Thus an array too large can cause this error too, which may seem very mysterious to those who don’t know about this limit.
·         Long jsp pagesSince most JSP compilers put all the jsp code in one method, large jsp pages can make you run into these errors too.
Of course, these are only a few common cases, there can be a lot of other reasons why your method size is too large.
How do we get around this issue?
If you get this error at compile time, it is usually trivial to split your code into multiple methods. It may be a bit hairy when the method limit is reached due to some automated code generation like ANTLR or JSPs, but usually even these tools have provisions to allow you to split the code into chunks, eg : jsp:include in the case of JSPs.
Where things get hairy is the second case I talked about earlier, which is when bytecode instrumentation causes the size of your methods to go beyond the 64k limit, which results in a runtime error. Of course you can still look at the method which is causing the issue, and go back and split it. However, this may not be possible if the method is inside a third party library.
Thus, for the Chronon recorder at least, the way we fixed it was to instrument the method, and then check the method's size after instrumentation. If the size is above the 64k limit, we go back and 'deinstrument' the method, thus essentially excluding it from recording. Since both our Recorder and  Time Travelling Debugger are already built from the groud up to deal  with excluded code, it wasn’t an issue while recording or debugging the rest of the code.
That said, the method size limit of 64k is too small and not needed in a world of 64 bit machines. I would urge everyone reading this to go vote on this JVM bug so that this issue can be resolved in some future version of the JVM.

No comments:

Post a Comment