最近在看《深入理解Java虚拟机》,书中给了几个例子,比较好的说明了几种OOM(OutOfMemory)产生的过程,大部分的程序员在写程序时不会太关注Java运行时数据区域的结构:

感觉有必要通过几个实在的例子来加深对这几个区域的了解

1)Java堆

所有对象的实例分配都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,sample如下所示:

  1. public class HeapOOM {
  2. static class OOMObject{}
  3. /**
  4. * @param args
  5. */
  6. public static void main(String[] args) {
  7. List<OOMObject> list = new ArrayList<OOMObject>();
  8. while(true){
  9. list.add(new OOMObject());
  10. }
  11. }
  12. }
public class HeapOOM {

	static class OOMObject{}

	/**
* @param args
*/
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>(); while(true){
list.add(new OOMObject());
}
} }

加上JVM参数-verbose:gc -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError,就能很快报出OOM:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

并且能自动生成Dump。

2)方法区

方法区是存放虚拟机加载类的相关信息,如类、静态变量和常量,大小由-XX:PermSize和-XX:MaxPermSize来调节,类太多有可能撑爆永久带:

  1. public class MethodAreaOOM {
  2. static class OOMOjbect{}
  3. /**
  4. * @param args
  5. */
  6. public static void main(String[] args) {
  7. // TODO Auto-generated method stub
  8. while(true){
  9. Enhancer eh = new Enhancer();
  10. eh.setSuperclass(OOMOjbect.class);
  11. eh.setUseCache(false);
  12. eh.setCallback(new MethodInterceptor(){
  13. @Override
  14. public Object intercept(Object arg0, Method arg1,
  15. Object[] arg2, MethodProxy arg3) throws Throwable {
  16. // TODO Auto-generated method stub
  17. return arg3.invokeSuper(arg0, arg2);
  18. }
  19. });
  20. eh.create();
  21. }
  22. }
  23. }
public class MethodAreaOOM {

	static class OOMOjbect{}

	/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
while(true){
Enhancer eh = new Enhancer();
eh.setSuperclass(OOMOjbect.class);
eh.setUseCache(false);
eh.setCallback(new MethodInterceptor(){ @Override
public Object intercept(Object arg0, Method arg1,
Object[] arg2, MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
return arg3.invokeSuper(arg0, arg2);
} });
eh.create();
}
} }

加上永久带的JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后会报如下异常:

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

静态变量或常量也会有可能撑爆方法区:

  1. public class ConstantOOM {
  2. /**
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. // TODO Auto-generated method stub
  7. List<String> list = new ArrayList<String>();
  8. int i=0;
  9. while(true){
  10. list.add(String.valueOf(i++).intern());
  11. }
  12. }
  13. }
public class ConstantOOM {

	/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List<String> list = new ArrayList<String>();
int i=0;
while(true){
list.add(String.valueOf(i++).intern());
}
} }

同样加上JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后报如下异常:

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

3)Java栈和本地方法栈

栈是存放线程调用方法时存储局部变量表,操作,方法出口等与方法执行相关的信息,栈大小由Xss来调节,方法调用层次太多会撑爆这个区域,samples如下所示:

  1. package com.cutesource;
  2. public class StackOOM {
  3. /**
  4. * @param args
  5. */
  6. private int stackLength = 1;
  7. public void stackLeak(){
  8. stackLength++;
  9. stackLeak();
  10. }
  11. public static void main(String[] args) throws Throwable{
  12. // TODO Auto-generated method stub
  13. StackOOM oom = new StackOOM();
  14. try{
  15. oom.stackLeak();
  16. }catch(Throwable err){
  17. System.out.println("Stack length:" + oom.stackLength);
  18. throw err;
  19. }
  20. }
  21. }
package com.cutesource;

public class StackOOM {

	/**
* @param args
*/ private int stackLength = 1; public void stackLeak(){
stackLength++;
stackLeak();
} public static void main(String[] args) throws Throwable{
// TODO Auto-generated method stub
StackOOM oom = new StackOOM();
try{
oom.stackLeak();
}catch(Throwable err){
System.out.println("Stack length:" + oom.stackLength);
throw err;
} } }

设置JVM参数:-Xss128k,报出异常:

Exception in thread "main" java.lang.StackOverflowError

打印出Stack length:1007,这里可以看出,在我的机器上128k的栈容量能承载深度为1007的方法调用。当然报这样的错很少见,一般只会出现无限循环的递归中,另外,线程太多也会占满栈区域:

  1. package com.cutesource;
  2. public class StackOOM {
  3. /**
  4. * @param args
  5. */
  6. private int stackLength = 1;
  7. private void dontStop(){
  8. while(true){
  9. try{Thread.sleep(1000);}catch(Exception err){}
  10. }
  11. }
  12. public void stackLeakByThread(){
  13. while(true){
  14. Thread t = new Thread(new Runnable(){
  15. @Override
  16. public void run() {
  17. // TODO Auto-generated method stub
  18. dontStop();
  19. }
  20. });
  21. t.start();
  22. stackLength++;
  23. }
  24. }
  25. public static void main(String[] args) throws Throwable{
  26. // TODO Auto-generated method stub
  27. StackOOM oom = new StackOOM();
  28. try{
  29. oom.stackLeakByThread();
  30. }catch(Throwable err){
  31. System.out.println("Stack length:" + oom.stackLength);
  32. throw err;
  33. }
  34. }
  35. }
package com.cutesource;

public class StackOOM {

