Hachim IntegerCache in Java 9
For many, switching to Java 9 looks like something abstract. Let us translate this into a practical plane with one short victorious example that Peter Vargas cited in his article [1] .
This is an article in the "incorrect translation" genre with a gag, because I'm an artist, as I see it =) Links to sources - as always, at the bottom of the text.
Five years ago, Peter published a Hungarian blog post about hacking IntegerCache in the JDK. This is just a small experiment with runtime, which has no practical application other than increasing erudition, understanding how reflection works, and how the Integer class works.
Look, the generation of real random numbers depends on the entropy of the system [2] . Some argue that this can be done with an honest die roll.[3] .

Others believe that redefining the body of the java.math.Random.nextInt () method will come to our aid.
For those who do not know the ancient button accordion [4] . At the hackathon of the Dutch JPoint in 2013, the assembly and modification of OpenJDK was discussed. After Roy van Rijn learned to build it under Windows (how to do it in 2017 I wrote here [5] ), he immediately got down to business and made his first commit.
Instead of changing the core of OpenJDK (which is all in native codes, you need to be a doctor of science for this), he found that the base libraries are just Java classes and they are defenseless against his charisma. If you look at [openjdk] / jdk / src / share / classes, you can find the usual package directories like “java. *”, “javax. *” and even “sun. *”. Therefore, you can get into [openjdk] /jdk/src/share/classes/java/util/Random.java with dirty boots and make the obvious change:
After rebuilding the JDK, all calls to new Random (). NextInt () will actually return 14.
But this is all complete garbage. Real boys know that the real way to add entropy is to rewrite java.lang.Integer.IntegerCache at the start of the JVM (and below we will show how).
Recall that Integer contains a private inner class IntegerCache containing objects of type Integer for the range from -128 to 127. When the code is boxed in Integer and has a value from this range, the runtime uses the cache instead of creating a new Integer. All this for the sake of speed optimization, and assuming that in real programs the numbers constantly fit into this range (take at least indexing of arrays).
The side effect of this is the well-known fact that the comparison operator can be used to compare int values while the numeral is in the specified range. It's funny that such code (being written incorrectly) usually works in all kinds of unit tests (written incorrectly in order to be consistent), but will fall down in real use immediately, as the values go beyond 128. The author of this habropost wonders why this implementation detail was God was pulled into the light and settled in the tests for interviews, tightly ruining the unreinforced child psyche of many good people.
Warning, danger. If you hook IntegerCache through reflection, it can lead to magical side effects and will have an effect not only on a specific place, but on the entire contents of this JVM. That is, if a servlet changes some pieces of the cache, then all other servlets in the same Tomcat will have a hard time. Olso, we warned.
Well, let's take the Java 9 beta and try to make it the same crap that it rolled in Java 8. Let's copy the code from the article by Lucas [2] :
As promised, this code accesses IntegerCache using reflection, and populates it with random values. What a wonderful dirty decision!
Now we run the same code under Nine. Bad news for dirty boys, there will be no holiday. When trying to humiliate her, Nine reacts much more seriously:
We got an exception that did not exist in the Eight. It says that the object is unavailable because the java.base module, which is part of the JDK runtime and is automatically imported by any java program, does not "open" (sic) the module we need for the unnamed module. The error falls on the line where we are trying to make the field accessible.
The object, which we could easily reach in the Eight, is no longer available, because it is protected by a module system. The code can access the fields, methods, etc. using reflection only if the class is in the same module, or if this module gives access to access by reflection for the whole world, or some specific module.
This is done in a file called module-info.java, something like this:
The java.base module does not give us access, so we suck on our paw. If you want to see a more beautiful error, you can create a module for our code, and see its name in the error text.
Can we open access programmatically? There java.lang.reflect.Module have some method addOpens, it prokanaet? The bad news is no. It can open a package in module A for module B only if this package is already open for module C, which calls this method. Thus, the modules can transfer to each other those rights that already have, but cannot open, closed.
But this can also be considered good news. Java is growing above itself, Nine is not as easy to smash as the Eight. At least this little hole was closed. Java is increasingly becoming a professional tool, not a toy. Soon we will be able to rewrite all the serious software on it, now written by IBM RPG and COBOL.
Oh yes, it can still be broken like this:
Maybe you should also ban Unsafe?
Btw, if you are afraid to write comments here, you can crawl into my fb , meet live at some Joker 2017 , or just cross next to the Kronos or Goose business centers in Novosibirsk, have a beer with a smoothie and discuss some other funny game . More game to the game god!
PS I was asked to insert cats into the article. Therefore, here is a rare photo of a smiling Mark Reinhold:

Sources :
[1] Original article
[2] The person who revived the code from the article in Hungarian
[3] Everyone knows the picture about random numbers
[4] How to redefine nextInt
[5]How to build Java on Windows
This is an article in the "incorrect translation" genre with a gag, because I'm an artist, as I see it =) Links to sources - as always, at the bottom of the text.
Five years ago, Peter published a Hungarian blog post about hacking IntegerCache in the JDK. This is just a small experiment with runtime, which has no practical application other than increasing erudition, understanding how reflection works, and how the Integer class works.
Look, the generation of real random numbers depends on the entropy of the system [2] . Some argue that this can be done with an honest die roll.[3] .

