你的位置:首页 > Java教程

[Java教程]JVM类加载机制


    1. JVM类加载机制

      1. 目录:

        1.  

           

        1. JVM加载的过程

          1. 加载

            1. 为什么需要加载?

            2. 加载什么?

            3. 怎么加载?

              1. JVM加载类的工具

                1. 系统自带工具

                  1. Bootstrap,根加载器(C++),程序员不可见

                  2. 扩展类加载器(Java),程序员可见

                  3. 系统加载器(Java),程序员可见

                2. 用户自定义工具

               

            4. 加载的结果是什么?

          2. 连接

            1. 验证『万一要是用户自己写的加载器加载的.class文件不符合JVM规范怎么办?--验证之』

            2. 准备『给类的静态变量分配内存,并且设置默认值』

            3. 解析

          3. 初始化『JVM遇到6种情况的时候,就会初始化类,把用户给的值赋值给对应的变量』


    2. 为什么需要加载?--java程序经过编译成. class文件,再装在到内存里面(由classloader执行),这样才能执行java程序

      1. 演示程序
         
         
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        package classloader;
         
        public class Singleton {
         
            //这边的内存图是怎么画的?自己里面创建自己是怎么回事?
            private static Singleton singleton=new Singleton();
            public  static int counter1;
            public  static int counter2=0;
            private Singleton(){
                counter1++;
                counter2++;
            }
             
            public static Singleton getInstance(){
                return singleton;
            }
             
        }


         

      2. 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        package classloader;
         
        public class MyClass {
        public static void main(String[] args) {
            Singleton singleton=Singleton.getInstance();
            System.out.println("counter1-"+singleton.counter1);
            System.out.println("counter2-"+singleton.counter2);
        }
             
        }


         

      1. AWT,聊天程序中可以使用该方法


    3. 加载                                          

      1. 加载什么?--class 文件从硬盘到内存的迁移

        1. 也就是在堆区域创建一个Class类的对象『类的名称是 Class』

        2. Class对象是JVM在加载对应的类文件 到方法区之后,在堆区  生成一个与该类文件对应的Class对象。强调:不管这个类生成多少个对象,狱该类对应的Class对象只有一个

        3. Class对象可以封装类在『方法区』内的数据结构:类里面的内容,都可以通过Class对象获得,像镜子一样,是整个反射的入口,可以看到目标类的关联的class结构,通过Class对象可以访问目标类的字段和方法

      2. 怎么加载?

        1. 加载方式

        2. 加载的工具

            1. 根类加载器C++,系统类加载器和扩展列加载器是java

            2. Classloader类,将二进制名称转换成文件名,然后尝试着从文件系统读取该名称的.class文件

            3.  

              1
              2
              3
              4
              5
              6
              7
              8
              9
              10
              11
              12
              13
              14
              15
              package classloader;
                
              public class Test1 {
                
                  public static void main(String[] args) throws ClassNotFoundException {
                      Class clazz=Class.forName("java.lang.String");
                      System.out.println(clazz.getClassLoader());//输出null
                      //获得String类的加载方式,null标明是由根加载器Bootstrap加载的,由C++编写
                    
                      Class class1=Class.forName("classloader.Singleton");
                        
                  System.out.println(class1.getClassLoader());//输出sun.misc.Launcher$AppClassLoader@105d88a
                    
                  }
              }


               

               
        3.  

           

        4. 加载的结果

          1.  

      3.  


        连接:

        1. 即本来用javac进行编译,但是有些人自己编译,生成的字节码文件不符合jvm对字节码文件的规范,因此需要检测

        2. 强调静态变量(static):此时对象还不存在,此时还不涉及实例方法。静态变量不属于某一个对象,是属于一个类的,所有的该类的对象都可以调用该静态变量。因此在该类加载到内存的时候,就可以给给静态变量分配内存了,并且初始化为默认值 boolean类型:false,int 类型:0等

        3. 【感觉像是一个屋子在规划的时候,就要划分好公共空间,之后要是有具体的别人住进来之后,可以根据不同人的不同的需求在各自的地方进行活动,但是公用的部分一定是在建设一始就划分好的,比如小区的公园和卫生间,并且要公园里面的花花草草给弄好,不能说就建了一个花园的大概的外围,里面什么都不搞,连地都不松一下土,这不行,还有比如卫生间,也是要把里面的设备搞齐全了,冲水的设备,纸篓都要放好,不能等业主进来了使用的时候才发现,“我擦,怎么什么都只是空样子”!至于后来小区业主进来了,可以在自己家里面再搞其他的花草什么的别人也管不了,】

        4. 解析:之后再说


           

      4. 初始化:这个不和『连接』里面的『准备』重复吗?

        1. 不重复

        2. 因为此时是把用户想赋的值赋值给静态变量

        3. 举例:

          1
          2
          3
          4
          public class Test{
               
               private static int i=3;
          }


        4. 首先,JVM会在『连接』的准备阶段 执行  『i=0』。准备阶段结束,执行解析,解析结束之后
        5. 解析完成,执行『初始化』:把3显示赋值给i;
        6. 1
          2
          3
          4
          5
          6
          7
          8
          public class Test{
               
              private static int i;
              static
              {
                  i=3;
              }
          }



        7. 此时完成类的初始化,此时仍然没有对象的生成


          1. new Test();

          2. int b=Tetst.a;或者 Test.a=b;

          3. Class.forName("classloader.Test");

          4. 1
            2
            3
            4
            5
            6
            7
            8
            class Father
            {}
             
            class Child extends Father
            {
                public static int i;
            }
            Child.a=3;


            启动类:含有main方法的类

 



来自为知笔记(Wiz)