JVM的内存模型
JVM运行Java程序时,会把它管理的内存大致划分5个区域。
其中,堆和方法去是线程共享,其他是线程隔离(线程私有)。
程序计数器
当前线程执行的字节码的行号指示器。
虚拟机栈
虚拟机栈的生命周期与线程保持一致。
虚拟机栈主要针对的是执行方法时产生的内存消耗。
每个方法在执行时会创建一个栈帧Stack Frame,用于存储局部变量、操作数和方法出口等。
每一个方法的调用和退出,都对应着一个栈帧在虚拟机栈中的入栈和出栈。
本地方法栈
VM Stack和Native Method Stack的区别是:VM Stack用于服务Java方法,Native Method Stack用于服务本地方法。
堆
堆是JVM中最大的一块内存区域,堆是被所有线程共享的一块内存区域。
堆在JVM启动时创建,主要用于存放对象。
堆是GC管理的主要区域,有时候也被称为GC堆。
堆只需要逻辑上连续,物理上可以不连续。
堆内存溢出
年老代溢出的原因:循环上万次的字符串处理、创建千万个对象和申请超大内存。
持久区Permanent Space溢出的原因:动态加载了大量类而导致溢出。
方法区
Method Area和Heap一样,也是线程共享的。
方法区存放:已记载的类的信息(类的版本、方法和接口等)、静态变量和常量等。
运行时常量池( Runtime Constant Pool )属于方法区的一部分。
方法区和永久代
HotSpot的GC的分代收集扩展到了方法区,为了省去专门为方法区编写内存管理代码,HotSpot VM 将方法区看做堆的一部分,并称
方法区为持久代(永久代)Permanent Generation。
对于其他VM( IBM J9、BEA JRockit ),不存在永久代的说法。
存储位置
new出来的对象放在堆中
成员变量放在堆中
方法中的局部变量放在栈中
Java的四种引用
1、强引用
强引用不会被垃圾回收器回收,即使当前内存空间不足,JVM 也不会回收它,而是抛出 OutOfMemoryError (OOM)错误,使程序异常终止。
如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象
2、软引用
软引用只有在内存不足时才会被垃圾回收器回收。
3、弱引用
JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。
4、虚引用
就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。
使用场景举例:利用软引用和弱引用解决OOM问题
我们可以用一个HashMap来保存图片路径和图片对象的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,
从而有效地避免了OOM的问题。
类的加载过程
类的生命周期7阶段
类的加载过程5阶段
1 加载
(1) 根据类名获得定义该类的二进制字节流
(2) 将字节流的静态存储数据结构转化为方法区的运行时数据结构
(3) 在内存中生成一个 java.lang.Class 对象,作为访问该类的入口。
2 验证
验证是连接阶段的第一步,主要目的是为了确保类的二进制字节流文件中包含的信息符合虚拟机的要求,且不会危害虚拟机。
(1) 文件格式验证
(2) 字节码验证
(3) 符号引用验证
3 准备
在方法区中为类变量分配内存和设置初始值
4 解析
将常量池中的符号引用转化为直接引用
5 初始化
类加载器
1 bootstrap
最先启动的类记载器是 bootstrap ,用于加载 JAVA 基础类库:jre/lib/rt.jar 。
2 ExtClassLoader
再启动类记载器 ExtClassLoader ,用于加载扩展类库:jre/lib/ext/*.jar 。
3 AppClassLoader
最后启动 AppClassLoader ,用于加载用于用户自定义类,即 classpath 指定的jar或者目录。
父亲委托机制
1 当前 ClassLoader 首先检查该类是否已经加载,如果是,则直接返回原来已经加载的类。
2 当前 ClassLoader 的缓存中没有找到该类,则委托父类加载器去加载,父类加载器采用同样的策略,直到 bootstrp ClassLoader 。
3 若所有父类加载器都没有加载过该类时,则由当前 ClassLoader 进行加载,并将其放入自己的缓存中。
为什么需要父类委托机制记载类?
加强 ClassLoader 之间的交流,实现类的共享,避免重复加载。
注
在 “父亲委托机制” 中,ExtClassLoader 是 AppClassLoader 的父亲,但 AppClassLoader 并非继承自 ExtClassLoader,AppClassLoader 和 ExtClassLoader 都继承自 URLClassLoader 加载器。
JVM知识点
什么是Java虚拟机?
JVM是一个可以执行Java字节码文件的虚拟计算机。
为什么Java被称作是“平台无关的编程语言”?
Java源文件会先被编译成能被JVM执行的字节码文件,再在JVM中执行。
而JVM有各个版本以适应不同的系统,所以各平台都能执行。
JDK和JRE的区别是什么?
JRE:Java运行时环境
JDK:Java开发工具包,包含了JRE、编译器、调试器等。