Many people know that every .class file has a wonderful data structure called a constant pool. But not every Java developer, looking at the source, can even approximately estimate how many constants will be created in the pool.
Take, for example, this code:
System.out.println("Hello World!");
It is translated into three bytecode instructions: getstatic (for loading the static field System.out), ldc (for loading the constant string “Hello World!”) And invokevirtual (for executing the virtual function println). Try to estimate how many constants are needed for this code to work.
It turns out that this string uses 14 constants, which can be schematically depicted as follows:

As we can see, most constants are references to other constants. Each constant has a type, a value, and a number by which it can be referenced. Here are the base types that don't refer to anything:
- Integer is an integer. They are referenced from the code where the number is required. The numbers from -32768 to 32767 do not add the compiler here: you can explicitly specify them in the code using the instructions iconst_ x , bipush and sipush.
- Long is a long integer. For historical reasons, it occupies two positions in the pool of constants (that is, the next constant number is two more). You can save only on 0L and 1L using lconst_ x ; 2L is already in the pool.
- Float - real single precision. Special instructions fconst_ x are for 0.0f, 1.0f and 2.0f; the remaining numbers used go to the pool.
- Double - real double precision. Like Long, occupies two positions in the pool. Only the numbers 0.0 and 1.0 can be used without a pool using the dconst_ x instructions.
- Utf8 is a Utf8 string literal. The maximum length does not exceed 65535 bytes (of course, there may be less characters). These literals are often referenced from other constants most often.
Here are some of the reference types:
- String - string. Contains a reference to a constant of type Utf8. If you use a string in the code, you refer to a constant of type String. It looks like an extra essence, but there is.
- NameAndType is a constant describing the name and type of the field or method. Contains two references to Utf8 constants with name and type.
- Class is a constant describing the name of a class or interface. Contains a reference to a Utf8 constant with the internal class name.
- Fieldref is a constant describing a specific field of a particular class. Contains a reference to the Class constant and a reference to the NameAndType constant.
- MethodRef, InterfaceMethodRef are constants that describe a particular method of a class or interface. They contain references to the Class constant and the NameAndType constant.
To access a field, you need not only its name, but also the full name of the class where the field is declared, as well as the field type. To access a method, you need a class, a name, and a method signature. Fortunately, the entire signature is encoded into one line regardless of the number of method parameters: primitive types are encoded with one letter (for example, D = double), objects with the letter L, followed by the full class name and a semicolon, and one array level adds square bracket. In parentheses are the types of arguments, followed by the return type (V is void). For example, the signature
(IDLjava/lang/Thread;)Ljava/lang/Object;
will have this method:
Object m(int i, double d, Thread t) {...}
From the fact that to refer to the method requires its exact signature, developers sometimes attach to NoSuchMethodError. Let's say you changed the return type of a method to a more specific one. Then the calls of this method from other classes remain the same, and the compiler will not reassemble these classes, because the source files have not changed. However, if you try to call this method at runtime, the Java machine will look for the old signature.
')
If you automatically generate Java code, remember that the maximum constant number in the pool does not exceed 65535, after that there will be a compilation error. This is not such a large number, given the huge number of links and the fact that long and double occupy two positions. Knowing the pool device will help you control how it is filled when generating code.
More information about the device pool of constants can be found in
§4.4 specification of the Java virtual machine.