Monthly Archives: October 2018

Comparing Golang and Understanding Value Types BaselOne

Comparing Golang and Understanding Value Types BaselOne Video

I was invited again to deliver my talk comparing Go language with Java and to talk a bit about value types. This time it was in Basel at the BaselOne conference. This one day conference happens once a year in Basel at the MarkHalle. This is a kind of shopping mall close to the railway station. The place is not too posh so you will not feel uncomfortable walking around in the typical developer outfits. At the same time, there are a lot of food places and the conference organizers provided coupons valid for some food. There were three rooms for parallel talks. One of the rooms is actually a café and you can really buy coffee before the talk and later listen to the talk while sipping your mocha. The audience was composed mainly of local developers from within Switzerland. The organization of the conference is very much related to the Swiss Java Users’ Group. There was no official video recording of the conference but organizers welcomed my recording and gave me permission to publish the video, so here it goes.

I have edited the video I recorded during the conference where I presented Comparing Golang and Understanding Value Types. The video shows the slides and, just for the sake of completeness and to increase the enjoyment factor, my slender myself presenting in PIP.

I delivered the talk also in May in Vilnius and before that April, the same year in Mainz at W-JAX. Both of those times the talk was disturbed some external noise. This time we had nothing like that. I almost started to miss it. (not really)

Now that JAX also published the video

https://vimeo.com/jaxtv/review/288743607/ce57328338

You can compare the three, how different the same talk can be. (Seriously, I do not think it is interesting for anyone.) Here is the Vilnius conference video:

Advertisements

JEP 181 incompatibility, nesting classes / 2

JEP 181 is a nest based access control https://openjdk.java.net/jeps/181. It was introduced in Java 11 and it deliberately introduced an incompatibility with previous versions. This is a good example that being compatible with prior versions of Java is not a rule carved into stone but it rather is to keep the consistency and steady development of the language. In this article, I will look at the change through an example that I came across a few years ago and how Java 11 makes life easier and more consistent in this special case.

Java backward compatibility is limited to features and not to behavior

Original Situation

A few years ago when I wrote the ScriptBasic for Java interpreter that can be extended with Java methods, so that they are available just as if they were written in BASIC I created some unit tests. The unit test class contained some inner class that had some method in it available for the BASIC code. The inner class was static and private as it had nothing to do with any other classes except the test, however, the class and the methods were still accessible to the test code because they resided in the same class. To my dismay, the methods were not accessible via the BASIC programs. When I tried to call the methods through the BASIC interpreter, which itself was using reflective access I got IllegalAccessException.

To rectify the situation I created the following simple code after a few hours of debugging and learning:

package javax0;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflThrow {
    private class Nested {
        private void m(){
            System.out.println("m called");
        }
    }
    public static void main(String[] args)
            throws NoSuchMethodException,
            InvocationTargetException,
            IllegalAccessException {
        ReflThrow me = new ReflThrow();
        Nested n = me.new Nested();
        n.m();
        Method m = Nested.class.getDeclaredMethod("m");
        m.invoke(n);
    }
}

If you run this code with Java N where N < 11 then you get something similar to this:

m called
Exception in thread "main" java.lang.IllegalAccessException: class ReflThrow cannot access a member of class ReflThrow$Nested with modifiers "private"
    at java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:423)
    at java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:414)
...

It works, however, fine using Java 11 (and presumably it will also work fine with later versions of Java).

Explanation

Up to version 11 of Java the JVM did not handle inner and nested classes. All classes in the JVM are top-level classes. The Java compiler creates a specially named top-level class from the inner and nested classes. For example one of the Java compilers may create the class files ReflThrow.class and ReflThrow$Nested.class. Because they are top level classes for the JVM the code in the class ReflThrow cannot invoke the private method m() of Nested when they are two different top-level classes.

On the Java level, however, when these classes are created from a nested structure it is possible. To make it happen the compiler creates an extra synthetic method inside the class Nested that the code in ReflThrow can call and this method already inside Nested calls m().

The synthetic methods have the modifier SYNTHETIC so that the compiler later knows that other code should not “see” those methods. That way invoking the method m() works nicely.
On the other hand, when we try to call the method m() using its name and reflective access the route goes directly through the class boundaries without invoking any synthetic method, and because the method is private to the class it is in, the invocation throws the exception.

Java 11 changes this. The JEP 181 incorporated into the already released Java 11 introduces the notion nest. “Nests allow classes that are logically part of the same code entity, but which are compiled to distinct class files, to access each other’s private members without the need for compilers to insert accessibility-broadening bridge methods.” It simply means that there are classes which are nests and there are classes which belong to a nest. When the code is generated from Java then the top level class is the nesting class and the classes inside are nested. This structure on the JVM level leaves a lot of room for different language structures and does not put an octroi of a Java structure on the execution environment. The JVM is aimed to be polyglot and it is going to be even “more” polyglot with the introduction of the GraalVM in the future. The JVM using this structure simply sees that two classes are in the same nest, thus they can access each other private methods, fields and other members. This also means that there are no bridge methods with different access restrictions and that way reflection goes through exactly the same access boundaries as the normal Java call.

Summary / Takeaway

Java does not change overnight and is mostly backward compatible. Backward compatibility is, however, limited to features and not to behavior. The JEP181 did not, and it never actually intended to reproduce the not absolutely perfect IllegalAccessException throwing behavior of the reflective access to nested classes. This behavior was rather an implementation behavior/bug rather than a language feature and was in Java 11 fixed.