Nested Based Access Control (JEP 181)

Reading Time: 2 minutes

In this blog we will discuss about a new feature which is being introduced in Java 11 Nested Based Access Control. Oracle introduces JVM level support for private access of nested classes, fields etc.

Nested Based Access Control

When we have nested classes in a class, after compilation different files are created. Before Java 11 for accessing the private member of the nested class or outer class we need to use the synthetic generated accessibility-broadening bridge methods.

But in Java 11 for accessing Classes and Interfaces Oracle has introduced another access control context known as nest.

Basically, the nest term defines a new access control context that allows classes that are logically part of the same code entity, but which are compiled with distinct class files, to access each other’s private members without the need for compilers to insert accessibility-broadening bridge methods (Java documentation).

So by the above defination we can say that this is a Java class bytecode level change.

Lets take an example

public class Test {
    private static int x = 5;

    public static class NestedTest {
        public static void doSomething() {

Now compile the code which will generate two classes

  1. Test.class
  2. Test$NestedTest.class

Lets see what we have in these files Before Java 11

javap -v Test.class
    static int access$000();
    descriptor: ()I
    flags: (0x1008) ACC_STATIC, ACC_SYNTHETIC
      stack=1, locals=0, args_size=0
         0: getstatic     #1                  // Field x:I
         3: ireturn
        line 1: 0
javap -v  'Test$NestedTest.class'
 public static void doSomething();
    descriptor: ()V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
      stack=2, locals=0, args_size=0
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: invokestatic  #3                  // Method Test.access$000:()I
         6: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
         9: return
        line 6: 0
        line 7: 9

Here we can see when we want to access the private field x from the NestedTest.doSomething() a bridge package-private method access$000() is syntactically generated. This is just because after compilation two different compiles files are generated one for outer class and one for inner class. So to access each others private members we need some access control mechanism.

Java 11 introduced JVM level support for private access classes using two new terms “NestMembers” and “NestHost”.”NestMembers” corresponds to nested classes and “NestHost” corresponds to the enclosing outer class. From Java 11 onwards we use these terms for bridging to use the private member of a class as well.

Lets see what we have in these files After Java 11

javap -v Test.class
SourceFile: ""
  public static #6= #5 of #3;             // NestedTest=class Test$NestedTest of class Test
javap -v  'Test$NestedTest.class'
SourceFile: ""
NestHost: class Test
  public static #23= #5 of #15;           // NestedTest=class Test$NestedTest of class Test

Here we can see that in the compiled file we have NestHost and NestMembers which helped us to access the private members as it does not effect the end user but helps at a JVM level.

Hope this blog will help you.

Happy Coding !!!



Written by 

Sanjana Aggarwal is a Software Consultant at Knoldus Software LLP, having experience of more than 1.5 years. She has done MCA from Bharati Vidyapeeth Institute of Computer Application and Management, Paschim Vihar. She has a decent knowledge of Java, Scala, Lagom, Kafka, Cassandra, Cocuhbase, MongoDB, Akka and Akka HTTP. She loves reading books and cooking and traveling.