栈溢出:方法执行时创建的栈帧超过了栈的深度 ,最有可能就是方法递归调用。
堆溢出:heap space表示堆空间,堆中主要存储的是对象。不断的new对象会导致堆中的空间溢出
JVM区域总体分两类,heap区和非heap区。
heap区又分为:
非heap区又分:
1个Eden区和2个Survivor区(分别叫from和to)。默认比例为8:1
Eden和Survivor的比例是8:1.
首先说如果没有Survivor区会出现什么情况:此时每触发一次Minor GC,就会把Eden区的对象复制到老年代,这样当老年代满了之后会触发Major Gc(通常伴随着MinorGC,可以看做Full GC),比较耗时。
如果只有1个Survivor区,那当Eden区满了之后,就会复制对象到Survivor区,容易产生内存碎片化。严重影响性能。
所以使用2个Survivor区,始终保持有一个空的Survivor区,可以避免内存碎片化。
Survivor减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历多次Minor GC还能在新生代中存活的对象,才会被送到老年代。
对象诞生即新生代->eden,在进行minor gc过程中,如果依旧存活,移动到from,变成Survivor,进行标记代数,如此检查一定次数后,晋升为老年代。
https://wangkang007.gitbooks.io/jvm/content/jvmcan_shu_xiang_jie.html
引用计数,标记-清除,标记-整理,复制,分代收集
https://blog.csdn.net/zdp072/article/details/51116081
Serial、parNew、ParallelScavenge、SerialOld、ParallelOld、CMS、G1
CMS:
一、初始标记:此时标记需要用户线程停下来;
二、并发标记:此时标记可以和用户线程一起运行;
三、重新标记:此时标记需要用户线程停下来,主要母的是为了对并发标记的垃圾进行审核;
四、并发清除:与用户线程一起与运行进行垃圾清除;
缺点:
1、CMS收集器对cpu资源非常敏感;
2、CMS收集器无法清除浮动垃圾;
3、cms基于标记清除的算法实现的,所以内存碎片会产生过多。
G1收集器:
1、初始标记:标记GC Root能直接关联的对象,并且修改TAMS的值,让下一阶段的用户进行并发运行是,能够正确运用Region创建新对象,这阶段需要停顿,但停顿时间很短
2、并发标记:从GC Root开始对堆进行可达性分析,找出存活的对象,这段耗时较长,但可以与用户线程并发执行。
3、最终标记是为了修正在并发标记阶段因用户程序继续运作导致标记产生变动的那一部分的标记记录,虚拟机将这部分标记记录在线程Remembered Set中,这阶段需要停顿线程,但是可并行执行。
4、筛选回收:首先对各个Region的回收价值和成本进行排序,根据用户所期待的GC停顿时间来制定回收计划,这个阶段也可以与用户线程并行执行,但由于只回收一部分的Region,时间是用户可控制的,而且停顿用户线程将大幅度提高收集效率。
首先分析是什么类型的内存溢出,对应的调整参数或者优化代码。
https://wangkang007.gitbooks.io/jvm/content/4jvmdiao_you.html
类加载器 就是根据指定全限定名称将class文件加载到JVM内存,转为Class对象。
- 启动类加载器(Bootstrap ClassLoader):由C++语言实现(针对HotSpot),负责将存放在\lib目录或-Xbootclasspath参数指定的路径中的类库加载到内存中。
- 其他类加载器:由Java语言实现,继承自抽象类ClassLoader。如:
- 扩展类加载器(Extension ClassLoader):负责加载\lib\ext目录或java.ext.dirs系统变量指定的路径中的所有类库。
- 应用程序类加载器(Application ClassLoader)。负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。
打破: 线程上下文加载器(Thread Context ClassLoader) 打破双亲委派机制则不仅要继承ClassLoader类,还要重写loadClass和findClass方法。
1:自己写一个类加载器
2:重写loadclass方法
3:重写findclass方法
Java程序在运行状态可以动态的获取类的所有属性和方法,并实例化该类,调用方法的功能
-server (64位无需此参数)
Xms6000M
-Xmx6000M
-Xmn500M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-XX:SurvivorRatio=65536
-XX:MaxTenuringThreshold=0
-Xnoclassgc
-XX:+DisableExplicitGC
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled
-XX:-CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=90
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log
Cms是以获取最短回收停顿时间为目标的收集器。基于标记-清除算法实现。比较占用cpu资源,切易造成碎片。
G1是面向服务端的垃圾收集器,是jdk9默认的收集器,基于标记-整理算法实现。可利用多核、多cpu,保留分代,实现可预测停顿,可控。 、
https://blog.csdn.net/KilluaZoldyck/article/details/75081875
利用jps 、 top 、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程 查找:Found one Java-level deadlock 即可
https://my.oschina.net/liufukin/blog/2222495
-server -Xms512m -Xmx512m -Xss1024K
-XX:PermSize=256m -XX:MaxPermSize=512m -
XX:MaxTenuringThreshold=20 XX:CMSInitiatingOccupancyFraction=80 -
XX:+UseCMSInitiatingOccupancyOnly。
Server模式启动
最小堆内存512m
最大512m
每个线程栈空间1m
永久代256
最大永久代256
最大转为老年代检查次数20
Cms回收开启时机:内存占用80%
只以CMS的阈值来收集垃圾
注释:
-XX:+UseCMSInitiatingOccupancyOnly
-XX+UseCMSInitiatingOccupancyOnly标志来命令JVM不基于运行时收集的数据来启动CMS垃圾收集周期。而是当该标志被开启时,JVM通过CMSInitiatingOccupancyFraction的值进行每一次CMS收集,而不仅仅是第一次。大多数情况下,JVM比我们自己能作出更好的垃圾收集决策。只有当我们充足的理由(比如测试)并且对应用程序产生的对象的生命周期有深刻的认知时,才应使用该标志。