JVM堆内存即GC介绍联合Hadoop

JVM


提示:后续会更新JVM内存优化,api接口优化,监测内存使用


一、JVM模型

在这里插入图片描述

JVM GC(垃圾回收机制)

在学习Java GC 之前,我们需要记住一个单词:stop-the-world 。它会在任何一种GC算法中发生。stop-the-world 意味着JVM因为需要执行GC而停止了应用程序的执行。当stop-the-world 发生时,除GC所需的线程外,所有的线程都进入等待状态,直到GC任务完成。GC优化很多时候就是减少stop-the-world 的发生。

1、JVM GC回收哪个区域内的垃圾?

JVM GC只回收堆区和方法区内的对象。而栈区的数据,在超出作用域后会被JVM自动释放掉,所以其不在JVM GC的管理范围内。


2、与Hadoop作业有什么关系?

我们在执行Mapreduce作业时,经常会碰到map任务不进行,或者reduce任务不进行了,卡在一个进度中。
因为每一次的map的输出都是一个新的对象,在内存分配少时(默认是1GB)且数据量为GB级别时会频繁发生GC,而且进程间(mapreduce是多进程,spark是多线程)会发生资源抢占,当高并发的job并发执行时即使开启FullGC(也无法清除掉堆对象因为单个进程还没有结束)且堆内存的不断增大,就会发生jvmpause异常(FULLGC执行的太过频繁这时程序会暂停,且CPU负担加重,若此时宕机或者程序卡住就会抛出sockettimeout异常或者60000ms内没有接收到新的数据),如果需要解决掉这个问题只能 提升单个节点的内存或者增加单个job任务的内存或者增加节点数。

3、JVM GC怎么判断对象可以被回收了?

· 对象没有引用

· 作用域发生未捕获异常

· 程序在作用域正常执行完毕

· 程序执行了System.exit()

· 程序发生意外终止(被杀线程等)

在Java程序中不能显式的分配和注销缓存,因为这些事情JVM都帮我们做了,那就是GC。

二、堆区内存的介绍

1.模型图

在这里插入图片描述
堆区分为新生代区和老年代区
新生代区又分为Eden(伊甸园区),S0和S1(幸存者区)
老年代区则独自为一区
比例为1:2 老年代区的空间比新生代大一倍

2.YGC

YGC(又名为小GC)
当新的对象来到堆区时,会首先进入到伊甸园区,如果伊甸园区的内存不够存放就会发生依次YGC,伊甸园内不需要的对象会被清理,若还有一些对象需要继续使用则会进入幸存者区。
若幸存者区已满或者放不下时,会直接进入老年代区,而幸存者区内的对象若存在时间过长且未被清理时,仍然会进入老年代区。
在这里插入图片描述


3.FULLGC

当老年代区已满或者存放不下内存时,会发生依次FULLGC,对所有的区都进行依次垃圾清除。FULLGC是最花销时间最大的GC,如果想要保证程序运行流程请务必减少FULLGC的次数,最好的方式就是加大内存的空间。

三. 总流程

1、绝大多数刚刚被创建的对象会存放在伊甸园空间(Eden)。

2、在伊甸园空间执行第一次GC(YGC)之后,存活的对象被移动到其中一个幸存者空间(Survivor)。

3、此后,每次伊甸园空间执行GC后,存活的对象会被堆积在同一个幸存者空间。

4、当一个幸存者空间饱和,还在存活的对象会被移动到另一个幸存者空间。然后会清空已经饱和的哪个幸存者空间。

5、在以上步骤中重复N次(N = MaxTenuringThreshold(年龄阀值设定,默认15))依然存活的对象,就会被移动到老年代。

从上面的步骤可以发现,两个幸存者空间,必须有一个是保持空的。如果两个两个幸存者空间都有数据,或两个空间都是空的,那一定是你的系统出现了某种错误。

我们需要重点记住的是,对象在刚刚被创建之后,是保存在伊甸园空间的(Eden)。那些长期存活的对象会经由幸存者空间(Survivor)转存到老年代空间(Old generation)。

也有例外出现,对于一些比较大的对象(需要分配一块比较大的连续内存空间)则直接进入到老年代。一般在Survivor 空间不足的情况下发生。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值