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存放在元空间中 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 如何将java.lang.float编码为TH3IFMw?
- 在Java 1.6中弃用
- 【SpringBoot】09.SpringBoot整合Freemarker
- java – JFrame如何工作?在内心深处,它如何绘制
- java – 有人可以解释Spring Security BasePermi
- java – Spring数据findFirstBy throws incorrec
- java – treemap vs arraylist – 迭代/添加/编辑
- Docke实例之搭建gitlab的方法
- java – 从另一个类检索int时获取null
- java – DynamoDBMappingException:没有HASH密钥