2021-09-03

JVM

介绍下Java内存区域(运行时数据区)
JDK1.6:堆区、方法区(运行时常量池)【堆区、方法区在JVM中只有一个所有线程共享】、【虚拟机栈、本地方法栈、程序计数器】[这三个线程私有]
JDK1.7:堆区(运行时常量池)、方法区、虚拟机栈、本地方法栈、程序计数器
JDK1.8以及之后:去除方法区,建立了一个独立于运行时数据区的元空间,建立在本地内存中。
程序计数器:是运行时数据区中唯一一块不会方式内存泄漏的内存区域,所以是线程的安全的。 保存当前要执行指令的指令号,一旦指令执行,计数器将更新到下一条要执行的指令的地址。
虚拟机栈:就是栈,每个方法都对应了一个栈帧,每个线程只能有一个活动栈帧,对应着当前正在执行的方法,该栈帧处于栈顶,虚拟机栈会发生内存溢出。
每个栈帧包括:
局部变量表:存储方法的局部变量。基本类型是存储值,对于引用类型的变量,存的是指向对象的引用。在编译器大小就确定了,在程序执行期间局部变量表的大小是不会改变的。
操作数栈:当前正在计算的数据会存入操作数栈,一次计算结束之后,操作数栈不会消失。
动态链接:在class文件中,描述一个方法调用或访问其成员变量是通过符号引用来表示,动态链接的作用就是将符号引用转换为直接引用
方法返回地址:作用就是需要返回到方法调用的位置,程序才能继续执行
本地方法栈:使用native修饰的方法为本地方法栈,本地方法不是由Java实现,而是由本地的动态库提供,可以是任意的语言,如C、C++;
虚拟机栈服务于Java方法(也就是class文件),而本地方法栈服务于Native方法。
堆区:Java虚拟机所管理的内存中最大的一块区域。用于存放对象实例和数组的内存区域。
堆是垃圾收集器只要管理的区域,都采用分代垃圾收集算法。堆分为Eden去和Servivor区。
堆内存溢出是Java项目非常常见的错误,java.lang.OutOfMemoryError:Java heap space:堆内存溢出错误。
方法区:JDC1.8之前使用永久代实现,JDC1.8之后使用元空间实现。
方法区用于存储类的结构:
运行时常量池(包括字符串常量)、静态变量、类的信息、常量
类信息包括:魔数、版本号、常量池、类(字段和方法)等。
方法区和堆区都是在JVM启动时创建。

如何判断对象是否死亡?
1) 引用计数器算法:指为对象添加一个引用计数器,当有一个地方引用该对象时,计数器+1,当引用失效,计数器-1,当计数器为0时表示该对象不再被引用。
2) 可达性分析算法:核心就是通过一个“GC Roots”的对象作为起始点,从这个节点向下搜索,搜索所走过的路径称为引用链。当一个对象到“GC Roots”没有任何引用链相连时,则证明该对象是不可用的。

Java中四种引用:
强引用(Reference):是代码中普遍存在的引用,一个对象具有强引用时,垃圾回收器绝对不会去回收它
软引用(soft):一个对象具有软引用时,只要空间足够就不会去回收它,不够时才回去回收它,只要不被回收,该对象就可以被程序使用。
弱引用(Weak):仅能够存活到垃圾回收之前,当垃圾收集时,一定会被回收无论空间是否足够。
虚引用(PhantomReference):虚引用并不会决定对象的生命周期,如果一个对象仅持有虚引用时,任何时候都可能被垃圾回收。虚引用必须和引用队列联合使用

如何判断一个常量时废弃常量?
运行时常量池主要回收的是废弃常量。如何判断:
假如在常量池中存在字符串“abc”,如果当前没有任何String对象引用该字符串常量的话,就说明“abc”是废弃常量,如果此时发生内存回收而且有必要的话,“abc”就会被清理出常量池。

如何判断一个类是无用的类?
方法区回收的是无用的类,如何判断:
需要满足以下三个条件才能算是”无用的类”:
Java堆中不存在该类的任何实例,该类的所有实例都已被回收。
加载该类的classLoader已被回收。
该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
而且并不是和对象一样不使用了就必然会回收。仅仅是虚拟机可以对满足以上三个条件的无用类进行回收。

垃圾收集有哪些算法,特点?
标记-清除算法:
首先标记出要回收的对象,在标记完成之后统一回收所有被标记的对象,是最基础的收集算法。
效率问题:效率不高
空间问题:标记清除后会产生大量的不连续的内存碎片。
复制算法:
解决了内存碎片的问题。将内存分为大小相同的两块,每次使用其中的一块,当这一块内存使用完后,就将还存活的对象复制到另一块上,然后再把使用的空间一次清理掉。
标记-整理算法:
将存活的对象整理到一端,然后清理掉端边界以外的内存。 JVM分代垃圾回收机制
双亲委派模型
Java虚拟机对class文件采用的是按需加载的方式,而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模型。
如果一个类加载器收到了类加载请求,它并不会自己去加载,而是交由父加载器去加载,
如果父加载器还存在其父加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器。
如果父加载器可以完成类加载任务,就成功返回,如果无法完成子加载器才会去自己加载,这就是双亲委派模型。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值