设为首页 加入收藏

TOP

深入理解java虚拟机[内存溢出实例](一)
2014-11-24 03:19:28 】 浏览:6953
Tags:深入 理解 java 虚拟 内存 溢出 实例

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

(1).java堆溢出:

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

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

例子代码如下:

[java]
  1. public class HeapOOM{
  2. static class OOMObject{
  3. }
  4. public static void main(String[] args){
  5. List list = new ArrayList ();
  6. while(true){
  7. list.add(new OOMObject());
  8. }
  9. }
  10. }

    运行一段时间就会发现产生OutOfMemoryError异常,并且产生了堆内存异常dump文件。

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

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

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

    a.java虚拟机栈深度溢出:

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

    [java]
    1. public class JavaVMStackOF{
    2. private int stackLength = 1;
    3. public void stackLeak(){
    4. statckLength++;
    5. stackLeak();
    6. }
    7. public static void main(String[] args){
    8. JavaVMStackOF oom = new JavaVMStackOF();
    9. oom.stackLeak();
    10. }
    11. }

      运行一段时间后,产生StackOverflowError异常。Java虚拟机栈溢出一般会产生在方法递归调用过多而java虚拟机栈内存不够的情况下。

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

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

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

      [java]
      1. public class JavaVMStackOOM{
      2. private void dontStop(){
      3. while(true){
      4. }
      5. }
      6. public void stackLeakByThread{
      7. while(true){
      8. Thread t = new Thread(new Runnable(){
      9. public void run(){
      10. dontStop();
      11. }
      12. });
      13. t.start();
      14. }
      15. }
      16. public static void main(String[] args){
      17. JavaVMStackOOM oom = new JavaVMStackOOM();
      18. oom. stackLeakByThread();.
      19. }
      20. }

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

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

        运行时常量池属于方法区的一部分,可以使用-XX:PermSize=10m和-XX:MaxPermSize=10m将永久代最大内存和最小内存设置为10MB大小,并且由于永久代最大内存和最小内存大小相同,因此无法扩展。

        String的intern()方法用于检查常量池中如果有等于此String对象的字符串存在,则直接返回常量池中的字符串对象,否则,将此String对象所包含的字符串添加到运行时常量池中,并返回此String对象的引用。因此String的intern()方法特别适合演示运行时常量池溢出,例子代码如下:

        [java]
        1. public class RuntimeConstantPoolOOM{
        2. public static void main(String[] args){
        3. List list = new ArrayList ();
        4. int i = 0;
        5. while(true){
        6. list.add(String.valueOf(i++).intern());
        7. }
        8. }
        9. }

          运行一段时间,永久代内存不够,运行时常量池因无法再添加常量而产生OutOfMemoryError。

          (4).方法区溢出:

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

          [java]
          1. public class JavaMethodAreaOOM{
          2. public static void main(String[] args){
          3. while(true){
          4. Enhancer enhancer = new Enhancer();
          5. enhancer.setSuperClass(OOMObject.class);
          6. enhancer.setUseCache(false);
          7. enhancer.setCallback(new MethodInterceptor(){
          8. public Object intercept(Object obj, Method method, Object[] args,
          9. MethodProxy proxy)throws Throwable{
          10. return proxy.invokeSuper(obj, args);
          11. }
          12. });
          13. enhancer.create();
          14. }
          15. }
          16. class OOMObject{
          17. }
          18. }

            运行一段时间之后,永久代内存不够,方法区无法再存放CGLIB创建处理的Class信息,产生方法区OutOfMemoryError。

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

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

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇HashMap的并发问题 下一篇工厂模式-简单工厂模式

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目