jvm

jvm内存结构

2018-08-10  本文已影响0人  John13

更多参考:
一篇简单易懂的原理文章,让你把JVM玩弄与手掌之中
关于JVM的类型和模式
jvm系列 (一) ---jvm内存区域与溢出
JVM常量池浅析 --- 很棒
JVM 的 工作原理,层次结构 以及 GC工作原理
JVM内存分配及GC
Java8内存模型—永久代(PermGen)和元空间(Metaspace)
JVM第一篇:一个Java内存泄漏的排查案例

一、JVM运行时数据区(注意jdk1.6/1.7/1.8的区别)

可见,垃圾回收主要针对于方法区和堆内存;不针对虚拟机栈、本地方法栈和程序计数器,因为它们的生命周期与栈相同,随生随灭。

二、java内存模型

JVM内存分布模型包括了堆和方法区,方法区称为永久代(permanent generation),堆空间分为新生代(young generation)和老年代(old generation)。新生代则又可以分为Eden和Survivor两个区域。如图:

三、jvm参数设置

堆空间内存分配(默认情况下)

  • 老年代 : 三分之二的堆空间
  • 年轻代 : 三分之一的堆空间
    eden区: 8/10 的年轻代空间
    survivor0 : 1/10 的年轻代空间
    survivor1 : 1/10 的年轻代空间
-server -Xms1800m -Xmx1800m -Xmn680m -Xss256k -XX:MetaspaceSize=340m -XX:MaxMetaspaceSize=340m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Dcom.sun.management.jmxremote.port=9981 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/logs

四、内存溢出、内存泄漏

内存溢出与内存泄漏

  • 内存溢出:
    简单地说内存溢出就是指程序运行过程中申请的内存大于系统能够提供的内存,没有足够的内存空间供其使用,导致无法申请到足够的内存,于是就发生了内存溢出,出现out of memory;
  • 内存泄漏:
    内存泄漏指程序运行过程中分配内存给临时变量,用完之后却没有被GC回收,始终占用着内存,既不能被使用也不能分配给其他程序,于是就发生了内存泄漏,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
  • memory leak会最终会导致out of memory!
  • 1、java.lang.OutOfMemoryError: PermGen space (持久带溢出)
    我们知道jvm通过持久带实现了java虚拟机规范中的方法区,而运行时常量池就是保存在方法区中的,因此发生这种溢出可能是运行时常量池溢出,或是由于程序中使用了大量的jar或class,使得方法区中保存的class对象没有被及时回收或者class信息占用的内存超过了配置的大小。
  • 2、java.lang.OutOfMemoryError: Java heap space (堆溢出)
    发生这种溢出的原因一般是创建的对象太多,在进行垃圾回收之前对象数量达到了最大堆的容量限制。
    解决这个区域异常的方法一般是通过内存映像分析工具对Dump出来的堆转储快照进行分析,看到底是内存溢出还是内存泄漏。如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链,定位出泄漏代码的位置,修改程序或算法;如果不存在泄漏,就是说内存中的对象确实都还必须存活,那就应该检查虚拟机的堆参数-Xmx(最大堆大小)和-Xms(初始堆大小),与机器物理内存对比看是否可以调大。
  • 3、虚拟机栈和本地方法栈溢出
    如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError。
    如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError。

1、常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
2、偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
3、一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
4、隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

上一篇下一篇

猜你喜欢

热点阅读