当前位置: 移动技术网 > IT编程>开发语言>Java > Java虚拟机常见内存溢出错误汇总

Java虚拟机常见内存溢出错误汇总

2020年09月13日  | 移动技术网IT编程  | 我要评论
一、引言从事java开发的小伙伴在平时的开发工作中,应该会遇见各式各样的异常和错误,在实际工作中积累的异常或者错误越多,趟过的坑越多,就会使我们编码更加的健壮,就会本能地避开很多严重的坑。以下介绍几个

一、引言

从事java开发的小伙伴在平时的开发工作中,应该会遇见各式各样的异常和错误,在实际工作中积累的异常或者错误越多,趟过的坑越多,就会使我们编码更加的健壮,就会本能地避开很多严重的坑。以下介绍几个java虚拟机常见内存溢出错误。以此警示,避免生产血案。

二、模拟java虚拟机常见内存溢出错误

1、内存溢出之栈溢出错误

package com.jayway.oom; 
 
/** 
 * 栈溢出错误 
 * 虚拟机参数:-xms10m -xmx10m 
 * 抛出异常:exception in thread "main" java.lang.stackoverflowerror 
 */
 public class stackoverflowerrordemo { 
 
 public static void main(string[] args) { 
  stackoverflowerror(); 
 } 
 
 private static void stackoverflowerror() { 
  stackoverflowerror(); 
 } 
 
}

2、内存溢出之堆溢出错误

package com.jayway.oom; 
 
import java.util.random; 
 
/** 
 * 堆溢出错误 
 * 虚拟机参数:-xmx10m -xms10m
 * 抛出异常:exception in thread "main" java.lang.outofmemoryerror: java heap space 
 */
 public class javaheapspaceerrordemo { 
 
 public static void main(string[] args) { 
  string temp = "java"; 
  //不断地在堆中开辟空间,创建对象,撑爆堆内存
  while (true) { 
    temp += temp + new random().nextint(111111111) + new random().nextint(222222222); 
    temp.intern(); 
  } 
 } 
}

3、内存溢出之gc超过执行限制错误

package com.jayway.oom; 
 
import java.util.arraylist; 
import java.util.list; 
 
/** 
 * gc超过执行限制错误 
 * 虚拟机参数:-xms10m -xmx10m -xx:+printgcdetails -xx:maxdirectmemorysize=5m 
 * * 抛出异常:exception in thread "main" java.lang.outofmemoryerror: gc overhead limit exceeded 
 * * 导致原因:gc回收时间过长会抛出outofmemoryerror,何为过长,即超过98%的cpu时间用来做gc垃圾回收 
 * 但是回收效果甚微,仅仅只有2%的cpu时间用来用户程序的工作,这种状态是很糟糕的,程序在不断地gc 
 * 形成恶性循环,cpu的使用率一直是满负荷的,正经活却没有干,这种情况虚拟机只好抛出错误来终止程序的执行 
 * 
 * 不断地full gc,事倍功微 
 * [full gc (ergonomics) [psyounggen: 2047k->2047k(2560k)] [paroldgen: 7167k->7161k(7168k)] 9215k->9209k(9728k), [metaspace: 3529k->3529k(1056768k)], 0.0291829 secs] [times: user=0.08 sys=0.02, real=0.03 secs] 
 */
 public class gcoverheaderrordemo { 
 
  public static void main(string[] args) { 
    int i = 0; 
    list<string> list = new arraylist<>(); 
    try { 
      while (true) { 
      list.add(string.valueof(++i).intern()); 
      } 
    } catch (throwable e) { 
      system.out.println("*****************i:" + i); 
      e.printstacktrace(); 
      throw e; 
    } 
  } 
}

4、内存溢出之直接内存溢出错误

package com.jayway.oom; 
 
import java.nio.bytebuffer; 
 
