找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索

[ JAVA开发技术 ] 【守望者 j2se】虚拟机各部分内存溢出情况

2014-10-12 11:23| 发布者: zhouy | 查看: 2988 | 收藏

摘要: 通过简单的小例子程序,演示java虚拟机各部分内存溢出情况:(1).java堆溢出:Java堆用于存储实例对象,只要不断创建对象,并且保证GC Roots到对象之间有引用的可达,避免垃圾收集器回收实例对象,就会在对象数量达到 ...

通过简单的小例子程序,演示java虚拟机各部分内存溢出情况:

(1).java堆溢出:

Java堆用于存储实例对象,只要不断创建对象,并且保证GC Roots到对象之间有引用的可达,避免垃圾收集器回收实例对象,就会在对象数量达到堆最大容量时产生OutOfMemoryError异常。


想要方便快速地产生堆溢出,要使用如下java虚拟机参数:-Xms10m(最小堆内存为10MB),-Xmx10m(最大堆内存为10MB,最小堆内存和最大堆内存相同是为了避免堆动态扩展),-XX:+HeapDumpOnOutOfMemoryError可以让java虚拟机在出现内存溢出时产生当前堆内存快照以便进行异常分析。
例子代码如下:

public class HeapOOM{

    static class OOMObject{

  }

public static void main(String[] args){
    List<OOMObject> list = new ArrayList<OOMObject>();

   while(true){
       list.add(new OOMObject());

      }
    }
}

public class HeapOOM{  
    
  static class OOMObject{

     public static void main(String[] args){
      
     List<OOMObject> list = new ArrayList<OOMObject>();
     
    while(true){  
     
            list.add(new OOMObject());
       }
   }
}
运行一段时间就会发现产生OutOfMemoryError异常,并且产生了堆内存异常dump文件。

(2).java虚拟机栈和本地方法栈溢出:


由于Sun的HotSpot虚拟机不区分java虚拟机栈和本地方法栈,因此对于HotSpot虚拟机来说-Xoss参数(设置本地方法栈大小)虽然存在,但是实际上是无效的,栈容量只能由-Xss参数设定。

由于Java虚拟机栈会出现StackOverflowError和OutOfMemoryError两种异常,所以分别使用两个例子演示这两种情况:
a.java虚拟机栈深度溢出:

单线程的环境下,无论是由于栈帧太大,还是虚拟机栈容量太小,当内存无法再分配的时候,虚拟机总抛出StackOverflowError异常。使用-Xss128k将java虚拟机栈大小设置为128kb,例子代码如下:

public class JavaVMStackOF{

      private int stackLength = 1;
      public void stackLeak(){
      statckLength++;
           stackLeak();
     }
public static void main(String[] args){

     JavaVMStackOF oom = new JavaVMStackOF();
      oom.stackLeak();

}

}
public class JavaVMStackOF{
    
      private int stackLength = 1;
     
      public void stackLeak(){     
     
      statckLength++;              
      stackLeak();

  }
public static void main(String[] args){
     
    JavaVMStackOF oom = new JavaVMStackOF();
    oom.stackLeak();
}
}
运行一段时间后,产生StackOverflowError异常。Java虚拟机栈溢出一般会产生在方法递归调用过多而java虚拟机栈内存不够的情况下。

b.java虚拟机栈内存溢出:

多线程环境下,能够创建的线程最大内存=物理内存-最大堆内存-最大方法区内存,在java虚拟机栈内存一定的情况下,单个线程占用的内存越大,所能创建的线程数目越小,所以在多线程条件下很容易产生java虚拟机栈内存溢出的异常。

使用-Xss2m参数设置java虚拟机栈内存大小为2MB,例子代码如下:

public class JavaVMStackOOM{

private void dontStop(){
   while(true){

}

}

public void stackLeakByThread(){

while(true){

Thread t = new Thread(new Runnable(){

   public void run(){
              dontStop();
       }
     });
   t.start();
}
}
public static void main(String[] args){
        JavaVMStackOOM oom = new JavaVMStackOOM();
        oom. stackLeakByThread();.
    }
}


public class JavaVMStackOOM{
       
private void dontStop(){        
while(true){
}
}
public void stackLeakByThread(){ 
  
     while(true){               
     Thread t = new Thread(new Runnable(){    
    public void run(){      
        dontStop();
}});
  t.start();
}}

public static void main(String[] args){  
    
   JavaVMStackOOM oom = new JavaVMStackOOM();        
    oom. stackLeakByThread();

}}
运行一段时间之后,java虚拟机栈就会因为内存太小无法创建线程而产生OutOfMemoryError。

(3).运行时常量池溢出:


运行时常量池属于方法区的一部分,可以使用-XXPermSize=10m和-XX:MaxPermSize=10m将永久代最大内存和最小内存设置为10MB大小,并且由于永久代最大内存和最小内存大小相同,因此无法扩展。
String的intern()方法用于检查常量池中如果有等于此String对象的字符串存在,则直接返回常量池中的字符串对象,否则,将此String对象所包含的字符串添加到运行时常量池中,并返回此String对象的引用。因此String的intern()方法特别适合演示运行时常量池溢出,例子代码如下:


public class RuntimeConstantPoolOOM{

public static void main(String[] args){

        List<String> list = new ArrayList<String>();
        list.add(String.valueOf(i++).intern());
}
}
}