Others believe that redefining the body of the java.math.Random.nextInt () method will come to our aid.
For those who do not know the ancient button accordion [4] . At the hackathon of the Dutch JPoint in 2013, the assembly and modification of OpenJDK was discussed. After Roy van Rijn learned to build it under Windows (how to do it in 2017 I wrote here [5] ), he immediately got down to business and made his first commit.
Instead of changing the core of OpenJDK (which is all in native codes, you need to be a doctor of science for this), he found that the base libraries are just Java classes and they are defenseless against his charisma. If you look at [openjdk] / jdk / src / share / classes, you can find the usual package directories like “java. *”, “javax. *” and even “sun. *”. Therefore, you can get into [openjdk] /jdk/src/share/classes/java/util/Random.java with dirty boots and make the obvious change:
public int nextInt() {
return 14;
}
After rebuilding the JDK, all calls to new Random (). NextInt () will actually return 14.
But this is all complete garbage. Real boys know that the real way to add entropy is to rewrite java.lang.Integer.IntegerCache at the start of the JVM (and below we will show how).
Recall that Integer contains a private inner class IntegerCache containing objects of type Integer for the range from -128 to 127. When the code is boxed in Integer and has a value from this range, the runtime uses the cache instead of creating a new Integer. All this for the sake of speed optimization, and assuming that in real programs the numbers constantly fit into this range (take at least indexing of arrays).
The side effect of this is the well-known fact that the comparison operator can be used to compare int values while the numeral is in the specified range. It's funny that such code (being written incorrectly) usually works in all kinds of unit tests (written incorrectly in order to be consistent), but will fall down in real use immediately, as the values go beyond 128. The author of this habropost wonders why this implementation detail was God was pulled into the light and settled in the tests for interviews, tightly ruining the unreinforced child psyche of many good people.
Warning, danger. If you hook IntegerCache through reflection, it can lead to magical side effects and will have an effect not only on a specific place, but on the entire contents of this JVM. That is, if a servlet changes some pieces of the cache, then all other servlets in the same Tomcat will have a hard time. Olso, we warned.
Well, let's take the Java 9 beta and try to make it the same crap that it rolled in Java 8. Let's copy the code from the article by Lucas [2] :
import java.lang.reflect.Field;
import java.util.Random;
public class Entropy {
public static void main(String[] args)
throws Exception {
// Вытаскиваем IntegerCache через reflection
Class clazz = Class.forName(
"java.lang.Integer$IntegerCache");
Field field = clazz.getDeclaredField("cache");
field.setAccessible(true);
Integer[] cache = (Integer[]) field.get(clazz);
// Переписываем Integer cache
for (int i = 0; i < cache.length; i++) {
cache[i] = new Integer(
new Random().nextInt(cache.length));
}
// Проверяем рандомность!
for (int i = 0; i < 10; i++) {
System.out.println((Integer) i);
}
}
}
As promised, this code accesses IntegerCache using reflection, and populates it with random values. What a wonderful dirty decision!
Now we run the same code under Nine. Bad news for dirty boys, there will be no holiday. When trying to humiliate her, Nine reacts much more seriously:
Exception in thread "main" java.lang.reflect.InaccessibleObjectException:
Unable to make field static final java.lang.Integer[]
java.lang.Integer$IntegerCache.cache
accessible: module java.base does not "opens java.lang" to unnamed module @1bc6a36eWe got an exception that did not exist in the Eight. It says that the object is unavailable because the java.base module, which is part of the JDK runtime and is automatically imported by any java program, does not "open" (sic) the module we need for the unnamed module. The error falls on the line where we are trying to make the field accessible.
The object, which we could easily reach in the Eight, is no longer available, because it is protected by a module system. The code can access the fields, methods, etc. using reflection only if the class is in the same module, or if this module gives access to access by reflection for the whole world, or some specific module.
This is done in a file called module-info.java, something like this:
module randomModule {
exports ru.habrahabr.module.random;
opens ru.habrahabr.module.random;
}The java.base module does not give us access, so we suck on our paw. If you want to see a more beautiful error, you can create a module for our code, and see its name in the error text.
Can we open access programmatically? There java.lang.reflect.Module have some method addOpens, it prokanaet? The bad news is no. It can open a package in module A for module B only if this package is already open for module C, which calls this method. Thus, the modules can transfer to each other those rights that already have, but cannot open, closed.
But this can also be considered good news. Java is growing above itself, Nine is not as easy to smash as the Eight. At least this little hole was closed. Java is increasingly becoming a professional tool, not a toy. Soon we will be able to rewrite all the serious software on it, now written by IBM RPG and COBOL.
Oh yes, it can still be broken like this:
public class IntegerHack {
public static void main(String[] args)
throws Exception {
// Вытаскиваем IntegerCache через reflection
Class usf = Class.forName("sun.misc.Unsafe");
Field unsafeField = usf.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
sun.misc.Unsafe unsafe = (sun.misc.Unsafe)unsafeField.get(null);
Class clazz = Class.forName("java.lang.Integer$IntegerCache");
Field field = clazz.getDeclaredField("cache");
Integer[] cache = (Integer[])unsafe.getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
// Переписываем Integer cache
for (int i = 0; i < cache.length; i++) {
cache[i] = new Integer(
new Random().nextInt(cache.length));
}
// Проверяем рандомность!
for (int i = 0; i < 10; i++) {
System.out.println((Integer) i);
}
}
}Maybe you should also ban Unsafe?
Btw, if you are afraid to write comments here, you can crawl into my fb , meet live at some Joker 2017 , or just cross next to the Kronos or Goose business centers in Novosibirsk, have a beer with a smoothie and discuss some other funny game . More game to the game god!
PS I was asked to insert cats into the article. Therefore, here is a rare photo of a smiling Mark Reinhold:

Sources :
[1] Original article
[2] The person who revived the code from the article in Hungarian
[3] Everyone knows the picture about random numbers
[4] How to redefine nextInt
[5]How to build Java on Windows