一、jvm内存结构、垃圾回收
方法区:存放对象的字节码对象,类的信息。
堆:存放实例
栈:存放变量和方法。
程序计数器:每个线程都会去抢CPU的运行时间,当CPU执行权,被抢走之后,程序计数器就会记录代码执行到哪一行。
1-1 哪些区域可能会产生内存溢出
除了计数器,其他都会。
出现OutOfMemoryError的情况
1 堆内存耗尽 - 对象越来越多,又一直在用,不能让GC回收
2 方法区内存耗尽 -- 加载的类越来越多,很多框架在运行期期间动态产生新的类。(比较少见)
3 虚拟机栈累积 -- 每个栈内存最多会占用1M内存,线程 个数越来越多,而长时间运行不能销毁时。
出现StatckOverFlowError的区域
1 虚拟机内存 -- 方法调用次数过多 (递归没写好)
1-2 方法区、元空间、永久区
元空间是虚拟机堆方法区的实现。
元空间中的字节码对象,只有当加载这些字节码的类加载器,不在使用,这些字节码对象才会被回收。
1-3 JVM内存参数
-Xmx :java虚拟机最大内存是多少
-Xms :java虚拟机最小内存是多少
-Xmn :java中新生代的内存占用多少
按比例设置:
-XX:SurvivorRatio :
from跟to一样的大小
eden跟from的比例(默认值 8 : 1)
-XX:NewRatio:
老生代:新生代
1-4 垃圾回收算法
标记清除(已经淘汰)
使用不可回收引用当根节点,标记正在引用的内存。
然后将无引用的部分清楚掉。
这种方式会导致内存碎片化
标记整理(用于老生代)
将所有不可回收的引用向一段靠拢
标记复制(用于新生代)
将不可回收的引用复制到内存的另一个区域。
需要更大的内存。
1-5 GC、分代回收算法
GC要点
GC的目的在于实现将无用的对象内存自动释放,减少内存碎片,加快内存的分配速度。
要点:
1 回收的区域是堆内存,不包括栈,方法执行完之后会自动出栈。
2 如何判断无用对象,使用可达性分析算法,三色标记法标记存活对象,回收未标记对象。
3 GC具体的实现称为垃圾回收器。
4 GC大部分采用了分代回收思想,理论依据是大部分对象用完可以马上回收,另外有一部分的对象会长时间存活,很难回收。根据这俩种区分将回收区域分为新生代和老生代,不同区域应用不同的回收策略。
5 根据GC的规模可以划分成MinoGC,MixedGC,FullGC.
1-6 三色标记于并发漏标
1-7 垃圾回收器
二、内存溢出、类加载
2-1 内存溢出的四种情况
使用线程池工具创建线程,导致没限制队列个数,最后导致内存溢出。
使用缓存线程池,对线程的个数没有限制,最后出现内存溢出。
查询数据量太大导致内存溢出(没有分页查询数据)。(堆内存)
动态产生的类太多也会出现内存溢出。(元空间)