jvm堆内存分布及gc发生的条件

  jvm虚拟机对内存管理主要体现在堆内存的管理上,我们可以在启动jvm的时候设置jvm对内存大小及调整策略。

  1.jvm启动参数:

    -Xms:jvm启动时初始堆大小。

    -Xmx:jvm堆的最大值。

    -Xss:线程栈大小。

    -Dname=value:jvm全局属性设置。

  jvm启动参数设置有很多,以上只是列举本人接触过的几个参数。

  1)首先,-Xms是jvm启动时堆内存的初始大小,当堆内存不够用时,jvm调整堆大小到-Xmx设置的大小。一般resin这些服务器会把-Xms和-Xmx大小设置一样以避免不必要的内存调整。第一次对这个参数有印象是在刚到公司实习的第二天,公司使用的项目是用maven编译的,在maven配置文件settings.xml中有maven的资源库位置以及编译的各项配置。看完各种新手入门教程之后开始下载部门主工程代码,用maven编译一直通过不了,原因就在于jvm内存不够,当时maven中设置-Xms:256m,-Xmx:256m,显然256m是不够的,-Xmx设置为512m之后就可以编译过了。还有一个问题就是,这里把-Xms和-Xmx设置一样大是不合理的,虽然两个大小设置一样会避免编译主工程的时候jvm调整堆内存大小,但是maven编译其他比较小的项目的时候也要分配512m有些过于浪费,jvm占用过多的内存会让机器很卡的。

  2)-Dname=value这个参数使用的更频繁,在resin的httpd.sh文件中配置这个参数可以在项目启动的时候将指定的域名映射到想要的ip上去,使得调试更为方便。其他作用的设置暂时还不了解。

  

  2.jvm堆内存分布

  刚刚毕业的时候,面试官问jvm内存知道么,我会脱口而出jvm内存分为堆和栈。直到第一次代码不小心造成了内存泄露,当时tail了一下resin的jvm.log发现gc和full gc的频率很高,正常情况下tail这个日志很少会有gc或者full gc。看着一条一条jvm日志,完全像是在看另外一个世界的东西,这时我才意识到jvm管理的内存只知道这些是不够的。

    

  事实上jvm虚拟机管理的内存主要有:程序计数器,堆,方法区(永久代),虚拟机栈,本地方法栈。堆是jvm管理的最大的一块内存,主要的作用:存放几乎所有的类的实例对象。

  首先,jvm对内存分为新生代(Young)和老年代(Old).新生代又可以划分为三块,这样jvm中就有新生代,老年大,永久代几片内存,这样分区的目的就是垃圾回收时使用分代算法。

   新生代被划分为三个区域:

      Eden:几乎所有新诞生的java对象存在这个区域。

      From Survivor/To Survivor:经历过gc之后仍然存活且未进入到老年代区域的对象。

  Young和Old大小比例是1:2,Young中Eden:From:To是8:1:1。这个比例由参数 -XX:SurvivorRatio=8 来决定的。

3.gc发生条件

  首先,一般的对象产生都会在Eden中,较大的对象会直接进入老年代这个由参数 -XX:PretenureSizeThreshold 设置。在新生代中三个区域eden,from,to,一个时刻只会有两片内存被使用,首先eden肯定会被使用,from和to只有一片会被使用,主要是由于虚拟机采用的复制算法。

  minor gc:为了避免在gc的时候产生内存碎片,jvm以牺牲空间的方式来做的,首先eden空间不足时会产生一次minor gc,垃圾回收器会在eden和一片使用的Survivor(假设是from)中进行清理,存活下来的对象会被复制到to中(假设to的大小足够装满),然后清空eden和from,保留下来的对象年龄加一。当年龄到达某一个设定值时会进入老年代,默认是15岁,由参数 -XX:MaxTenuringThreshold设置。还有一种情况是在Survivor区域相同年龄多有对象大于Survivor区域一半是所有该年龄及以上的都会被移动到老年代。

  full gc:minor gc时Survivor区域不足以容纳年轻代中存活下来的对象时,且老年代中剩余空间容纳不了新生代中存活下来的对象时会进行full gc。老年代中因为没有进行分区,所以回收算法使用的是标记-清理算法或者标记整理算法。

