jvm基础
虚拟机栈:
是Java 方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧用于存储 局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
存放:基本数据类型,对象引用
堆(Java Heap)是Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的
唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC 堆”
如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java 堆中还可以细分为:新生代和老年代;
再细致一点的有Eden 空间、From Survivor(幸存) 空间、To Survivor 空间等。
GC:
新生代:
Eden区,最开new的对象保存在伊甸园区,如果伊甸园区内存满了,会触发一次轻GC,存活的就会进入from(大部分GC回收在伊甸园区)
幸存from区:
幸存to区:
老年代: 新生代满了会触发一次重GC,存活的会进入老年代,老年代满了就会oom。
jdk1.6之前:永久代,常量池在方法区
jdk1.7:去永久代,常量池在堆中
jdk1.8之后:元空间,常量池在元空间
产生oom:1.加载大量的jar包2.tomcat部署太多应用3.动态生成大量的反射类
默认情况下jvm分配的总内存 是电脑内存的4分之一,初始化内存是64分之一
在实际工作中,我们可以直接将初始的堆大小与最大堆大小相等,
这样的好处是可以减少程序运行时垃圾回收次数,从而提高效率。
oom的处理方式:
1.调到最大化内存看结果
2.使用内存快照分析工具,分析内存,看那个地方出问题(会生成一个dump文件,使用工具打开)
a.分析dump文件,快速定位内存泄漏问题
b.获取堆中的数据
c.获取最大对象
GC算法:
标记清楚法:1.扫描对象,对对象进行标记,2.扫描对象,对没有标记的对象进行清除(清楚的内存会产生内存碎片)
好处:不需要额外的空间 坏处:两次扫描,浪费时间,产生内存碎片
标记压缩法:清除内存碎片,向前压缩空间,移动对象位置,是对象排列紧凑
复制算法:gc回收后存活的对象会转移到from区和to区(谁空谁是to),(每次gc后伊甸园区和to区都是空的,经历15次没死就会放到老年代),复制算法用在新生区,适用于对象存活率低的场景
好处:没有内存碎片 坏处:浪费空间,多了一半空间永远是空的
引用计数法:给对象分配一个计数器,计数对象的使用情况,没有使用的就回收
Minor GC触发条件:
当Eden区满时,触发Minor GC。
Full GC触发条件:
System.gc()方法的调用
老年代空间不足
方法区空间不足
由Eden区、From Space区向To Space区复制时
方法区(Method Area)与Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
然Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java 堆区分开来。
运行时常量池(Runtime Constant Pool)是方法区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池(Constant PoolTable),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
什么情况下会发生 栈 内存溢出?
栈是线程私有的,他的生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。局部变量表又包含基本数据类型,对象引用类型;
1.如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常,方法递归调用产生这种结果
2.在新建立线程的时候没有足够的内存去创建对应的虚拟机栈,那么Java虚拟机将抛出一个OutOfMemory异常
3.参数-Xss ,去调整JVM栈的大小。
JVM内存新生代中为什么要分为Eden和Survivor?
如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,进行一次Full GC消耗的时间比Minor GC长得多,所以需要分为Eden和Survivor
JVM的永久代中会发生垃圾回收吗?
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。
简述java类加载机制?
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的java类型。
类加载器双亲委派模型机制?
当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类去加载,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。
对象分配的规则?
(1)对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC;
(2)大对象直接进入老年代。
(3)长期存活的对象进入老年代。
Java对象创建过程?
new 类名-->去常量池中定位一个符号引用-->没有找到说明类没有被加载,则进行类的解析,加载,初始化。-->jvm为对象在堆中分配内存-->设置内存的初始值为0调用init方法。

浙公网安备 33010602011771号