Monthly Archives: May 2017

Who needs Java modules after all ?

Oleg Selajev asked on twitter


Jigsaw questions for 1000. I as an X want JPMS modules. What is X if it’s not a platform developer?

My answer is that X is a human being (minus platform developers, because that was a condition). We all need module system to have safer code resulting in more reliable systems resulting in better performance in the business resulting in better economy resulting in human happiness. Perhaps I went a bit too far with the conclusions but the point is that module system is needed by everyone in the industry whether they’re aware of it or not. You will get it. First of all we should start with the ob(li)vious answer to the question.

Nicolai Parlog said: Every library developer whose types are not all public.

Very true. As a library developer I want to design my libraries so that I separate the API. I wan to separate the public interface from the implementation. This is what we, programmers call “encapsulation”. This is soooo good to encapsulate. We love to do it! We do it, because it is hilarious! We love it!

On the second thought though we do it because it is a tool to create reliable bug free (he he he) software.

It helps the code developers who use my code that encapsulates the internal state and implementation to write better code. It is a bit like raising children. I as parent disallow certain things that they would do. Eat lots of chocolate, stay up late and so on. And this is for their own good, even though they do not see or understand it at the moment. Later, of course, when they grow up and become parents themselves they will understand and do the same. It is not much different with library developers and library using programmers, except, perhaps, that programmers never grow up.

Similarly I as a library developer need JPMS for the sake of the developers who are going to use my code. My library will not be better or worse just because I encapsulate. (Side note: it will be better, but not because of the lessened number of bugs in it.) I can easily get the implication that I as a library developer want JPMS the least. Who cares if you, dear programmer, shoot off your testicles using my library? It is your responsibility to call only the public API and not some frequently modified internal class and method. Or is it?

Not really. It is also my responsibility to create a library that is easy to use and hard to make mistakes using it. This is what we call usability. This is where JPMS module system comes into the picture. Without JPMS I can document what packages are public and which are implementation specific. The contract between me and the users of the library is that they will not use the privates of my library and for this well behaviour I will keep the public part of the library stable so that they do not need to change their code from release to release. (Btw. has anyone ever realized how literally bloody this name, jPMS is? What the fly? PMS, really? Not to mention seeing currently all the cramps related to it: nomen est omen. It was not a lucky baptism.)

Let’s get back on our rail: why do we need module system for that? Developers are disciplined (he he he) people and they do not want to harm themselves. They should not and they will not use internal code of the library. That is not good for them on the long run and they are well aware of that. The catch is the long run thingy. In the long run we are all dead. There will be a point during the development, typically a few days before release date, when some of the internal APIs of a library just seem lucrative to be used. In some weird way those internal calls are just exactly what you need. You know that you are not supposed to use them, and there is a good, well-mannered solution, but that needs more time to develop. It is just that with the release date approaching you do not have the time to follow that pattern. Not to mention feeling proud about the “I can do that”, “how well I know these tools” thoughts, instead of feeling shame tampering with the parts of the library that are private.

That is where Java Module System comes into the picture. You will not be able to do shortcuts. You will sigh remembering the good old days when Java was open to the whole world whatever there was on the classloader (not to mention FORTRAN programming, am I right or just the contrary I am right?) but you will follow the rules, because it just will not work otherwise.

You think that you are not vulnerable to such vanity as using the internal parts of a library. Here is a test: did you recognize that I used the expression “internal APIs of a library”? If not, then feel ashamed but don’t admit it. No need. Java Module System will help to forget things that do not exist, like internal API. Nonsense. API is public. There is no such thing as internal API. The resulting code will be better, easier to maintain, less prone to library upgrades and thus cheaper at the bottom line.

In the long run, when we are all dead our offspring will create better code and having module level encapsulation will be an obvious thing, just like world peace will be that time.

So I need Java Module System, you need it, and everybody else needs it for a better world and for the sake of world peace.

Disclaimer: The author of the article no speaks English as naive language 😉

Advertisements

Hacking the IntegerCache in Java 9

