zoukankan      html  css  js  c++  java
  • JVM 内存分析(转)

    一、JVM简介

    JVM是Java Virtual Machine(Java虚拟机)的缩写,Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java 虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。JVM 也有自己的相关规范,使得第三方可以开发出自己的JVM,比如IBMJVM,MSJVM,HOTSPOT JVM(SUN)。本文是参考HOTSPOT JVM进行介绍。

    二、JVM内存结构

    JVM内存框架图

    注: 上图的序号是从左向右进行标记,序号顺序不代表逻辑关系

    下面我们将按逻辑关系进行介绍

    1 JVM Process Heap

    32位OS:最多约2GB

    64位OS:更多。

    2 Java Object Heap(JAVA Heap)

    通常被称为JVM  heap ,容易和JVM process Heap混淆,它是用来存储java OBject的如:

    Object的实例和Object的基本数据及引用。

    -XX:MinHeapFreeRatio=

    Default is 40 (40%)

    -XX:MaxHeapFreeRatio=

    Default 70%

    JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小 于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、 -Xmx相等以避免在每次GC后调整堆的大小。

    3、Young Generation

    所有新创建的Object 都将会存储在这里。

    配置方式 :

    -Xmn – not preferred (fixed value)

    -XX:NewRatio=<value> - preferred

    (dynamic)

    官方推荐的配置是新生代(Young Generation)占整个Java Object Heap内存的33%

    4、Eden Space

    新的Object总是创建在Eden Space。

    5、Old Generation

    如果Young Generation的数据在一次或多次GC后存活下来,那么将被转移到OldGeneration。

    6、Survivor Spaces

    GC时,Eden中活的对象复制到surivivor spaces ,当对象达到最打值(老化)时,被送到Old Generation

    10、Tenured Space

    5MB min 44MB max (default)

    这就是传说中的老年代,官方给的解释就是:

    pool containing objects that have existed for some time in the survivor space.

    11、Everything else

    这其实就是我们常常见到的no-heap

    12、Permanent Space

    4MB initial , 63MB max

    存储class的函数及其他的meta Data.

    配置方式:

    -XX:PermSize=<value> (initial)

    -XX:MaxPermSize=<value> (max)

    13、Code Generation

    转换byte code 为native code.

    基本不会导致内存异常。

    如果该操作没有足够的空间,JVM可能会导致崩溃。

    14、Socket Buffers

    包括两部分:1:Receive buffer ~37k   2:Send buffer ~25k

    需要在JAVA代码中来控制他,所以在外部无法配置。

    他可能导致的异常:IOException: Too many open files (for

    example)

    15、Threaded JVM Stacks

    jvm stacks:

    jvm stack: frame data 、operand stack ...

    Thread Stacks:

    表示各个Thread所分配的空间。

    默认至取决于OS/JVM

    线程数增加,Thread Stacks则增大。

    配置: –Xss

    异常:java.lang.OutOfMemoryError:

    unable to create new native thread

    如果-Xss配置的太小,会引起

    java.lang.StackOverflowError

    16、Direct Memory Space

    他可以让开发人员映射内存到java Object Heap外。

    配置: XX:MaxDirectMemorySize=<value>

    17、JNI Code 、

    JNI code本身使用的内存非常小。

    19、JNI allocate memory

    JNI 程序本身也需要分配内存。

    18、Garbage Collection

    其实GC也是需要内存的,gc线程的消耗以及存放GC所缓存的信息。

    这里简单介绍下GC的历史:

    GC始于1959 –LISP语言

    他的初衷:

    1、 自动内存清理

    2、 让开发变得简单

    3、 让debug更方便

    Gc的过程

    1、锁(Lock it down)

    所有对象在GC时会被锁定,以保证他们不会变化。

    2、标记(Mark)

    遍历所有对象,标记 不可到达阶段的对象(unreachable)为 垃圾(需要回收)

    3、清理(Sweep)

    删除所有被标记对象

    清理内存

    GC在早及的JAVA版本中的问题

    1、GC不能很好的协调。

    2、只有一个算法。

    3、标记(Mark)、清理(Sweep)需要扫描整个Heap,需要花费很久的时间。当然该时间取决与堆的大小。所以人们发明了永久性空间(Permanent Space)

    GC工作原理:

    Eden——所有新创建的对象都被放置在这里。

    Survivor——当Eden区空间不足时,会将其中依旧存活的对象拷贝到两块Survivor区域(FromSpace 和                     ToSpace)中的一个,如果此时这个Survivor区域也空间不足,则将该块区域中存活的对象拷贝到另一块区域中。           注意,总有一个Survivor区域是空的。

    对Young Generation的垃圾回收叫minor GC,通常很多的对象都活不过一次GC。

    Old Generation——但一个Survivor区域满了的时候,会将该区域中已经历一定次数GC而依旧存活的对象放到Old Generation中。如果Old Generation也满了,那就要Full GC了。Full GC很耗性能,当Full GC进行时,应用程序会暂停。由于大部分对象都活不过一次GC,所以如果服务器上频繁的发生Full GC,就要关注下是不是出问题了。

     三、引起的异常

    java.lang.OutOfMemoryError: Java heap space

    原因:Heap内存溢出,意味着Young和Old generation的内存不够。

    解决:调整java启动参数-Xms -Xmx 来增加Heap内存。

    java.lang.OutOfMemoryError: unable to create new native thread

    原因:Stack空间不足以创建额外的线程,要么是创建的线程过多,要么是Stack空间确实小了。

    解决:由于JVM没有提供参数设置总的stack空间大小,但可以设置单个线程栈的大小;而系统的用户空间一共是3G,除了Text/Data/BSS /MemoryMapping几个段之外,Heap和Stack空间的总量有限,是此消彼长的。因此遇到这个错误,可以通过两个途径解决:1.通过 -Xss启动参数减少单个线程栈大小,这样便能开更多线程(当然不能太小,太小会出现StackOverflowError);2.通过-Xms -Xmx 两参数减少Heap大小,将内存让给Stack(前提是保证Heap空间够用)。

    java.lang.OutOfMemoryError: PermGen space

    原因:Permanent Generation空间不足,不能加载额外的类。

    解决:调整-XX:PermSize= -XX:MaxPermSize= 两个参数来增大PermGen内存。一般情况下,这两个参数不要手动设置,只要设置-Xmx足够大即可,JVM会自行选择合适的PermGen大小。

    java.lang.OutOfMemoryError: Requested array size exceeds VM limit

    原因:这个错误比较少见(试着new一个长度1亿的数组看看),同样是由于Heap空间不足。如果需要new一个如此之大的数组,程序逻辑多半是不合理的。

    解决:修改程序逻辑吧。或者也可以通过-Xmx来增大堆内存。

    在GC花费了大量时间,却仅回收了少量内存时,也会报出OutOfMemoryError ,我只遇到过一两次。当使用-XX:+UseParallelGC或-XX:+UseConcMarkSweepGC收集器时,在上述情况下会报错,在 HotSpot GC Turning文档 上有说明:

    The parallel(concurrent) collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown.

    对这个问题,一是需要进行GC turning,二是需要优化程序逻辑。

    java.lang.StackOverflowError

    原因:这也内存溢出错误的一种,即线程栈的溢出,要么是方法调用层次过多(比如存在无限递归调用),要么是线程栈太小。

    解决:优化程序设计,减少方法调用层次;调整-Xss参数增加线程栈大小。

    IOException: Too many open files

    原因: 这个是由于TCP connections 的buffer 大小不够用了。

    java.lang.OutOfMemoryError:Direct buffer memory

    解决:调整-XX:MaxDirectMemorySize=<value>

    转自:http://www.2cto.com/kf/201108/99433.html

  • 相关阅读:
    Redis为什么使用单进程单线程方式也这么快
    高性能IO模型浅析
    计算机基础知识_硬件知识
    计算机基础知识_进制转化
    计算机基础知识
    C语言_第一讲_C语言入门
    C语言_第二讲_规范以及常用数据类型
    COM_第四讲_保存GUID_优化使用代码
    4.性能下降原因和常见的Join查询
    3.MySQL的架构介绍
  • 原文地址:https://www.cnblogs.com/zxyl/p/2371188.html
Copyright © 2011-2022 走看看