zoukankan      html  css  js  c++  java
  • JVM常量的含义与反编译助记符详解

    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
    

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

  • 相关阅读:
    Oracle分页查询
    Oracle表空间
    Oracle中DBA常用操作
    数据库的约束
    数据库设计的三范式
    数据类型的比较 有四种情况
    github快速上手
    3D正方体做法
    animation-声明关键帧
    轮播图样式
  • 原文地址:https://www.cnblogs.com/linlf03/p/10989311.html
Copyright © 2011-2022 走看看