JVMGC相关总结

JVMGC过程

java虚拟机垃圾清理主要是针对堆内存进行回收。
之前:引用计数法 缺点:可能产生无效引用导致堆内无用对象无法回收
之后:可达性分析算法 大致原理:是否直接或者间接的与GCRoot(根节点)产生连接。 根节点:1.栈内存引用的变量2.方法区引用的变量或常量3.本地方法栈中引用的变量。
涉及到的算法:1.复制算法2.标记清除法3.标记整理法
java8JVMGC具体详解:
垃圾回收涉及的内存图
年轻代,老年代,永久代
年轻代:新生的对象分配到年轻代,细分成三个区域伊甸园,存活区0,存活区1,大小比例8:1:1。
特征:生成的对象多,经常产生无用的对象故会频繁回收垃圾内存。
采用算法:复制算法—jvm虚拟机刚开始时对象都生成到伊甸园区,满了之后采用复制算法具体是将伊甸园区可达对象(可达性分析算法判断)复制到存活区0。当往后第N次则是将伊甸园区和(N-1)%2存活区的存活对象复制到N%2存活区且删除自身区域的数据,每个对象存在一个计算器默认当迭代到15次是对象进入老年代。
老年代:年轻代中默认迭代存活15次的分配到老年代。
特征:对象可能大部分可达,故垃圾回收频率低。
采用算法:标记清除法/标记整理——挑选出不可达对象,进行垃圾清除/挑选出不可达对象,进行垃圾清除再压缩整理其中非连续的垃圾碎片。
两种算法对比:主要是对生成垃圾碎片处理上不同。不处理(效率快),处理(省空间)。
永久代:生成类,静态变量,常量的区域,通常不进行垃圾回收。

JVM参数

参考链接

JVM相关异常

第一类内存溢出,也是大家认为最多,第一反应认为是的内存溢出,就是堆栈溢出:

那什么样的情况就是堆栈溢出呢?当你看到下面的关键字的时候它就是堆栈溢出了:

Java.lang.OutOfMemoryError: …Java heap space…

也就是当你看到heap相关的时候就肯定是堆栈溢出了,此时如果代码没有问题的情况下,适当调整-Xmx和-Xms是可以避免的,不过一定是代码没有问题的前提,为什么会溢出呢,要么代码有问题,要么访问量太多并且每个访问的时间太长或者数据太多,导致数据释放不掉,因为垃圾回收器是要找到那些是垃圾才能回收,这里它不会认为这些东西是垃圾,自然不会去回收了;主意这个溢出之前,可能系统会提前先报错关键字为:

java.lang.OutOfMemoryError:GC over head limit exceeded

这种情况是当系统处于高频的GC状态,而且回收的效果依然不佳的情况,就会开始报这个错误,这种情况一般是产生了很多不可以被释放的对象,有可能是引用使用不当导致,或申请大对象导致,但是java heap space的内存溢出有可能提前不会报这个错误,也就是可能内存就直接不够导致,而不是高频GC.

第二类内存溢出,PermGen的溢出,或者PermGen 满了的提示,你会看到这样的关键字:

关键信息为:

java.lang.OutOfMemoryError: PermGen space

原因:系统的代码非常多或引用的第三方包非常多、或代码中使用了大量的常量、或通过intern注入常量、或者通过动态代码加载等方法,导致常量池的膨胀,虽然JDK 1.5以后可以通过设置对永久带进行回收,但是我们希望的是这个地方是不做GC的,它够用就行,所以一般情况下今年少做类似的操作,所以在面对这种情况常用的手段是:增加-XX:PermSize和-XX:MaxPermSize的大小。

第三类内存溢出:在使用ByteBuffer中的allocateDirect()的时候会用到,很多javaNIO的框架中被封装为其他的方法

溢出关键字:

java.lang.OutOfMemoryError: Direct buffer memory
如果你在直接或间接使用了ByteBuffer中的allocateDirect方法的时候,而不做clear的时候就会出现类似的问题,常规的引用程序IO输出存在一个内核态与用户态的转换过程,也就是对应直接内存与非直接内存,如果常规的应用程序你要将一个文件的内容输出到客户端需要通过OS的直接内存转换拷贝到程序的非直接内存(也就是heap中),然后再输出到直接内存由操作系统发送出去,而直接内存就是由OS和应用程序共同管理的,而非直接内存可以直接由应用程序自己控制的内存,jvm垃圾回收不会回收掉直接内存这部分的内存,所以要注意了哦。

如果经常有类似的操作,可以考虑设置参数:-XX:MaxDirectMemorySize

第四类内存溢出错误:

溢出关键字:

java.lang.StackOverflowError

这个参数直接说明一个内容,就是-Xss太小了,我们申请很多局部调用的栈针等内容是存放在用户当前所持有的线程中的,线程在jdk 1.4以前默认是256K,1.5以后是1M,如果报这个错,只能说明-Xss设置得太小,当然有些厂商的JVM不是这个参数,本文仅仅针对Hotspot VM而已;不过在有必要的情况下可以对系统做一些优化,使得-Xss的值是可用的。

第五类内存溢出错误:

溢出关键字:

java.lang.OutOfMemoryError: unable to create new native thread

上面第四种溢出错误,已经说明了线程的内存空间,其实线程基本只占用heap以外的内存区域,也就是这个错误说明除了heap以外的区域,无法为线程分配一块内存区域了,这个要么是内存本身就不够,要么heap的空间设置得太大了,导致了剩余的内存已经不多了,而由于线程本身要占用内存,所以就不够用了,说明了原因,如何去修改,不用我多说,你懂的。

第六类内存溢出:

溢出关键字

java.lang.OutOfMemoryError: request {} byte for {}out of swap

这类错误一般是由于地址空间不够而导致。

JVM垃圾处理器及应用

老一代垃圾处理器大致上从年轻代跟老年代中划分。新型垃圾处理器G1
年轻代:串行,并行( ParNew收集器/Parallel Scavenge 新生代收集器-尤其关注吞吐量)
老年代:串行,并行,并发CMS(Concurrent Mark & Sweep)
串行/并行/并发区别:串行只有一个垃圾处理器工作且进行JVMGC时其他线程被打断
并行多个垃圾处理器工作且进行JVMGC时其他线程被打断
并发个垃圾处理器工作且进行JVMGC时其他线程不被打断(GC工作时分四个步骤1.初始标记2.并发标记3.重新标记4. 并发清除 1.3独占 2.4并发)
具体搭配思路:1对1,1对N,N对N.
垃圾处理器G1:G1其实是Garbage First的意思,垃圾优先? 不是,是优先处理那些垃圾多的内存块的意思。它是将堆空间划分2的幂次方个小区域最大64G,每个内存块细分成年轻代或老年代但是空间并不连续。

优点:年轻代老年代都是并发回收垃圾,并且用户能够自行设置垃圾回收时间。
缺点:算法交复杂,吃内存,吃cpu

资料参考:

G1的并行收集做得特别好,我们第一次听到并行收集应该是CMS(Concurrent Mark & Sweep)垃圾回收算法, 但是CMS的并行收集也只是在收集老年代能够起效,而在回收年轻代的时候CMS是要暂停整个应用的(Stop-the-world)。而G1整个收集全程几乎都是并行的,它回收的大致过程是这样的:
在垃圾回收的最开始有一个短暂的时间段(Inital Mark)会停止应用(stop-the-world)
然后应用继续运行,同时G1开始Concurrent Mark
再次停止应用,来一个Final Mark (stop-the-world)
最后根据Garbage First的原则,选择一些内存块进行回收。(stop-the-world)
由于它高度的并行化,因此它在应用停止时间(Stop-the-world)这个指标上比其它的GC算法都要好。
G1的另一个显著特点他能够让用户设置应用的暂停时间,为什么G1能做到这一点呢?也许你已经注意到了,G1回收的第4步,它是“选择一些内存块”,而不是整代内存来回收,这是G1跟其它GC非常不同的一点,其它GC每次回收都会回收整个Generation的内存(Eden, Old), 而回收内存所需的时间就取决于内存的大小,以及实际垃圾的多少,所以垃圾回收时间是不可控的;而G1每次并不会回收整代内存,到底回收多少内存就看用户配置的暂停时间,配置的时间短就少回收点,配置的时间长就多回收点,伸缩自如。 (阿里面试)
由于内存被分成了很多小块,又带来了另外好处,由于内存块比较小,进行内存压缩整理的代价都比较小,相比其它GC算法,可以有效的规避内存碎片的问题。
说了G1的这么多好处,也该说说G1的坏处了,如果应用的内存非常吃紧,对内存进行部分回收根本不够,始终要进行整个Heap的回收,那么G1要做的工作量就一点也不会比其它垃圾回收器少,而且因为本身算法复杂了一点,可能比其它回收器还要差。因此G1比较适合内存稍大一点的应用(一般来说至少4G以上),小内存的应用还是用传统的垃圾回收器比如CMS比较合适。
总结
G1通过在垃圾回收领域应用并行化的策略,把几块大内存块的回收问题,变成了几百块小内存的回收问题,使得回收算法可以高度并行化,同时也因为分成很多小块,使得垃圾回收的单位变成了小块内存,而不是整代内存,使得用户可能对回收时间进行配置,垃圾回收变得可以预期了。
分而治之、化整为零这些朴素的架构思想往往是很多牛叉技术产品背后的思想根源啊。

问:如何在工作环境中使用特定的垃圾处理器
答:内部调优/外部调优
内部调优:在这里插入图片描述
外部调优:1.编译在这里插入图片描述
2.运行 在这里插入图片描述
3.结果
在这里插入图片描述

补充

强引用—CC cc = new CC();永不进行垃圾回收
软引用— SoftReference ccSoftReference = new SoftReference(cc);堆内存满的情况下进行回收。

Object obj = new Object();
SoftReference<Object> ccSoftReference = new SoftReference<>(obj);
System.out.println(ccSoftReference.get());
System.out.println("====================");
System.gc();
System.out.println(ccSoftReference.get());

弱引用—WeakReference ccWeakReference = new WeakReference<>(cc);进行JVMGC时回收垃圾。

 Object obj = new Object();
 WeakReference<Object> ccWeakReference = new WeakReference<>(obj);
 obj=null;
 System.out.println(ccWeakReference.get());
  System.out.println("====================");
        System.gc();
 System.out.println(ccWeakReference.get());

结果:java.lang.Object@4554617c
*====================*
null

虚引用—本身无用,标识作用,与引用队列搭配使用,清理垃圾后对象出现在队列中。

Object obj = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue();
PhantomReference<Object> phantomReference = new PhantomReference<>(obj, referenceQueue);
obj=null;
System.out.println(phantomReference.get());
System.out.println(referenceQueue.poll());
System.out.println("====================");
        System.gc();
System.out.println(phantomReference.get());
System.out.println(referenceQueue.poll());

结果:
null
null
*====================*
null
java.lang.ref.PhantomReference@4554617c
相关应用:WeakHashMap,做服务系统的图片缓存,当GC的时候map中的value进行清理。

	bject obj = new Object();
        WeakHashMap<Object,String> map = new WeakHashMap<>();    
        WeakReference<Object> ccWeakReference = new WeakReference<>(obj);
        map.put(obj,"10");
        obj=null;
      
        System.out.println(map);
        System.out.println("====================");

        System.gc();
        System.out.println(map);
     

运行结果:
{java.lang.Object@4554617c=10}
*====================*
{}
弱引用hashmap参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值