/** 
 * 直接内存溢出错误 
 * 抛出异常:exception in thread "main" java.lang.outofmemoryerror: direct buffer memory 
 * * 配置虚拟机参数:-xms10m -xmx10m -xx:+printgcdetails -xx:maxdirectmemorysize=5m 
 * * 导致原因:通常nio程序经常使用bytebuffer来读取或者写入数据,这是一种基于通道(channel)与缓冲区(buffer)的io方式, 
 * 它可以使用native函数库直接分配堆外内存,然后通过一个存储在java堆里面的directbytebuffer对象作为这块内存的引用, 
 * 这样能子一些场景中显著提高性能,因为避免了在java堆和native内存中来回复制数据。 
 * 
 * bytebuffer.allocate(capability):分配jvm堆内存,数据gc的管辖范围,由于需要拷贝所以速度相对较慢 
 * 
 * bytebuffer.allocate(capability):分配os本地内存,不属于gc管辖范围,由于不需要内存拷贝,所以速度相对较快。 
 * 
 * 但是如果不断分配本地内存,堆内存很少使用,那么jvm就不需要执行gc,directbytebuffer对象就不会被回收,此时如果继续分配堆外内存, 
 * 可能堆外内存已经被耗光了无法继续分配,此时程序就会抛出outofmemoryerror,直接崩溃。 
 * 
 */
 public class directbuffermemoryerrordemo { 
 
  public static void main(string[] args) { 
    //默认jvm配置的最大直接内存是总物理内存的四分之一 
    long maxdirectmemory = sun.misc.vm.maxdirectmemory() / 1024 / 1024; 
    system.out.println("配置的maxdirectmemory:" + maxdirectmemory + "mb"); 
 
    bytebuffer bytebuffer = bytebuffer.allocatedirect(6 * 1024 * 1024); 
  } 
 
}

5、内存溢出之无法创建新的本地线程

package com.jayway.oom; 
 
/** 
 * 内存溢出之无法创建新的本地线程 
 * 抛出异常:java.lang.outofmemoryerror: unable to create new native thread 
 * * 描述: 
 * 高并发请求服务器时,经常出现java.lang.outofmemoryerror: unable to create new native thread 
 *   native thread异常与对应的平台有关 
 * 
 * 导致原因: 
 *   1、应用程序创建了太多线程了,一个应用进程创建的线程数超过系统承载极限。 
 *   2、操作系统并不允许你的应用进程创建这么多的线程,linux系统默认允许单个进程可以创建的线程数是1024个 
 * 
 * 解决方法: 
 *   1、想办法降低应用进程创建的线程数量, 
 *   2、如果应用程序确实需要这么多线程,超过了linux系统的默认1024个限制,可以通过修改linux服务器配置,提高这个阈值。 
 * 
 */
 public class unablecreatenativethreaderrordemo { 
 
  public static void main(string[] args) { 
    for (int i = 0; true; i++) { 
      system.out.println("***************i:" + i); 
 
      //不断得创建新线程,直到超过操作系统允许应用进程创建线程的极限 
      new thread(() -> { 
        try { 
          thread.sleep(integer.max_value); 
        } catch (interruptedexception e) { 
          e.printstacktrace(); 
        } 
      }).start(); 
    } 
  } 
}

6、内存溢出之元空间溢出错误

package com.jayway.oom; 
 
import org.springframework.cglib.proxy.enhancer; 
import org.springframework.cglib.proxy.methodinterceptor; 
import org.springframework.cglib.proxy.methodproxy; 
 
import java.lang.reflect.method; 
 
/** 
 * 元空间溢出错误 
 * 抛出异常:java.lang.outofmemoryerror: metaspace 
 * * 设置虚拟机参数:-xx:metaspacesize=8m -xx:maxmetaspacesize=8m 
 * * 描述:java8及以后的版本使用metaspace来替代了永久代。metaspace是方法区在hotspot中的实现,它与持久代最大的区别在于 
 *   metaspace并不在虚拟机内存中而是在本地内存中。 
 * 
 * 元空间存储了以下信息: 
 *   1、虚拟机加载的类信息 
 *   2、常量池 
 *   3、静态变量 
 *   4、即时编译后的代码 
 * 
 */
 public class metaspaceerrordemo { 
 
  static class oomtest { 
  } 
 
  public static void main(string[] args) { 
    int count = 0; 
 
    try { 
    //cglib不断创建类,模拟metaspace空间溢出,我们不断生成类往元空间中灌,超过元空间大小后就会抛出元空间移除的错误 
      while (true) { 
        count++; 
        enhancer enhancer = new enhancer(); 
        enhancer.setsuperclass(oomtest.class); 
        enhancer.setusecache(false); 
        enhancer.setcallback(new methodinterceptor() { 
          @override 
          public object intercept(object o, method method, object[] objects, methodproxy methodproxy) throws throwable { 
            return methodproxy.invokesuper(o, args); 
          } 
        }); 
        enhancer.create(); 
      } 
    } catch (throwable e) { 
      system.out.println("************多少次后发生了异常:" + count); 
      e.printstacktrace(); 
    } 
  } 
}

以上就是java虚拟机常见内存溢出错误汇总的详细内容,更多关于java虚拟机内存溢出的资料请关注移动技术网其它相关文章!

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网