类加载过程代码实例

来源:互联网 发布:java常用api详解 编辑:程序博客网 时间:2024/06/06 02:21
package com.it;/** * Man load 加载 * @author mmry * */public class ManLoad extends User { /*class文件结构 对象结构*/  /*class常量池 utf-8 string int long float double  字母量和变量名字,描述符 class  field_ref  method-ref interface 其他符号引用 string直接生成string对象*/  /*运行时常量池  加载的时候   符号引用转换为方法区内存的直接引用。转换   方法运行的时候,动态的指向运行时常量池的直接引用。指向  User user=new Man();     user.say();    // #71 class字节码是 User say()  public 运行时找动态引用    #60  Man say() public  ox0140 _2   全局字符串常量池 哈哈 指向同一个对象。 */   /*--类的加载过程 包括类变量 -----加载 class对象 和验证交叉进行,写入方法区。 -----验证  文件格式 元数据  字节码  符号引用 -----准备  分配内存 ,方法表(自己的,父类的内存地址) -----解析  符号引用转换为直接引用。指向方法区内存 ,静态解析。class常量池里面的符号引用  解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程 -----初始化 clinit方法 -----解析  动态解析。动态链接。方法里面的符号引用*/ /* 方法区类 1 运行时常量池 运行时常量池属于每个类的,指向方法区内存的直接引用。 2 元数据信息,类接口信息,所有方法信息,所有字段信息, (包括继承的吗) 3 class对象引用,classloader引用 4 方法表,包括继承父类的 5 类变量  栈帧 1局部变量表,指向堆引用 2操作数栈 3动态链接,指向运行时常量池。修改指向不同的直接引用。 5 计数器 6方法出口其他信息  堆 分代垃圾回收  */  //  方法引用 字段引用 静态引用 动态引用    String s="哈哈";  //字段引用    String s2="哈哈";  //字段引用    User u; //类字段引用 //静态引用 private void smoke() {      System.out.println("我会抽烟"); }  //静态引用 private void smoke(String s) {      System.out.println("我会抽"+s); }  //动态引用    public void say() {      System.out.println("我是Man"); }       /*  先看方法,在看实际类型    如果是私有方法 构造方法 final方法 super方法,直接执行    其他的就看实际类型*/    public static void main(String[] args) throws InterruptedException {       //方法运行时,动态会解析 #57  #60 等符号引用,指向运行时常量池里解析过的地址。         ManLoad man=new ManLoad();         man.start();     // #57 class字节码是 Man start() private 运行时找静态引用    ox0140_3         man.say();        // #60   class字节码是 Man say() public  运行时找动态引用  ox0140 _2         man.smoke();      //#62  class字节码是 Man smoke() private 运行时找静态引用  ox0140 _4          man.smoke("大麻"); // #66  class字节码是 Man smoke(s) private 运行时找静态引用  ox0140 _5         man.eat();        // #75   class字节码是 Man eat()   public 运行时找动态引用 User  eat()  0x0133_3         System.out.println(man.name);                    User user=new ManLoad();            user.say();    // #71 class字节码是 User say()  public 运行时找动态引用    #60  Man say() public  ox0140 _2         System.out.println(user.name);            Thread.sleep(100*1000);         }  private void start() { //方法引用        System.out.println("开始 "); }   /*方法区类加载 //方法表 start say  main  继承object的方法  Constant pool: 运行时常量池 加载 解析阶段        类加载时,把class常量池复制到运行时常量池, 符号引用转换为内存地址,直接引用      方法运行时,把字节码里面的符号引用。 指向直接引用。动态改变指向直接引用。  *    符号引用                                  内存直接引用     #1 = Class         ox0140          //  com/it/Man     #3 = Class         0x0133          //  com/it/User      #56 = Methodref     ox0140 _1          //  com/it/Man."<init>":()V    #57 = Methodref     ox0140 _3           //  com/it/Man.start:()V    #60 = Methodref     ox0140 _2         //  com/it/Man.say:()V    #62 = Methodref    ox0140 _4           //  com/it/Man.smoke:()V    #66 = Methodref    ox0140 _5        //  com/it/Man.smoke:(Ljava/lang/String;)V    #71 = Methodref     0x0133 _2          //  com/it/User.say:()V             #74 = Fieldref      0x0133 _4           //  com/it/ManLoad.name:Ljava/lang/String;       #17 = Fieldref      ox0140 _6          //  com/it/ManLoad.s:Ljava/lang/String;             #75 = Methodref     0x0133_3         //  com/it/ManLoad.eat:()V 类信息 加载阶段 Man     ox0140     User    0x0133 Object  0x0033   字段信息 (是否包括继承的字段?不包括继承的字段name age )  加载阶段 String s   ox0140 _6   String s2  ox0155   User u  方法信息(不包括继承的方法eat()) 加载阶段符号引用:在静态引用如 私有方法,静态方法,构造方法,父类方法,可以确定的,直接转换为直接引用          动态引用。在不能确定方法,都是在运行时看实例类型决定使用哪个方法的直接引用。 say()  字节码指令   ox0140 _2     start()  字节码指令     ox0140_3 smoke()  字节码指令   ox0140 _4  smoke(s) 字节码指令  ox0140 _5  类变量信息  准备阶段和初始化阶段 无   方法表信息 解析阶段 say()      ox0140 _2     start()    ox0140_3 smoke()    ox0140 _4  smoke(s)   ox0140 _5 eat()      0x0133_3 继承方法  */  /* 先调用父类构造方法,在初始化自己的成员变量          父类构造方法,会初始化父类的成员变量  * public com.it.ManLoad();     flags: ACC_PUBLIC     Code:       stack=2, locals=1, args_size=1          0: aload_0          1: invokespecial #13                 // Method com/it/User."<init>":()V  先调用父类构造方法          4: aload_0          5: ldc           #15                 // String 哈哈          7: putfield      #17                 // Field s:Ljava/lang/String;         10: aload_0         11: ldc           #15                 // String 哈哈         13: putfield      #19                 // Field s2:Ljava/lang/String;         16: return       LineNumberTable:         line 9: 0         line 64: 4         line 65: 10         line 9: 16       LocalVariableTable:         Start  Length  Slot  Name   Signature                0      17     0  this   Lcom/it/ManLoad;*/ }package com.it;public class User { String name="张三"; int age=18;  public void say() {     System.out.println("我是user"); }  public void eat() {      System.out.println("我是user eat"); }  //方法表   say 继承object的方法    /*Constant pool:                  #1 = Class         0x0133        //  com/it/User                                           #3 = Class         0x0033        //  java/lang/Object                                    */  /*  *  类 User    0x0133 Object  0x0033  字段信息 String name  0x0133 _4 int age      0x0133 _4  方法信息
符号引用:在静态引用如 私有方法,静态方法,构造方法,父类方法,可以确定的,直接转换为直接引用          动态引用。在不能确定方法,都是在运行时看实例类型决定使用哪个方法的直接引用。
 say() 字节码指令 0x0133_2 eat() 字节码指令 0x0133_3 方法表 say() 字节码指令 0x0133_2 eat() 字节码指令 0x0133_3 继承方法 */}

0 0
原创粉丝点击