`

JVM内存区域与内存溢出

    博客分类:
  • JVM
阅读更多
[/b][b]运行时数据区:方法区、虚拟机栈、本地方法栈、堆、程序计数器。
程序计数器:作用是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
分支、循环、跳转、异常处理、线程恢复等都是依赖这个计数器来完成。

在任何一个确定的时刻,一个处理器只会执行一条线程中的指令。

Java虚拟机栈:也是线程私有的,每个方法被执行的时候都会同时创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息,
Java 虚拟机规范中规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverFlowError异常,
如果虚拟机栈可以动态扩展,当扩展无法申请到足够的内存时会抛出OutOfMemoryError异常

本地方法栈:为虚拟机使用到的Native方法服务。本地方法栈也会抛出StackOverFlowError和OutOfMemoryError异常。
Java堆:java虚拟机管理内存中最大的一块,被所有线程共享的一块内存,所有对象实例以及数组都要在堆上分配内存。Java堆是垃圾回收的主要区域。
        Java堆还可以分为新生代和年老代。
        java堆处于物理上不连续的区域 可通过-Xmx和-Xms控制扩展大小,如果堆中没有内存完成实例分配并且堆也无法扩展时,将会抛出OutOfMemoryError异常。


方法区:各个线程共享的内存。用于存储已经被虚拟机加载的类信息、常量、静态变量等信息

        运行时常量池:是方法区的一部分,用于存放编译期生成的各种字面变量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
        运行时常量池相对于Class文件常量池的另外一个重要的特性是动态性。运行期间也可能将新的常量放入池中,用的最多的是String类的intern()方法。

对象的访问:
   对于代码Object obj=new Object();
  首先java本地变量表中存储一个引用,而new Object又会在堆中开辟内存空间。
另外,java堆中还必须包含能查找到此对象类型的数据。(如:对象类型、父类型、实现的接口、方法等)的地址信息,这些类型数据存储在方法区中。

主流的访问方式为1:使用句柄 2.直接指针

内存溢出的代码:
 
 public class HeapOOM{
       static class OOMObject{}
       public static void main(String[] args)
       {
            List<OOMObject> list=new ArrayList<OOMObject>();
            while(true)
                list.add(new OOMObject());
       }
   }




虚拟机栈和本地方法栈的溢出:

HotSpot虚拟机不区分虚拟机栈和本地方法栈,栈容量只由-Xss参数设定。
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverFlowError异常
如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。

看如下代码:
  public class JavaVMStackOF{
     public int stackLength;
     public void stackLeak(){
        stackLength++;
        stackLeak();     
    }

    public static void main(String[] args){
        JavaVMStackOF oom=new JavaVMStackOF();
        oom.stackLeak();
 
    }

  }
 

以上代码会出现StackOverFlowError异常。实验证明在单线程下无论是栈帧太大还是虚拟机栈容量太小虚拟机抛出的都是StackOverFlowError异常。

操作系统分配给每个进程内存有限:
  栈内存=可分配内存限制(win 32位为2G)-Xmx(最大堆容量)-MaxPermSize(最大方法区容量)-程序计数器容量(忽略)

注意:每个线程分配的栈容量越大,可建立的线程数量则减小,建立线程时越容易把剩余内存耗尽。

public class JavaVMStackOOM{
   private void dontStop(){
        while(true){
        
          
        }
   }


   public void stackLeakByThread(){
        while(true){
            Thread thread=new Thread(new Runnable(){
                   public void run(){
                         dontStop();
                    }
             });
              thread.start();
        }

   }



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




运行时常量池溢出:

   实例代码如下:
  
 public class RuntimePoolOOM {

	
	public static void main(String[] args){
		
		List<String> list=new ArrayList<String>();
		int i=0;
		while(true){
		  //String.intern()方法作用是:如果池中已经包含一个等与此String对象的字符串,直接返回 否则将String对象中包含的字符串添加到常量池中。  
                           list.add(String.valueOf(i++).intern());
		}
		
		
	}

运行结果如下:Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
at java.lang.String.intern(Native Method)
at com.test.jvm.RuntimePoolOOM.main  (RuntimePoolOOM.java:16)
    }
分享到:
评论

相关推荐

    深入理解JVM内存区域与内存溢出异常

    深入理解JVM内存区域与内存溢出异常

    深入理解JVM内存结构及运行原理全套视频加资料.txt

     第4讲 jvm初体验-内存溢出问题的分析与解决 免费 00:17:59  第5讲 jvm再体验-jvm可视化监控工具 免费 00:21:17  第6讲 杂谈 免费 00:12:37  第7讲 Java的发展历史 00:27:24  第8讲 Java的发展历史续 00:...

    eclipse 内存溢出解决办法

    ermGen space的全称是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出,解决方法也一定是加大内存。说说为什么会内存益出:这一部分 用于存放Class和...

    Tomcat内存溢出的三种情况及解决办法分析

    可能是由于这些框架会动态class,而且jvm的gc是不会清理PemGen space的,导致内存溢出。 这一个一般是加大-XX:PermSize -XX:MaxPermSize 来解决问题。 -XX:PermSize 永久保存区域初始大小 -XX:PermSize 永久...

    深入理解Java虚拟机——Java内存区域与内存溢出异常.xmind

    这是自己读《深入理解Java虚拟机》时候用XMind建立的思维导图,目的是为了能够帮助自己整理、梳理相关的知识以及方便自己日后的回顾,帮助自己建立起关于JVM的知识体系,里边也有一些对相关内容的补充,通过备注的...

    Java内存区域与内存溢出

    内存区域  Java虚拟机在执行Java程序的过程中会把他所管理的内存划分为若干个不同的数据区域。Java虚拟机规范将JVM所管理的内存分为以下几个运行时数据区:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区...

    学习JVM之java内存区域与异常

    关于JVM内存区域的知识对于初学者来说其实是很重要的,了解Java内存分配的原理,这对于以后JAVA的学习会有更深刻的理解。下面来看看详细介绍。

    JVM基础学习图例 1、性能优化 2、类加载 3、JVM内存区域 4、JVM内存溢出 5、垃圾回收

    用于学习JVM基础,仅参考,结构图来源其他地方(忘记) (xmind中的备注内容为查找资料,直接保存的,可以参考来源链接)

    JVM 精华知识点汇总1

    前言文章对 JVM 内存区域分布、JVM 内存溢出分析、JVM 垃圾回收算法/垃圾收集器、JVM 性能调优工具及技巧、类加载等部分做了详细描述。用XMind画了

    深入理解Java虚拟机视频教程(jvm性能调优+内存模型+虚拟机原理)视频教程

    第4节jvm初体验-内存溢出问题的分析与解决 [免费观看] 00:17:59分钟 | 第5节jvm再体验-jvm可视化监控工具 [免费观看] 00:21:17分钟 | 第6节杂谈 [免费观看] 00:12:37分钟 | 第7节Java的发展历史00:27:24分钟 | ...

    java 内存泄漏的解决方案

    本文介绍了Java内存溢出的详细解决方案。本文总结内存溢出主要有两种情况,而JVM经常调用垃圾回收器解决内存堆不足的问题,但是有时...作者分析了JVM内存区域组成及JVM设置虚拟内存的方式,从而给出了一系列解决方案。

    tomcat内存的分配和溢出处理方法

    如何获得JVM的最大可用内存?内存溢出的处理办法:第一种:是堆溢出。第二种:永久保存区域溢出。第三种:无法创建新的线程。

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    第2章 Java内存区域与内存溢出异常 / 24 2.1 概述 / 24 2.2 运行时数据区域 / 25 2.2.1 程序计数器 / 25 2.2.2 Java虚拟机栈 / 26 2.2.3 本地方法栈 / 27 2.2.4 Java堆 / 27 2.2.5 方法区 / 28 2.2.6 运行...

    Java 内存区域与内存溢出

    内存区域  Java虚拟机在执行Java程序的过程中会把他所管理的内存划分为若干个不同的数据区域。Java虚拟机规范将JVM所管理的内存分为以下几个运行时数据区:程序计数器,Java虚拟机栈,本地方法栈,Java堆,方法区...

    java虚拟机JVM详解ppt

    详细介绍了java虚拟机和java内存区域的描述解释,并针对堆和栈的内存溢出进行了案例描述,是不可多得的分享资料

    【JVM和性能优化】1.Java内存区域

    文章目录了解的必要性JVM历史JVM数据区域私有区共有区内存区域版本变化1.61.71.8元空间栈跟堆Java中的对象都是在堆中分配吗逃逸分析标量替换栈上分配同步消除JVM对象对象创建过程对象内存布局对象访问方式通过句柄...

    java虚拟机知识点整理

    java内存区域与内存溢出处理 虚拟机栈和本地方法栈区别 对象定位访问 垃圾收集器GC管理 虚拟机GC垃圾回收收集算法(内存回收方法论) 虚拟机GC垃圾回收收集器(内存回收具体实现) 对象内存分配 虚拟机性能监控与故障...

    【JVM和性能优化】2.垃圾回收器和内存分配策略

    Compact)GC算法综合用年轻代老年代永久代枚举根节点安全点安全区域GC回收器Serial 收集器ParNew 收集器Parallel Scavenge 收集器Serial Old 收集器Parallel Old 收集器CMS 收集器G1 收集器ZGCSTW实现内存分配与回收...

    Java虚拟机

    第2章 Java内存区域与内存溢出异常 2.1 概述 2.2 运行时数据区域 2.2.1 程序计数器 2.2.2 Java虚拟机栈 2.2.3 本地方法栈 2.2.4 Java堆 2.2.5 方法区 2.2.6 运行时常量池 2.2.7 直接内存 2.3 HotSpot...

    Java常见面试问题整理.docx

    直接内存:不受JVM GC管理,直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/...

Global site tag (gtag.js) - Google Analytics