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
    

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

  • 相关阅读:
    【BZOJ】2100: [Usaco2010 Dec]Apple Delivery(spfa+优化)
    【BZOJ】2101: [Usaco2010 Dec]Treasure Chest 藏宝箱(dp)
    【BZOJ】3404: [Usaco2009 Open]Cow Digit Game又见数字游戏(博弈论)
    【BZOJ】3403: [Usaco2009 Open]Cow Line 直线上的牛(模拟)
    【BZOJ】3402: [Usaco2009 Open]Hide and Seek 捉迷藏(spfa)
    【BZOJ】3400: [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队(dp)
    【BZOJ】3399: [Usaco2009 Mar]Sand Castle城堡(贪心)
    【BZOJ】3392: [Usaco2005 Feb]Part Acquisition 交易(spfa)
    【BZOJ】2020: [Usaco2010 Jan]Buying Feed, II (dp)
    【BZOJ】2015: [Usaco2010 Feb]Chocolate Giving(spfa)
  • 原文地址:https://www.cnblogs.com/linlf03/p/10989311.html
Copyright © 2011-2022 走看看