4.gc日志解读

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以通过以下命令查看JVM堆内存大小: 1. 使用jstat命令查看JVM堆内存使用情况: jstat -gc <pid> 其中,<pid>为Java进程的进程ID。 该命令会输出JVM堆内存的使用情况,包括堆内存的容量、已使用的空间、已提交的空间等信息。 2. 使用jmap命令查看JVM堆内存使用情况: jmap -heap <pid> 该命令会输出JVM堆内存的详细信息,包括堆内存的容量、已使用的空间、已提交的空间、垃圾回收器的信息等。 需要注意的是,使用jmap命令会暂停Java进程的运行,可能会影响应用程序的性能。因此,在生产环境中,建议使用jstat命令查看JVM堆内存使用情况。 ### 回答2: 在Linux系统中,要查看JVM堆内存大小,可以采用以下方法: 1.使用jps命令查看Java进程编号 jps命令可以列出当前在运行的Java进程编号,输入如下命令: jps 会输出所有正在运行的Java进程编号,找到需要查看的Java进程编号。 2.使用jmap命令查看堆内存使用情况 jmap命令可以生成当前Java进程的堆内存转储快照,输入如下命令: jmap -heap <Java进程编号> 例如,如果Java进程编号为12345,则输入如下命令: jmap -heap 12345 会输出该Java进程的堆内存使用情况,其中包括堆内存的大小、使用情况、垃圾回收情况等信息。 3.使用jstat命令实时查看堆内存使用情况 jstat命令可以实时查看Java进程的堆内存使用情况,输入如下命令: jstat -gc <Java进程编号> <时间间隔> <次数> 例如,如果Java进程编号为12345,时间间隔为1秒,次数为10次,则输入如下命令: jstat -gc 12345 1 10 会输出该Java进程的堆内存使用情况,其中包括堆内存的大小、使用情况、垃圾回收情况等信息,并每秒钟更新一次。 总之,Linux系统中可以通过jps、jmap、jstat等命令来查看Java进程的堆内存大小和使用情况,帮助用户优化Java程序的性能。 ### 回答3: 在Linux系统上,我们可以通过命令行来查看JVM堆内存大小。具体步骤如下: 1. 打开命令行终端,输入以下命令来检查是否已经安装了Java环境: ```shell java -version ``` 如果已经安装了Java环境,会显示出Java版本号等信息;否则需要先安装Java环境。 2. 运行JVM应用程序,使用jstat命令来查看堆内存使用情况: ```shell jstat -gc <pid> ``` 其中,<pid>是JVM的进程号,可以使用命令ps -ef | grep java来查找。在jstat命令输出中,我们可以看到类似下面的信息: ```shell S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 1024.0 1024.0 0.0 701.0 8192.0 3331.8 26624.0 13705.5 20480.0 12483.9 24 1.809 2 0.562 2.371 ``` 在这里,我们关注OC列和OU列,它们分别表示老年代堆的容量和使用量。可以根据这两列的数据来计算老年代堆的使用率和空余内存大小,以及整个堆内存的使用率。 另外,我们还可以使用jmap命令来获取JVM内存信息,并导出堆内存的详细信息到文件中: ```shell jmap -heap <pid> jmap -dump:format=b,file=<path-to-dumpfile> <pid> ``` 同样,<pid>是JVM的进程号,<path-to-dumpfile>是导出文件的路径。使用jmap命令可以获取JVM中各个内存区域的使用情况、GC算法、线程堆栈等信息;使用jmap -dump命令可以导出当前JVM堆内存状态到文件中,以便于后续分析和调试。 通过以上方法,我们可以非常方便地查看Linux系统上JVM堆内存大小和使用情况,从而及时定位和解决JVM性能问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值