Five years ago I published an article in Hungarian about how to alter the IntegerCahe in the JDK. Doing that is essentially hacking the Java run-time and there is no practical advantage unless while you develop the hacking code you get a better understanding how reflection works and how the Integer class is implemented.

The Integer class has a private nested class named IntegerCache that contains Integer objects for the int values -127 to 128. When the code has to box an int to Integer and the value is within this range then the run-time uses the cache instead of creating new Integer object. This is done for speed optimization reasons bearing in mind that the int values in programs are many times in this range (think about array indexing).

The side effect of this is that many times using the identity operator to compare two Integer objects may work so long as long the value is in the range. This is typically during unit test. In operational mode, when some of the values get bigger than 128 the code fails.

Hacking the IntegerCache using reflection may also lead to mysterious side effects and note that this is something that has its effect on the whole JVM. If a servlet redefines the small Integer cached values then all other servlets running in the same Tomcat under the same JVM will suffer.

There are other articles about it on the net from Lukas Eder

Add Some Entropy to Your JVM

and on the excellent blog site Sitepoint:

https://www.sitepoint.com/10-things-you-didnt-know-about-java/

Now that I started to play around with Java 9 early access version it came to my mind if I can do the same hacking with the new version of Java. Before starting that let’s refresh what we did with Java 8.

Lukas in his article displays a sample code, I copy here:

import java.lang.reflect.Field;
import java.util.Random;
 
public class Entropy {
  public static void main(String[] args) 
  throws Exception {
 
    // Extract the IntegerCache through reflection
    Class<?> clazz = Class.forName(
      "java.lang.Integer$IntegerCache");
    Field field = clazz.getDeclaredField("cache");
    field.setAccessible(true);
    Integer[] cache = (Integer[]) field.get(clazz);
 
    // Rewrite the Integer cache
    for (int i = 0; i < cache.length; i++) {
      cache[i] = new Integer(
        new Random().nextInt(cache.length));
    }
 
    // Prove randomness
    for (int i = 0; i < 10; i++) {
      System.out.println((Integer) i);
    }
  }
}

The code gets access to the IntegerCache via reflection and then fills the cache with random values. Naughty.

We can try to execute the same code in Java 9. Do not expect much fun though. Java 9 is more serious when somebody tries to violate it.

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 @1bc6a36e

We get an exception that did not exist in Java 8. It says that object is not accessible because the module java.base, which is the part of the run-time of the JDK that is automatically imported by each Java program does not ‘opens’ (sic) the module to the unnamed module. It is thrown from the line where we try to set the field accessible.

The object we could easily access in Java 8 is not accessible any more, because the module system protects it. A code can only access fields, methods, and other things using reflection only if the class is in the same module, or if the module opens the package for reflective access for the world or for the module that needs the access. This is done in the module-info.java module definition file, like

module myModule {
    exports com.javax0.module.demo;
    opens com.javax0.module.demo;
}

The module java.base does not open itself for reflective access for us and especially not for the unnamed module, which is the code that we run. If we create a module for our code and name it then the error message will contain the name of that module.

Can we open the module programmatically? There is an addOpens method in the java.lang.reflect.Module module. Will it work?

Bad news for the hackers that it will not. It can only open a package in a module to another module if that package is already opened for the module calling this method. That way modules can pass on to other modules the right that they already have to access some packages in a reflective way but can not open things that are not open.

But the same time it is a good news. Java 9 is not so easily hackable like Java 8 was. At least this little hole is closed. It seems that Java starts to be professional grade and not to be a toy. Soon the time will come when we can migrate serious programs from RPG and COBOL to Java. (Sorry for the joke.)

UPDATE

After the article was republished on DZONE Peter Runge pointed out that the module system in this case still can be neglected using sun.misc.Unsafe class. Based on his suggestion the whole hack is here:

public class IntegerHack {

    public static void main(String[] args)
            throws Exception {
        // Extract the IntegerCache through 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));
        // Rewrite the Integer cache
        for (int i = 0; i < cache.length; i++) {
            cache[i] = new Integer(
                    new Random().nextInt(cache.length));
        }

        // Prove randomness
        for (int i = 0; i < 10; i++) {
            System.out.println((Integer) i);
        }
    }
}