• 05.jvm常量池02


    1.double

    CONSTANT_Double_info{
    u1 tag;
    u4 high_bytes;
    u4 low_bytes; }

    2.fieldref_info(字段的使用)与字面量类型常量的规则(既是常量又是字段)

       static final float f=15.5.f;//冲突,会不会同时出现?,这里不可以,因为规则
       float f3=25.5f;//float字面量和fieldref可以同时出现
       static float f2=25.5f;//也可以同时出现
    
    • 1
    • 2
    • 3

    1.所有非static final字段
    2.所有使用的字段 //在另外一个类的方法中写引用常量

       public class m{
                public void fun1(){
    	            sout(MyC1.f1);//之前定义的静态字段,只有1个字面量,没有field常量
                    sout(MyC1.f2);//发现同时出现
    
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
     }
      字面量: 数据类型是String以及基本数据类型,及其包装类
       1.static final修饰的字面量在本类和其他类里面都会以字面量类型的常量出现
       2.非static final修饰的字面量在本类 以字面量常量和fieldref_info类型的常量出现
          ,其他类以 fieldref_info类型的常量出现
      非字面量: 引用类型,(包装类算引用类型,字面量的包装类型)不能以字面量出现,只有string_info
         
       3.(是不是static final 都可以)引用类型在本类和其他类里面都会以fieldref_info出现
           static final C3 c_3=new C3(); //fieldref_info能出来,
          static  C3 c_4=new C3();
       自己总结:(看不到的,都只出现1个)
             1. static final 字面量 在本类和其他类  出现字面量常量
                                             在本类和其他类 关于包装类 都会出现                                                                              
             2.除static final的常量在本类 都会出现
                                             包装类 在本类 字面量出现
    	             在其他用包装类  都会出现
                                             
    
      ‘
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    •                ![在这里插入图片描述](https://img-blog.csdnimg.cn/bc01ff44ac1248b1b2f23921d0af2f96.png#pic_center)
      
      • 1

    2.字段与字段类型或方法与方法类型(字段也包括方法)与Methodref_info连接起来

    CONSTANT_NameAndType_ info{
    u1 tag;
    u2 name_index;//指向utf-8,构造方法用
    u2 descriptor_index; //字段类型的描述符
    }

    //创建一个类,查看 <()V> ,V代表返回void,()代表没有参数

        int a=10;#出现 字段名a    描述符I  类型是int  ,也使用了
                 //方法必须调用才能出现
        public void fun1(){
    	int a=func2();//调用后出现, 方法名func2  描述符()I代表返回int
    	C19 c18=fun3(1,2)//  方法名func3 描述符(II)Ltop/jamsee/C18;  #代表里面方法参数是2个int,返回C18引用类型
    
        }
         public int fun2(){return 0;}
         public C19 func3(int a,int b){return null;}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.utf-8(不是字符串常量,这个jvm认为需要存数据的地方)

    CONSTANT_Utf8_info{
    u1 tag;
    u2 length;
    u1 bytes[length];//字符串是byte的数组
    }

    //直接建空类一个看 //有init<> ()V Code LineNumberTable this // L
    top/jamsee/C19 本类的描述符 SourceFile C19.java源代码名 top/jamsee/C19 //
    java/lang/Object

    4.动态类型语言支持(了解)

    CONSTANT_MethodHandle_info{ u1 tag;
    u1 reference_kind; // $0表内部类
    u2 reference_index; }

    CONSTANT_MethodType_info{
    u1 tag; u2
    descriptor_index;#方法的描述符,输入,返回值
    }

    CONSTANT_InvokeDynamic_info{ u1 tag;
    u2 bootstrap_method_attr_index;#调用点#0,启动的点
    u2 name_and_type_index;
    }

       class xxx{
             interface A{
             	int add(int a,int b);
              }
             public void fun1(){
                //lambda表达式,实现run方法
    			Runnable runnable=()-> System.out.println("ok");
    			//MethodHandle_info偷偷调用方法常量支持的方法
    		 A a=(a,b)->{ return a+b;}
       
             }
    
               
    
    
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    5.类的access_flags是有标志所构成的掩码,表示类或者接口的访问权限

    1.分类(jvm规范)(描述类,字段方法的访问权限)
    标志名 值 含义
    ACC_PUBLIC 0x0001 声明为public,可以从包外访问
    ACC_FINAL 0x0010 声明final,不许有子类
    ACC_SUPER 0x0020 用 invokespecial指令,需要对父类方法做特殊处理
    ACC_INTERFACE 0x0200 规定class是接口不是类
    ACC_ABSTRACT 0x0400 abstract 不能被实例化
    ACC_SYNTHETIC 0x1000 声明synthetic,表class文件不是有java源代码生成,其他语言转换而来
    ACC_ANNOTATION 0x2000 为@interface 注解
    ACC_ENUM 0x4000 为枚举类型

         //写个普通类,看一般信息
        //访问标志 看到0x0021 [public], jdk8以后给每个类加ACC_SUPER	
       // 所以是      ACC_PUBLIC 0x0001+ACC_SUPER  0x0020= 0x0021
       //类加个final
          public final class xx{}     0x0031 [public final] //累加的
        //加abstract
        public abstract class xx{}    //0x0421
        //ACC_SYNTHETIC   例子,lambda表达式,不是java写的
         //在jcclasslib的方法的中找lambda$fun1$0可以找到这个描述符号
         public void fun1(){
     Runnable runnable=()-> sout("xxx");
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6.this(本类的索引)这是表示本类的索引 必须是CONSTANT_Class_info

      u2 this_class;
      //一般信息-->本类索引,是本类的全限定类名称
    
    • 1
    • 2

    7.super父类索引

    u2 super_class;

    1.super_class为0 object为父类
    2.super_class为一个索引指向CONSTANT_Class_info类型表示他的父类
    3.!!! 对于接口,super_class索引必须指向Object的CONSTANT_Class_info的结果
    (注意不能证明是object的父类)

        public  class xx extends aa{} //一般信息可以看到指向全限定名称
        public class xx{} //跳转到object类发现#0,#0不让我们看
        public interface xx{}//是object 
        public interface xx extends xx1{}//继承   是object 
         public interface xx extends xx2{}//多继承还是 object,所有接口的引用是object
    
    • 1
    • 2
    • 3
    • 4
    • 5

    8.本类interface

    //因为接口是多继承,区别于 this_class和super_class u2 interfaces_count
    //记录一个类有多少个接口 u2 interfaces[interfaces_count]

    //一般信息—>接口计数, 写个普通类实现接口,多实现 public class xx extends xx
    implements xx,xx{}

    9.field

    field _info field[field _count]; //复合的数据结构 u2
    field _count;

    //field _info内容 field _info{
    u2 access_flags; #权限
    u2 name_index; #字段名称
    u2 descriptor_index; #字段的描述符
    u2 attribute_count; #属性 attribute_info attributes[attributes_count]; }

    //access_flags;9总标记与类区别
    ACC_PUBLIC 0x0001
    ACC_PRIVATE 0x0002
    ACC_PROTECTED 0x0004
    ACC_STATIC 0x0008
    ACC_FINAL 0x0010
    ACC_VOLATILE 0x0040 解决内存可见性问题
    ACC_TANSIENT 0x0080 修饰的不能被序列化
    ACC_SYNTHETIC 0x1000 不是java编译产生
    ACC_ENUM 0x4000

    //写个2个类,在一般信息可以看3个字段
     public  static float b=11.1f; 
     //u2 access_flags;  #权限 0x0009
     //u2 name_index;  #字段名称  b
     //u2 descriptor_index;  #字段的描述符 F代表是float类型 ,引用类型是Ljava/lang/String;
     public int a=10;
     MyC2 c=new MyC2();
      int [] a1; //描述符是[I
      Integer i; //标识符是 Ljava/lang/Integer;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    10.这个filed与 CONSTANT_Fieldred_info的区别

     //字段的引用是指等号右边   10
     //field是字段的定义              a
       int a=10;    // 定义什么类型都要出来,不像引用
    
    • 1
    • 2
    • 3
    1. attribute_info attributes[attributes_count];

    attribute_info{
    name_index
    attributes_count
    attributes_info #指向ConstantValue 表示静态变量的初值 static final,值并且是String类型而且不能是new }

    ConstantValue_attribute{
    u2 attribute_name_index; //固定的 ConstantValue
    u4 attribute_length; //固定的
    u2 constantvalue_index; //指向String,最终的初值 }

    //在工具的字段的查看 public static final float c=25.5f; //
    public static final String s=“aaa”; //ConstantValue出不来因为不能new,不能是对象,他需要的是值
    public static final String s= new String(“bbb”); //不能是引用类型
    Interger i=10; 等同于 Interger i=new Interger();

    1. Signature 泛型签名
      属性名
      签名索引

    //在字段查看Signature
    ArrayList strings; //签名索引显示 Ljava/util/ArrayList; HashMap //
    Ljava/util/HashMap;

    13.Deprecated

    Deprecated_attribute{
    u2 attribute_name_index;
    u4 attribute_length;
    }

    //在工具的字段会有
    @Deprecated
    String aa=“XXX”;

    14.字段的注解(运行时可见的注解)(也是在字段查看)

    RuntimeVisibleAnnotations(可见的注解,必须为RetentionPolicy.RUNTIME的注解定义)
    {
    u2 attribute_name_index; #以下都是描述名称
    u4 attribute_length;
    u2 num_annotations;
    annotation annotations[num_annotations]
    }

    RuntimeInvisibleAnnotations如上结构(注解定义是RetentionPolicy.CLASS)

    @SupperssWarning(“xxx”)
    //不是RetentionPolicy.CLASS出不来,这个定义了RetentionPolicy.SOURCE,所以不能进入直接只能停留在java层面中
    String bb=“aaa”; //自己定义个注解 @Target({FIELD})
    @Retention(RetentionPolicy.CLASS) //保存的方式 re往回 ten拿 不断的拿–>保存
    public @interface M1{

    }
    @M1
    @M2 #可以是多个注解
    String c=“xx”;

    15.注解的生命周期(面试题)
    java --> class -->jvm(注解只能存活到java代码,以RuntimeInvisibleAnnotations或者不可见,不可以jvm使用反射获得信息)
    RetentionPolicy.SOURCE,只存在于源文件,不会到class字节码里面
    CLASS只把注解信息在字节码中不会加载到jvm中(默认值)
    RUNTIME 加载到jvm中,可以反射读取注解信息
    //案例通过反射,在不同周期的注解,可不可以通过反射得到注解信息
    //写一个注解 切换几个定义
    //写个测试类

        
         MyC3 myC3=new MyC3();
         Field a=myC3.getClass().getDeclaredField("a");  //得到类的字段(跨包)
        Annotation[] declareAnnotations =a.getDeclareAnnotations();
        for(Annotation annotation : declareAnnotations ){
                    sout(annotation.toString());//查看注解反射名称
       }
         
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    【535. TinyURL 的加密与解密】
    易点易动固定资产管理系统:实现全生命周期闭环式管理和快速盘点
    res.add(new ArrayList<>(path))和res.add(path)的区别
    Linux top命令的cpu使用率和内存使用率
    利用Jmeter做接口测试(功能测试)全流程分析
    java spring cloud 企业工程管理系统源码+二次开发+定制化服务
    DTCloud 复杂字段类型
    【设计模式】Java设计模式 - 桥接模式
    LeetCode每日一题(756. Pyramid Transition Matrix)
    【场外衍生品系列】雪球结构定价研究
  • 原文地址:https://blog.csdn.net/weixin_47039303/article/details/127909227