Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the maximum size of a Java .class file?

Tags:

A .class file is a rather well documented format that defines sections and size, and therefore maximum sizes as well.

For instance, a .class file contains a magic number (4 bytes), a version (4 bytes), the constant pool (variable size), etc. But sizes can be defined on several levels: you can have 65535 methods and each is limited to 65535 bytes.

What are the other limits? And, if you would make the largest .class file possible, what size would it be?

If needed, limit answers to Java. Meaning that if Scala or Clojure (or...) change some limits, disregard those values.

like image 744
Olivier Grégoire Avatar asked Feb 17 '17 10:02

Olivier Grégoire


People also ask

How long should class files be?

Like functions, according to Clean Code, classes should also be “smaller than small”. Some people recommend that 200 lines is a good limit for a class – not a method, or as few as 50-60 lines (in Ben Nadel's Object Calisthenics exercise)and that a class should consist of “less than 10” or “not more than 20” methods.

What is in a Java class file?

Java class files are stream files that are produced when a source file is compiled by the Java compiler. The class file contains tables that describe each field and method of the class. The file also contains the bytecodes for each method, static data, and descriptions that are used to represent Java objects.

How many .class files are created in Java?

class" files are created in the corresponding folder as there are four classes are defined in the "ClassTest. java" file. Those are A. class, B.

How many lines can a Java class have?

As mentioned the above, there is no limit on "lines of code” per class in java, we can probably use 200 lines as a good guideline and not exceed 500 lines per class.


2 Answers

The JVM specification doesn’t mandate a limit for class files and since class files are extensible containers, supporting arbitrary custom attributes, you can even max it out as much as you wish.

Each attribute has a size field of the u4 type, thus, could specify a number of up to 2³²-1 (4GiB). Since, in practice, the JRE API (ClassLoader methods, Instrumentation API and Unsafe) all consistently use either byte[] or ByteBuffer to describe class files, it is impossible to create a runtime class of a class file having more than 2³¹-1 bytes (2GiB).

In other words, even a single custom attribute could have a size that exceeds the size of actually loadable classes. But a class can have 65535 attributes, plus 65535 fields, each of them having 65535 attributes of its own and plus 65535 methods, each of them having up to 65535 attribute as well.

If you do the math, you will come to the conclusion that the theoretical maximum of a still well formed class file may exceed any real storage space (more than 2⁶⁵ bytes).

like image 99
Holger Avatar answered Sep 29 '22 11:09

Holger


It's quite easy to make huge StackMapTable using nested finally blocks as javac unwisely generates separate variables for each nesting level. This allows to produce several megabytes from very simple method like this:

class A {{   int a;   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   a=0;   }}}}}}}}}}}} }} 

Adding more nesting level is not possible as you will exceed code size for single method. You can also duplicate this using the fact that instance initializer is copied to every constructor:

class A {{   int a;   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   try {a=0;} finally {   a=0;   }}}}}}}}}}}} } A() { } A(int a) { } A(char a) { } A(double a) { } A(float a) { } A(long a) { } A(short a) { } A(boolean a) { } A(String a) { } A(Integer a) { } A(Float a) { } A(Short a) { } A(Long a) { } A(Double a) { } A(Boolean a) { } A(Character a) { }  } 

This simple java file when compiled with Java 8 javac produces 105,236,439 bytes .class-file. You can also add more constructors, though there's a risk that javac will fail with OutOfMemoryError (use javac -J-Xmx4G to overcome this).

like image 29
Tagir Valeev Avatar answered Sep 29 '22 11:09

Tagir Valeev