妙博客

主机评测 香港服务器 洛杉矶VPS测评

谈谈java中对JVM的理解

JVM也叫java虚拟机,特点是它的跨平台性,Java语言使用Java虚拟机屏蔽了与具体平台相关的信息。


Java虚拟机在运行Java程序时,会管理着一块内存区域,JVM内存模型可分为五个部分:堆、方法区、虚拟机栈、本地方法栈、程序计数器

1.堆:该内存区域是jvm虚拟机管理的内存中最大的一块内存,它存放了对象实例及数组

2.方法区:是各个线程共享的内存区域,用于已被虚拟机加载的类型信息、常量、静态变量、编译器代码缓存等

3.虚拟机栈:它保存方法的局部变量、方法返回地址和一些额外的附加信息

4.本地方法栈:它保存的是Native方法中的局部变量、方法返回地址和一些额外的附加信息

5.程序计数器:程序中分支、循环、跳转、异常处理、线程恢复等基础功能要用到计数器支持


jvm一大特色就是自动内存管理,它负责对堆内存中对象的分配与回收。一个对象从加载到jvm,再到被垃圾回收器GC清除,经过如下步骤:

1.用户创建一个对象,jvm首先需要到方法区去找对象的类信息。

2.jvm实例化对象,首先在堆中先创建一个对象,然后分配在堆内存中新生代的Eden区,然后经过依次新生代的的垃圾收集动作(Minor GC),

  对象如果存活,就会被移动到From survivor空间,再次执行Minor GC,如果对象还存活,此时会将对象移动到To Survivor区,同时把该对象的年龄+1,此时再把From Survivor 和 To Survivor指针交换,用来保证下一次MinorGC时,to survivor区还是空的。

  如果对象被复制的次数达到15(-XX:+MaxTenuringThreshold),那么该对象会被移动到老年代。另外如果单个Survivor区已经被占用了 50%( -XX:TargetSurvivorRatio),那么大年龄对象也会被移动老年代。老年代对象存活一段时间后,如果发现对象不可达GcRoot,而且此时老年代空间比率已经超过了阈值将触发FullGC,随后将被垃圾收集器回收。


JVM内存异常一般是程序bug导致的,典型的有:死循环、使用无界队列等,也可以通过定制JVM运行参数来提高Java应用程序的运行性能

1.一般情况下如果发现java进程负载过高,我们这个时候就会进行相关的排查。

2.第一步我们会通过top命令查看java进程所占用的CPU和内存,如果长期处于高负载状态,我们先查看GC日志(-verbose:gc 可以输出GC情况)。

3.gc日志中我们定时查看触发GC前后的内存空间是否一直处于居高不下缓慢上升的状态,说明可能出现了无法被回收的内存空间。

5.这个时候,我们可以通过top -Hp命令列出该java进程占用cpu和内存最高的线程(记下线程ID)。然后通过jstack命令打印当前java进程的线程堆栈信息

6.根据线程堆栈信息的调用找到出问题的代码,然后分析出现异常的原因。



JVM 内存指标有如下:

1.查看堆存储快照,分析内存的占用情况

2.查看堆各区域的内存增长是否正常

3.查看是哪个区域导致的GC

4.查看GC后能否正常回收到内存

JVM GC指标有:

1.查看每分钟GC时间是否正常

2.查看每分钟YGC次数是否正常

3.查看FGC次数是否正常

4.查看单次FGC时间是否正常

5.查看单次GC各阶段详细耗时,找到耗时严重的阶段

6.查看对象的动态晋升年龄是否正常


针对上述指标查找问题,一般有:

1.代码bug:升级修复bug。典型的有:死循环、使用无界队列。

2.不合理的JVM参数配置,优化 JVM 参数配置,典型的有:年轻代内存配置过小、堆内存配置过小、元空间(方法区)配置过小。



Copyright Your 142132.com Rights Reserved. 赣ICP备17010829号-2