	/**
* @param args
*/ private int stackLength = 1; private void dontStop(){
while(true){
try{Thread.sleep(1000);}catch(Exception err){}
}
} public void stackLeakByThread(){
while(true){
Thread t = new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
dontStop();
} });
t.start();
stackLength++;
}
} public static void main(String[] args) throws Throwable{
// TODO Auto-generated method stub
StackOOM oom = new StackOOM();
try{
oom.stackLeakByThread();
}catch(Throwable err){
System.out.println("Stack length:" + oom.stackLength);
throw err;
} } }

报出异常:Exception in thread "main" java.lang.OutOfMemoryError:unable to create new native thread

不过在windows上运行这个例子要小心,会出现系统假死的情况,有可能需要重启机器才行。

以上几个例子虽然比较简单,但能很好帮助普通的程序员更加直观的了解Java堆方法区Java栈和本地方法栈

从几个sample来学习JAVA堆、方法区、JAVA栈和本地方法栈的更多相关文章

  1. jvm:内存结构(堆、方法区、程序计数器、本地方法栈、虚拟机栈)

    1.jvm内存结构 静态编译:把java源文件编译成字节码文件class,这个时候class文件以静态方式存在. 类加载器:把java字节码文件加载到内存中 方法区:将字节码放到方法区作为元数据(简单 ...

  2. JVM 运行时数据区:程序计数器、Java 虚拟机栈和本地方法栈,方法区、堆以及直接内存

    Java 虚拟机可以看作一台抽象的计算机,如同真实的计算机,它也有自己的指令集和运行时内存区域. Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存(运行时内存区域)划分为若干个不同的数 ...

  3. Java虚拟机栈和本地方法栈

    Java虚拟机栈的特征 线程私有 后进先出(LIFO)栈 存储栈帧,支持Java方法的调用.执行和退出 可能出现OutOfMemoryError异常和StackOverflowError异常 Java ...

  4. java虚拟机 jvm java堆 方法区 java栈

    java堆是java应用程序最密切的内存空间.几乎所有的对象都存在堆中.java堆完全自动化管理,通过垃圾回收机制,垃圾对象会自动清理,不需要显式释放. 根据java垃圾回收机制的不同,java堆可能 ...

  5. java高级用法之:在JNA中将本地方法映射到JAVA代码中

    目录 简介 Library Mapping Function Mapping Invocation Mapping 防止VM崩溃 性能考虑 总结 简介 不管是JNI还是JNA,最终调用的都是nativ ...

  6. Java虚拟机03(Java虚拟机内存模型)

    根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 其实最需要Java程序员关注的是堆,栈,还有方法区,因为啊: 如果代码又问题的话,可能回出现栈溢出 然后说 ...

  7. 【JAVA基础】05 Java语言基础:数组

    1. 数组概述和定义格式说明 为什么要有数组(容器) 为了存储同种数据类型的多个值 数组概念 数组是存储同一种数据类型多个元素的集合.也可以看成是一个容器. 数组既可以存储基本数据类型,也可以存储引用 ...

  8. 从sample来学习Java堆(转)

    1)Java堆 所有对象的实例分配都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,sample如下所示: public class HeapOOM { static class OOMOb ...

  9. JVM学习001通过实例总结Java虚拟机的运行机制

    JVM学习(1)——通过实例总结Java虚拟机的运行机制-转载http://www.cnblogs.com/kubixuesheng/p/5199200.html 文章转载自:http://www.c ...

随机推荐

  1. iOS AVAudioPlayer 提示音

    NSString *urlPath = [[NSBundle mainBundle] pathForResource:@"" ofType:@""]; NSUR ...

  2. C#编程实现朴素贝叶斯算法下的情感分析

    C#编程实现 这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Lang ...

  3. apache window环境下本地配置虚拟主机

    1.在httpd.conf中去掉如下注释: # Virtual hostsInclude conf/extra/httpd-vhosts.conf 2.在 httpd-vhosts.conf添加内容 ...

  4. WINDOWS 2012忘记密码之后。。。

    要使用windows server 2012安装DVD,选择光盘引导进入 进入修复系统 选择疑难解答,进入界面 选择命令提示符 切换目录至系统目录 执行move命令 执行 copy命令 重新启动系统, ...

  5. hadoop 1.2.1 安装步骤 伪分布式

    最近在系统的学习hadoop 课程第一步是安装hadoop1.x,具体安装步骤如下: 一.系统安装 本文使用centos6.5安装,具体安装步骤省略 二.jdk安装 下载jdk1.7.0_51解压,在 ...

  6. linux svn用法

    创建一个版本库.项目目录. 创建一个版本库: svnadmin create ~/SVNTestRepo 创建一个项目目录: svn mkdir file:///home/lsf/SVNTestRep ...

  7. CString 的一些事

    MFC Visual Studio 2008 CString 的 Format 中不能这样存在str.Format(_T("Cool(\%)"));  或者 str.Format( ...

  8. Only2 Labs — A Visual Design Studio

    Only2 Labs - A Visual Design Studio 设计合作 对您目前的设计很不满意?或是急缺一个设计供应商?您的团队最近做的项目需要指导?Only2都很乐意为您解困惑. 或者,你 ...

  9. Android学习笔记__1__Android体系架构

    Android 体系结构图 Android作为一个移动设备的平台,其软件层次结构包括了一个操作系统(OS),中间件(MiddleWare)和应用程序(Application).根据Android的软件 ...

  10. 2个2D向量计算交点的夹角和补角

    2维向量如何计算与某一个交点之间的夹角,假设A,B是向量,C是他们共同连接的一个点计算出A-C-B形成的角度   我们先了解几个简单的计算: 2D向量的乘积计算 (A.x * B.x + A.y * ...