类加载过程

来源:互联网 发布:小马云现身阿里总部 编辑:程序博客网 时间:2024/06/07 09:02


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
原创粉丝点击