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.所有非static final字段
2.所有使用的字段 //在另外一个类的方法中写引用常量
public class m{
public void fun1(){
sout(MyC1.f1);//之前定义的静态字段,只有1个字面量,没有field常量
sout(MyC1.f2);//发现同时出现
}
}
字面量: 数据类型是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的常量在本类 都会出现
包装类 在本类 字面量出现
在其他用包装类 都会出现
‘
-
![在这里插入图片描述](https://img-blog.csdnimg.cn/bc01ff44ac1248b1b2f23921d0af2f96.png#pic_center)
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;}
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;}
}
}
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");
}
6.this(本类的索引)这是表示本类的索引 必须是CONSTANT_Class_info
u2 this_class;
//一般信息-->本类索引,是本类的全限定类名称
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
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;
10.这个filed与 CONSTANT_Fieldred_info的区别
//字段的引用是指等号右边 10
//field是字段的定义 a
int a=10; // 定义什么类型都要出来,不像引用
- 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();
- Signature 泛型签名
属性名
签名索引
//在字段查看Signature
ArrayList strings; //签名索引显示 Ljava/util/ArrayList<Ljava/lang/String>; HashMap<Integer,MyC1> //
Ljava/util/HashMap<Lxxx/Integer;Ltop/jamsee/beans/MyC1;>;
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());//查看注解反射名称
}