登录 |  注册 |  繁體中文


Jvm内存管理

分类: 其它 颜色:橙色 默认  字号: 阅读(1259) | 评论(0)

一、Jvm内存描述

Jvm管理的内存大致包括三种不同类型的内存区域:Permanent Generation space(永久保存区域)、Heap space(堆区域)、Java Stacks(Java栈)。
1, Permanent Generation space(永久保存区域)主要存放Class(类),Meta的信息,Class第一次被Load的时候,Class需要存储的内容主要包括方法和静态属性。
2, Heap space(堆区域)用来存放Class的实例(即对象),对象需要存储的内容主要是非静态属性。每次用new创建一个对象实例后,对象实例存储在堆区域中,这部分空间也被jvm的垃圾回收机制管理。
3,Java Stacks(Java栈),跟大多数编程语言包括汇编语言的栈功能相似,主要基本类型变量以及方法的输入输出参数。Java程序的每个线程中都有一个独立的堆栈。

二、常见错误

容易发生内存溢出问题的包括:Permanent Generation space和Heap space。

第一种OutOfMemoryError: PermGen space
发生这种问题的原意是程序中使用了大量的jar或class,使java虚拟机装载类的空间不够。解决办法:
1. 增加java虚拟机中的XX:PermSize和XX:MaxPermSize参数的大小,其中XX:PermSize是初始永久保存区域大小,默认是物理内存的1/64,XX:MaxPermSize是最大永久保存区域大小,默认是物理内存的1/4。
2 .减少引用的jar或class

第二种OutOfMemoryError:  Java heap space
发生这种问题的原因是java虚拟机创建的对象太多,在进行垃圾回收之间,虚拟机分配的到堆内存空间已经用满了,解决思路:
1. 检查程序,看是否有死循环或不必要地重复创建大量对象。
2. 增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。如:set JAVA_OPTS= -Xms256m -Xmx1024m

第三种 线程栈OutOfMemoryError:unable to create new native thread
栈(JVM Stack)存放主要是栈帧( 局部变量表, 操作数栈 , 动态链接 , 方法出口信息 )的地方。注意区分栈和栈帧:栈里包含栈帧。
与线程栈相关的内存异常有两个:

  • StackOverflowError(方法调用层次太深,内存不够新建栈帧)

  • OutOfMemoryError(线程太多,内存不够新建线程)

不合理的JVM参数导致程序无法启动主要有以下几种原因:
1) 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize。
2) -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制。

三、JVM内存模型

JVM运行时内存=共享内存区+线程内存区

1).共享内存区

共享内存区=持久带+堆

持久带=方法区+其他

堆=Old Space+Young Space

Young Space=Eden+S0+S1

(2)堆

堆,主要用来存放类的对象实例信息。

堆分为Old Space(又名,Tenured Generation)和Young Space。

Old Space主要存放应用程序中生命周期长的存活对象;

Eden(伊甸园)主要存放新生的对象;

S0和S1是两个大小相同的内存区域,主要存放每次垃圾回收后Eden存活的对象,作为对象从Eden过渡到Old Space的缓冲地带(S是指英文单词Survivor Space)。

堆之所以要划分区间,是为了方便对象创建和垃圾回收,

2).线程内存区

线程内存区=单个线程内存+单个线程内存+.......

单个线程内存=PC Regster+JVM栈+本地方法栈

JVM栈=栈帧+栈帧+.....

栈帧=局域变量区+操作数区+帧数据区

四、查看内存使用情况

 Runtime run = Runtime.getRuntime();  
 long max = run.maxMemory();  
 long total = run.totalMemory();  
 long free = run.freeMemory(); 
 long usable = max - total + free;  
  System.out.println("最大内存 = " + max/1024/1024);  //以字节为单位 
  System.out.println("已分配内存 = " + total/1024/1024);  
  System.out.println("已分配内存中的剩余空间 = " + free/1024/1024);  
  System.out.println("最大可用内存 = " + usable/1024/1024); 

最大内存(maxMemory)是通过启动JAVA虚拟机时使用参数-Xmx100m指定的,而输出也确实是100m。这表示JVM的堆内存最大可以使用104071168字节。 

已分配内存(totalMemory)jvm使用的内存都是从本地系统获取的,但是通常jvm刚启动的时候,并不会向系统申请全部的内存。而是根据所加载的Class和相关资源的容量来决定的。在本例中,由于只在一个main()主方法中执行了上面的几行简单的代码。所以JVM只申请了5177344字节的内存。 

已分配内存中的剩余空间(freeMemory) 这是相对以分配内存(totalMemeory)计算的,相当于totalMemory - 已使用内存。当freeMemory 快要接近0时,以分配的内存即将耗尽,JVM会决定再次向系统申请更多的内存。 

最大可用内存 (usable)这是JVM真正还可以再继续使用的内存(不考虑之后垃圾回收再次得到的内存)。由【最大内存 - 已分配内存 + 已分配内存中的剩余空间】计算得到。

 




姓 名: *
邮 箱:
内 容: *
验证码: 点击刷新 *   

回到顶部