JVM内存回收问题处理方法

开发 后端
上节我们介绍了JVM体系结构,这里和大家学习一下JVM内存回收问题,Sun的JVMGenerationalCollecting(垃圾回收)原理是这样的:把对象分为年青代(Young)、年老代(Tenured)、持久代(Perm),对不同生命周期的对象使用不同的算法。

本文和大家重点讨论一下JVM内存回收问题的解决方法,通常我们说的JVM内存回收总是在指堆内存回收,确实只有堆中的内容是动态申请分配的,所以以上对象的年轻代和年老代都是指的JVM的Heap空间,而持久代则是之前提到的MethodArea,不属于Heap。

JVM内存回收

了解JVM的系统结构,再来看看JVM内存回收问题了——
Sun的JVMGenerationalCollecting(垃圾回收)原理是这样的:把对象分为年青代(Young)、年老代(Tenured)、持久代(Perm),对不同生命周期的对象使用不同的算法。(基于对对象生命周期分析)

Java堆中的各代分布

如上图所示,为Java堆中的各代分布。

1.Young(年轻代)

年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从***个Survivor区复制过来的并且此时还存活的对象,将被复制年老区(Tenured。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从***个Survivor去过来的对象。而且,Survivor区总有一个是空的。

2.Tenured(年老代)

年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。

3.Perm(持久代)

用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=进行设置。

举个例子:当在程序中生成对象时,正常对象会在年轻代中分配空间,如果是过大的对象也可能会直接在年老代生成(据观测在运行某程序时候每次会生成一个十兆的空间用收发消息,这部分内存就会直接在年老代分配)。年轻代在空间被分配完的时候就会发起内存回收,大部分内存会被回收,一部分幸存的内存会被拷贝至Survivor的from区,经过多次回收以后如果from区内存也分配完毕,就会也发生内存回收然后将剩余的对象拷贝至to区。等到to区也满的时候,就会再次发生内存回收然后把幸存的对象拷贝至年老区。

通常我们说的JVM内存回收总是在指堆内存回收,确实只有堆中的内容是动态申请分配的,所以以上对象的年轻代和年老代都是指的JVM的Heap空间,而持久代则是之前提到的MethodArea,不属于Heap。

关于JVM内存管理的一些建议

1、手动将生成的无用对象,中间对象置为null,加快内存回收。

2、对象池技术如果生成的对象是可重用的对象,只是其中的属性不同时,可以考虑采用对象池来较少对象的生成。如果有空闲的对象就从对象池中取出使用,没有再生成新的对象,大大提高了对象的复用率。

3、JVM调优通过配置JVM的参数来提高垃圾回收的速度,如果在没有出现内存泄露且上面两种办法都不能保证JVM内存回收时,可以考虑采用JVM调优的方式来解决,不过一定要经过实体机的长期测试,因为不同的参数可能引起不同的效果。如-Xnoclassgc参数等。

推荐的两款JVM内存检测工具

1、jconsoleJDK自带的内存监测工具,路径jdkbin目录下jconsole.exe,双击可运行。连接方式有两种,***种是本地方式如调试时运行的进程可以直接连,第二种是远程方式,可以连接以服务形式启动的进程。远程连接方式是:在目标进程的jvm启动参数中添加-Dcom.sun.management.jmxremote.port=1090-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=false1090是监听的端口号具体使用时要进行修改,然后使用IP加端口号连接即可。通过该工具可以监测到当时内存的大小,CPU的使用量以及类的加载,还提供了手动gc的功能。优点是效率高,速度快,在不影响进行运行的情况下监测产品的运行。缺点是无法看到类或者对象之类的具体信息。使用方式很简单点击几下就可以知道功能如何了,确实有不明白之处可以上网查询文档。

2、JProfiler收费的工具,但是到处都有破解办法。安装好以后按照配置调试的方式配置好一个本地的session即可运行。可以监测当时的内存、CPU、线程等,能具体的列出内存的占用情况,还可以就某个类进行分析。优点很多,缺点太影响速度,而且有的类可能无法被织入方法,例如我使用jprofiler时一直没有备份成功过,总会有一些类的错误。

【编辑推荐】

  1. 探索Java工作原理之JVM内存回收
  2. Tomcat配置JVM参数巧妙方法
  3. JVM基础:解析JVM分代垃圾回收策略
  4. JVM for Linux JIT诊断技术简介
  5. 巧解IBM JVM for Linux onPOWER性能调优

 

责任编辑:佚名 来源: tech.e800.com.cn
相关推荐

2010-09-26 16:42:04

JVM内存组成JVM垃圾回收

2017-04-25 14:39:55

JVM内存Java

2009-12-30 10:14:29

JVM垃圾回收

2010-09-25 15:19:01

2010-06-02 13:00:43

Linux 内存监控

2009-04-28 13:48:09

2012-01-09 17:06:16

JavaJVM

2013-10-11 17:32:18

Linux运维内存管理

2010-09-25 09:56:46

JVM最大内存

2023-08-08 10:29:55

JVM优化垃圾回收

2019-09-04 15:31:04

JVM内存String

2017-08-04 10:53:30

回收算法JVM垃圾回收器

2022-01-20 10:34:49

JVM垃圾回收算法

2010-09-26 15:38:33

JVM内存泄漏

2010-09-27 09:01:26

JVM分代垃圾回收

2022-03-21 11:33:11

JVM垃圾回收器垃圾回收算法

2010-09-25 15:33:19

JVM垃圾回收

2022-06-22 09:54:45

JVM垃圾回收Java

2010-06-11 17:07:14

Linux 内存监控

2019-12-18 15:13:33

JVM虚拟机内存
点赞
收藏

51CTO技术栈公众号