JVM介绍、运行流程
什么是程序计数器
详细介绍一下堆
方法区/永久代 存储的是类信息、静态常量等,1.7以前放在堆中,那么在项目运行过程中,随着类加载越来越多,最终可能导致堆内存溢出,所以放在本地内存中,从而节省堆内存空间,防止内存溢出
什么是虚拟机栈
一个线程对应一个栈,一个栈对应多个栈帧,其中只有一个是活动栈帧,对应正在执行的方法
m2的形参、m3的返回值都导致局部变量逃离方法的作用范围,需要考虑线程安全
一般是递归调用导致的,第二种情况一般栈帧大小是1M,正常大部分栈帧都不会超过这个大小,所以不是导致栈内存溢出的主要原因
解释一下方法区
如果设置的最大元空间大小太小,则会报错
符号地址会变为真正的内存地址
介绍一下直接内存
直接内存不属于JVM运行时内存,而是操作系统内存
常规的IO首先由用户态转变为内核态,然后调用操作系统提供的native方法从磁盘读取文件数据到系统内存的系统缓存区,在系统内存时java代码是无法运行的,所以需要进一步读到java堆内存,并且通过new一个java缓冲区,来进行分批次的转移,转移成功后,由内核态转变为用户态,再调用输出流的写入操作,这样反复读写,从而把一个文件复制到另外一个位置
直接内存,java可以访问,因此减少了一次转移的操作,从而读写性能更高
JVM的内存模型介绍一下
运行时内存 = 两个栈、一个堆、一个空间、一个计数器
直接内存
栈:私有、栈帧、局部变量表(只是引用)、操作数栈、方法出口、固定或动态扩展
堆:共享、对象实例、数组、可回收、内存占用最大、管理最复杂
JVM内存模型里的堆和栈有什么区别
栈中存的到底是指针还是对象
堆分为哪几部分呢
元空间(永久代容易内存溢出):类的结构信息(字段、方法信息等),不在虚拟机中,而是使用本地内存
大对象区:堆中存储对象实例和数组,假设有一个大数组,且这个大数组存活时间很长,因此迟早会转移到老年代里,由于数组很大,转移到老年代时可能会导致内存碎片化,所以最好将那些很大的对象单独放在一个区域里(也可以直接放到老年代里?)
程序计数器的作用,为什么是私有的
方法区中的方法的执行过程
解析(找到方法的地址)----栈帧-----执行(字节码指令)-----返回结果、清除栈帧
方法区中还有哪些东西
元空间----方法区-----类信息、常量、静态变量、JIT编译后的代码缓存
注意存储的是谁的东西
String保存在哪里呢?String s = new String(“abc”)执行过程中分别对应哪些内存区域
引用类型有哪些?有什么区别
弱引用了解吗?举例说明在哪里可以用
内存泄漏和内存溢出的理解
jvm 内存结构有哪几种内存溢出的情况
有具体的内存泄漏和内存溢出的例子么请举例及解决方案
创建对象的过程
对象的生命周期
什么是类加载器,类加载器有哪些
类加载用于装载字节码文件到运行时数据区,然后分配内存、执行
具体而言,如下
双亲委派模型的作用
这就是为什么自定义类的时候不能用已有的关键字
讲一下类加载过程
加载阶段首先通过类的全名获取类的二进制数据流,然后解析成数据结构到元空间,元空间存储的是类的信息,包括方法、构造函数、字段等,然后会在堆中先创建一个该类的实例,当每次要创建该类的对象时,会将对象头指向这个实例,通过这个实例去元空间获取到相应的方法、构造函数、字段,从而完成对象的创建
验证其实就是进行安全性检查,其中符号引用验证是检查常量池中会使用到的类或方法是否存在
准备阶段主要看赋值的完成时机
解析阶段就是将符号引用转换为直接引用,常量池中的#号就是符号引用,通过一直查询#最终查到对应的方法,这就是直接引用
初始化阶段主要是对静态变量、静态代码块执行的初始化操作
使用阶段就是真正地进行使用
讲一下类的加载和双亲委派原则
什么是Java里的垃圾回收?如何触发垃圾回收
垃圾回收回收的是堆中的垃圾
判断垃圾的方法有哪些
变量存储在栈中,对象存储在堆中
当变量指向null,则形成环状(循环引用),从而引用计数法失效,导致内存泄漏
垃圾回收算法是什么,是为了解决了什么问题
垃圾回收算法有哪些
首先通过GCRoot标记还存活的对象,然后清除垃圾对象,但这样碎片化严重,内存不连贯,如果有一个比较大的数组要存储到堆中,由于没有足够的连续空间,所以无法存储
标记、清除之后,会整理一下内存空间,适用于老年代的垃圾回收器
复制算法适用于年轻代的垃圾回收器
说一下JVM的分代回收
垃圾回收器有哪些
对于CMS,初始标记是指与GCRoots关联的最近的对象,比如A,并发标记则是顺着A继续往后的对象,如B、C、D,而由于CMS在垃圾回收时应用仍然可以正常运行,所以代码运行过程中有可能突然A指向X,从而使X成为存活对象,也有可能B突然不指向D了,从而使D成为垃圾对象,因此还会做一个重新标记的操作,最后并发清理。由于CMS只在初始标记阶段标记最近的对象,所以标记时间很短,从而阻塞时间也很短,因此CMS具有停顿时间短的特点
G1垃圾回收器分为三个阶段:YC、YC+CM、MC
YC阶段:使用的是复制算法,首先会从堆内存中选出几个区域作为存储对象的区域,当堆内存到底阈值时触发垃圾回收,会在堆内存中选出一块区域,将Eden区的对象复制到Survivor区,然后释放掉Eden区,在YC阶段,其他应用需要停止(STW)。随后,当再次创建对象并且堆内存达到阈值时再次触发垃圾回收,会将Eden区和上一次的Survivor区中的年轻对象复制到新的Suvivor区中,而晋升的老对象放在Old区中,最后释放掉Eden区和之前的Survivor区即可。以上就是第一次年轻代垃圾回收
当老年代占用内存过多时会触发垃圾回收,需要进行并发标记,也就找出老年代中的存活对象进行标记,在此期间是不会阻塞用户程序(STW),同时并发标记之后还会重新标记,对一些漏标的对象进行标记,这个部分就需要STW。
混合垃圾回收就是 年轻代和老年代同时回收,混合垃圾回收可能重复多次,因为老年代是一点点回收的(每次找出一部分价值高的进行回收)
如果创建的对象是大对象,则会使用连续的内存进行分配
标记清除算法的缺点是什么
垃圾回收算法哪些阶段会stop the world
minorGC、majorGC、fullGC的区别,什么场景触发full GC
垃圾回收器 CMS 和 G1的区别
什么情况下使用CMS,什么情况使用G1
G1回收器的特色是什么
GC只会对堆进行GC吗
JVM调优参数有哪些
JVM调优工具
java内存泄露的排查思路
虽然内存泄漏包括元空间内存泄露、堆内存泄漏、虚拟机栈内存泄漏,但一般指的是堆内存泄漏