I try to new a inner staic class, But I find that bytecode appear the jvm instruction ACONST_NULL
bwteen NEW
,DUP
and INVOKE_SPECIAL
,
But I know about a class new is
- NEW
- DUP
- INVOKE_SPECIAL
package com.hoho.api;
/**
* @author linuxea
*/
public class Main {
private static class InnerMain {
// no field
}
public static void main(String[] args) {
InnerMain innerMain = new InnerMain();
}
}
// class version 52.0 (52)
// access flags 0x21
public class com/hoho/api/Main {
// compiled from: Main.java
// access flags 0xA
private static INNERCLASS com/hoho/api/Main$InnerMain com/hoho/api/Main InnerMain
// access flags 0x1008
static synthetic INNERCLASS com/hoho/api/Main$1 null null
// access flags 0x1
public <init>()V
L0
LINENUMBER 6 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/hoho/api/Main; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static main([Ljava/lang/String;)V
// parameter args
L0
LINENUMBER 13 L0
NEW com/hoho/api/Main$InnerMain
DUP
ACONST_NULL
INVOKESPECIAL com/hoho/api/Main$InnerMain.<init> (Lcom/hoho/api/Main$1;)V
ASTORE 1
L1
LINENUMBER 14 L1
RETURN
L2
LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
LOCALVARIABLE innerMain Lcom/hoho/api/Main$InnerMain; L1 L2 1
MAXSTACK = 3
MAXLOCALS = 2
}
Why
L0
LINENUMBER 13 L0
NEW com/hoho/api/Main$InnerMain
DUP
ACONST_NULL
INVOKESPECIAL com/hoho/api/Main$InnerMain.<init> (Lcom/hoho/api/Main$1;)V
ASTORE 1
What is the ACONST_NULL
?
This is the way how
javac
solves private member access problem before JDK 11.InnerMain
is declared private, and it has private default constructor:According to the JVM specification, no class may access private members of other classes, but according to Java language rules,
Main
should be able to access private members ofInnerMain
. To solve this problem,javac
generates a synthetic package private bridge constructor. To ensure this constructor is not called directly from user code, compiler adds a dummy classMain$1
in the signature:When you write
new InnerMain()
, the compiler actually calls this bridge constructor. The actual value of the dummy argument does not matter, so it's just set tonull
- henceACONST_NULL
instruction:Note that bridge methods are not needed when the inner class is public or package private.
Since JDK 11, a fundamentally new mechanism was introduced, see JEP 181: Nest-Based Access Control. Now, if you compile your Main class with JDK 11 or newer,
Main
andInnerMain
will become nestmates and will be able to access private members of each other without bridge methods and synthetic classes.