• JVM类加载机制和内存模型


    一.JVM类加载机制

      首先需要了解一下类加载器(ClassLoader)

        ClassLoader是Java的一个核心组件,它主要作用是从系统外部获得Class二进制数据流,然后将数据流装载到系统,交给JVM进行连接,初始化等操作,所有的Class都是有ClassLoader进行加载的。

        点开ClassLoader类,如下图所示:

        

      类加载器种类

        启动类加载器(BootStrapClassLoader):它用来加载 Java 的核心类,如java.xxx。

        扩展类加载器(ExtensionsClassLoader):它负责加载JRE的扩展目录,如javax.xxx。

        应用类加载器(AppClassLoader):它一般用来加载程序所在目录下的类。

        自定义类加载器:通过继承ClassLoader类实现自定义类加载器。

      双亲委派机制:

        虚拟机是根据类的全限定名来加载类的,那么有个问题,如果同时存在两个或多个全限定名完全一致的情况下,该如何选择加载哪个类?如何判断该类是否被加载过了?这都是双亲委派机制能做的。

        下图是双亲委派机制的实现(这是ClassLoader中的loadClass方法),很明显,parent也是一个类加载器。

        

        双亲委派机制原理:

          1.一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,直到启动类加载器

          2.启动类加载器检查能不能加载(使用findClass()方法),能就加载(结束);否则,抛出异常,通知子加载器进行加载。

        双亲委派机制的优点是:

          1.安全,可避免用户自己编写的类动态替换Java的核心类,如java.lang.String
          2.避免全限定命名的类重复加载(使用了findLoadClass()判断当前类是否已加载)

      附:Java跨平台实现的原理:Java源码首先被编译成字节码(不同平台编译后的字节码是一样的,因此在不同平台上运行时不需要重新编译),再由不同平台的JVM进行解析,将字节码转换成具体平台上的机器指令。

      类加载流程:

        加载:通过ClassLoader加载class文件字节码,生成Class对象

        连接:检查加载的class文件的正确性和安全性;为类变量分配存储空间并设置类变量初始值;JVM将常量池内的符号引用转换为直接引用

        初始化:执行类变量赋值和静态代码块

      类加载的方式:

        隐式加载:通过new关键字来创建实例对象。

        显式加载:

          通过Class.forName()来加载类,它得到的是已经初始化完成的class

          通过类加载器的loadClass()方法来加载类,它得到的class还没有完成连接过程

    二.JVM内存模型

       

      所有线程共享的内存数据区:方法区,堆。而虚拟机栈,本地方法栈和程序计数器都是线程私有的。

         1、存放于栈中的:

          每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(如变量的名字)。

          每个栈中的数据(基础数据类型和对象引用)都是私有的,其他栈不能访问。

          方法的形式参数,方法调用完后从栈空间回收。

          引用对象的地址,引用完后,栈空间地址立即被回收,堆空间等待GC。

         2、存放于堆中的:

           存储的全部是对象,每个对象包含一个与之对应的class信息

          Jvm只有一个堆区(heap)被所有线程共享,堆区中不存放基本类型和对象引用,只存放对象本身

         3、存放于方法区中的:

          存放线程所执行的字节码指令

          跟堆一样.被所有线程共享.方法区包含:static变量

      注意:Class实例在jdk1.6及之前是存放在方法区中, 在jdk1.7及之后存放在堆中

         常量池在jdk1.6及之前是存放在方法区中,在jdk1.7存放在堆中,在jdk1.8存放在元空间中

  • 相关阅读:
    git基本使用
    list和tuple
    牛客(60)把二叉树打印成多行
    牛客(59)按之字形顺序打印二叉树
    牛客(58)对称的二叉树
    牛客(57)二叉树的下一个结点
    牛客(56)删除链表中重复的结点
    牛客(55)链表中环的入口结点
    mybits(1)配置
    牛客(53)表示数值的字符串
  • 原文地址:https://www.cnblogs.com/ywb-articles/p/11219325.html
Copyright © 2020-2023  润新知