public class RuntimeConstantPoolOOM{
     
   public static void main(String[] args){
List<String> list = new ArrayList<String>();       
         int i = 0;          
      while(true){   
             list.add(String.valueOf(i++).intern());
}
}
}
运行一段时间,永久代内存不够,运行时常量池因无法再添加常量而产生OutOfMemoryError。

(4).方法区溢出:


运行时常量池是方法区的一部分,他们都属于HotSpot虚拟机中的永久代内存区域。方法区用于存放Class的相关信息,Java的反射和动态代理可以动态产生Class,另外第三方的CGLIB可以直接操作字节码,也可以动态产生Class,实验通过CGLIB来演示,同样使用-XXPermSize=10m和-XX:MaxPermSize=10m将永久代最大内存和最小内存设置为10MB大小,并且由于永久代最大内存和最小内存大小相同,因此无法扩展。例子代码如下:

public class JavaMethodAreaOOM{

  public static void main(String[] args){

   while(true){

                Enhancer enhancer = new Enhancer();

                enhancer.setSuperClass(OOMObject.class);

                 enhancer.setUseCache(false);

                enhancer.setCallback(new MethodInterceptor(){

                public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy)throws Throwable{
                 return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}
}

class OOMObject{
}
}
public class JavaMethodAreaOOM{ 
   
    public static void main(String[] args){  
  
    while(true){    
   
    Enhancer enhancer = new Enhancer();
      
     enhancer.setSuperClass(OOMObject.class); 
    
    enhancer.setUseCache(false);  
      
    enhancer.setCallback(new MethodInterceptor(){
      
     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)throws Throwable{
     
     return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}}
class OOMObject{} 
}
运行一段时间之后,永久代内存不够,方法区无法再存放CGLIB创建处理的Class信息,产生方法区OutOfMemoryError。

(5).本机直接内存溢出:

Java虚拟机可以通过参数-XX:MaxDirectMemorySize设定本机直接内存可用大小,如果不指定,则默认与java堆内存大小相同。JDK中可以通过反射获取Unsafe类(Unsafe的getUnsafe()方法只有启动类加载器Bootstrap才能返回实例)直接操作本机直接内存。通过使用-XX:MaxDirectMemorySize=10M,限制最大可使用的本机直接内存大小为10MB,例子代码如下:


public class DirectMemoryOOM{

                 private static final int _1MB = 1024* 1024 * 1024;

                publc static void main(String[] args) throws Exception{

                Field unsafeField = Unsafe.class.getDeclaredFields()[0];

               unsafeField.setAccessible(true);

                Unsafe unsafe = (Unsafe) unsafeField.get(null);

                while(true){

                         //unsafe直接想操作系统申请内存
                       unsafe.allocateMemory(_1MB);
}
}
}
public class DirectMemoryOOM{   
   
    private static final int _1MB = 1024* 1024 * 1024; 
  
     publc static void main(String[] args) throws Exception{ 
         
      Field unsafeField = Unsafe.class.getDeclaredFields()[0]; 
         
      unsafeField.setAccessible(true);        
      
      Unsafe unsafe = (Unsafe) unsafeField.get(null); 
       
     while(true){   
                 
      //unsafe直接想操作系统申请内存       
     unsafe.allocateMemory(_1MB);
     }
     }
}

当运行一段时间之后,10MB的本机直接内存被分配光,无法在进行直接内存分配时,产生OutOfMemoryError。


本文由守望者watchmen收集整理,部分内容源于网络(http://it.deepinmind.com)。本文仅代表作者个人观点,不代表守望者的本意。如有违法侵权内容,请提交到守望者管理员处,立即处理。

推荐阅读

【守望者  j2se】双向链表模拟
【守望者 j2se】双向链表模拟
我们熟悉了java单向链表的模拟,现在我就必须开始双向链表的模拟的.1.基础结构
【守望者  j2se】ConcurrentHashMap原理分析
【守望者 j2se】ConcurrentHashMap原
集合是编程中最常用的数据结构。而谈到并发,几乎总是离不开集合这类高级数据
【守望者 高并发】现有高并发WEB服务器 lighttpd Apache Nginx比较
【守望者 高并发】现有高并发WEB服务器
lighttpd网络服务器基于的Lighttpd的网络服务器具有这样的特点:占用内存资源
【守望者 高并发】C10K/C500K与I/O框架
【守望者 高并发】C10K/C500K与I/O框架
C10K、C/500K问题C10K 的意思是10000并发请求,C500K意思是500 000并发请求,
【守望者  JMM】理解volatile内存语义
【守望者 JMM】理解volatile内存语义
理解volatile变量对写多线程程序还是很有帮助的,这样就会避免一上来就是syn这
【守望者  j2se】虚拟机各部分内存溢出情况
【守望者 j2se】虚拟机各部分内存溢出
通过简单的小例子程序,演示java虚拟机各部分内存溢出情况:(1).java堆溢出:
【守望者 大数据】Mahout学习路线图
【守望者 大数据】Mahout学习路线图
Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Z
【守望者 高并发】使用CAS实现高效并发处理
【守望者 高并发】使用CAS实现高效并发
守望者:在并发处理应用中,一般使用锁的方式来解决竞争问题,但锁的效率比较
【守望者  j2se】吃透 java I/O 工作机制-1
【守望者 j2se】吃透 java I/O 工作机
I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这
【守望者 j2se】ConcurrentMap之putIfAbsent(key,value)用法讨论
【守望者 j2se】ConcurrentMap之putIfA
先看一段代码:public class Locale { private final static MapString, Lo
【守望者 大数据】机器学习已成为大数据的基石
【守望者 大数据】机器学习已成为大数
机器学习(Machine Learning, ML)是一门多领域交叉学科,涉及概率论、统计学、
【守望者  javascript】判断IE浏览器世界上最短的代码
【守望者 javascript】判断IE浏览器世
最短的IE判定var ie=!-分析以前最短的IE判定借助于IE不支持垂直制表符的特性
【守望者  j2se】多线程与并发知识点总结
【守望者 j2se】多线程与并发知识点总
对于多线程和并发编程这个比较大的技术模块,我们会整理一些帖子方便知识点的
【守望者  j2se】二叉树模拟
【守望者 j2se】二叉树模拟
接着我们就要写一个比较复杂的数据结构的,但是这个数据结构是很重要的,假如
【守望者 SRS  】SRS 源代码分析笔记(0.9.194)-分析服务器对端口的监听 ...
【守望者 SRS 】SRS 源代码分析笔记(
第一部分 分析服务器对端口的监听 端口监听与初始化(一)全局变量_srs_confi

行业聚焦  面试交流  职位推荐  开发视频   技术交流  腾讯微博  新浪微博

友情链接:课课家教育  阿里云  鲜果  W3Cfuns前端网  中国企业家  环球企业家  投资界  传媒梦工场  MSN中文网  Android开发者社区  cnbeta  投资中国网  又拍云存储  美通说传播  IT茶馆  网商在线  商业评论网  TechOrange  IT时代周刊  3W创新传媒  开源中国社区  二维工坊  Iconfans  推酷  智能电视网  FreeBuf黑客与极客  财经网  DoNews  凤凰财经  新财富  eoe移动开发者社区  i黑马  网易科技  新浪科技  搜狐IT  创业家  创业邦  腾讯财经  福布斯中文网  天下网商  TechWeb  雷锋网  新浪创业  和讯科技  品途O2O  极客公园  艾瑞网  抽屉新热榜  卖家网  人民网通信频道  拉勾网  创新派  简单云主机  

手机版|黑名单|守望者在线 在线教育 linux 高级程序设计 C/C++ 大数据 ( 蜀ICP备14029946号

成都守望者科技有限公司 © 2013-2016 All Rights Reserved