work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

JVM常量的含义与反编译助记符详解

Posted on 2019-06-07 22:27  work hard work smart  阅读(247)  评论(0编辑  收藏  举报

1、定义一个常量

public class MyTest2 {
    public static void main(String[] args) {
        System.out.println(MyParent2.str);
    }
}

class MyParent2{

    public static final String str = "hello world";

    static {
        System.out.println("MyParent2 static block");
    }

}

  打印结果:

hello world

  此时MyParent2类不会进行实例化,因为str是一个常量。常量在编译阶段,会存如调用这个常量的方法所在类的常量池中。本质上,调用类并没有直接引用到定义常量的类,因此并不会触发定义常量的类初始化。 

注意: 这里值的是将常量str存放到MyTest2类的常量池中,之后MyTest2和MyParent2就没有任何关系了。甚至,我们可以将MyParent2的class文件删除。

 

2.使用javap反编译class文件(jdk版本1.7)

命令:javap -c MyTest2.class

 3: ldc           #3                  // String hello world

说明System.out.println(MyChild1.str); 这行代码已经成为hello world

 

 

3、增加一个short类型的常量

public class MyTest2 {
    public static void main(String[] args) {
        System.out.println(MyParent2.s);
    }
}

class MyParent2{

    public static final String str = "hello world";

    public  static final short s = 8;


    static {
        System.out.println("MyParent2 static block");
    }

}

  反编译

此时已经变为bipush

 

 

4、助记符:

1)、ldc表示将int,float或是String类型的常量值从常量池中推送至栈顶。 (public static final String str = "hello world";)

2)、bipush 表示将单字节(-128 ~ 127)的常量推送至栈顶(public static final short s = 8;)

3)、sipush表示将一个短整型常量值(-32678 ~ 32676)推送至栈顶 (public static final int  i = 128;)

4)、iconst_1 表示将int类型的1推送至栈顶(iconst_m1, iconst_0, iconst_1 ~ icont_5      -1到5)(public static final short m = 1) 

 

   

 

5、助记符相关的类

每个助记符都有相关的类

1)LDC

 

2) ICONST.java源码

在包com.sun.org.apache.bcel.internal.generic;下

 

 

6、编译期常量与运行期的常量的区别

创建MyParent3类,里面有一个常量,但这个常量是UUID

public class MyTest3 {
    public static void main(String[] args) {
        System.out.println(MyParent3.str);
    }
}

class MyParent3{
    public  static  final  String str = UUID.randomUUID().toString();

    static {
        System.out.println("MyParent3 static code");
    }
}

  打印输出:

MyParent3 static code
a8be85e9-ef3c-4fd9-88aa-56b2c377a25c

  总结: 当一个常量的值并非编译期间可以确定的,那么其值就不会被放到调用类的常量池中,这时在程序运行时,会导致主动使用这个常量所在的类,显然会导致这个类被初始化