程序计数器

作用:

程序计数器是较小的内存空间,它可以当做是当前线程所执行的字节码的行号指示器

字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支循环跳转异常处理线程恢复等基础功能都需要依赖这个程序计数器来完成。

程序计数器的线程隔离性

java 虚拟机的多线程都是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时间,一个处理器(对于多核处理器来说是一个内核)都会只执行一条线程中的指令。因此为了保证线程的执行,每一个线程都有一个独立的线程计数器,各个线程的程序计数器 相互独立,互不影响。

说明:

  1. 如果线程执行的时一个Java代码,这个计数器记录的是正在执行的虚拟机字节码的指令地址
  2. 如果正在执行的时Native方法,这个计数器值则为空。
  3. 此内存区域是为一个在Java虚拟机中没有规定任何OutOfmemoryError情况的区域.

java 虚拟机栈

作用:

java 虚拟机栈描述的是java方法执行时候的内存模型。

每一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。
每一个方法从调用直至完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

哪些局部变量可以存放到java 虚拟机栈中?

局部变量表存放了预编译期的可知基本类型(boolean, byte, char, sort, short, int, float, long, double),对象引用(可能是一个指向对象的指针,也可能是指向一个代表对象的句柄)

64位长度的基本类型(long, double)会占用两个局部变量空间,其余的数据类型只占用一个。

说明

  1. 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError异常;
  2. 如果虚拟机栈可以动态扩展,扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常;

本地方法栈

本地方法栈与虚拟机栈所发挥的作用是非常相似的,他们的区别不过是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务

java 堆

对于绝大多数应用程序来说: Java 堆是java虚拟机所管理的内存中最大的一块。

Java 堆是被所有线程共享的一块内存区域,在虚拟机时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里面分配内存(随着JIT发展,所有对象都在堆上分配变得不再绝对)。

说明:

如果堆中没有内存完成实例分配,并且堆也无法在扩展时,将会抛出OutOfMemoryError异常。

方法区

方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息常量静态变量,即使编译器编译编译后的代码等数据。

运行时常量池

运行时常量池是方法区的一部分, Class 文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量中存放。

直接内存:

什么是直接内存?

直接内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。

在 JDK 1.4 中新加入了NIO类,引入了一种基于通道与缓冲区的I/O方式,他可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中DirectByteBuffer对象作为这块内存的引用进行操作。

OutOfMemoryError:

1.Java堆溢出

参数信息:

-Xms:最小堆大小
-Xmx:最大堆大小
-XX:+HeapDumpOnOutOfMemoryError : 打印堆信息

/**** <pre>*     -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError**     java -Xmx20m -Xms20m -XX:+HeapDumpOnOutOfMemoryError -cp jvm-study-1.0.jar com.saligia.HeapOOM*     java.lang.OutOfMemoryError: GC overhead limit exceeded*     Dumping heap to java_pid1530.hprof ...*     Heap dump file created [36732326 bytes in 0.165 secs]*     Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded*      at java.util.LinkedList.linkLast(LinkedList.java:142)*      at java.util.LinkedList.add(LinkedList.java:338)*      at com.saligia.HeapOOM.main(HeapOOM.java:23)* </pre>* @user : saligia* @date : 2018-05-09*/
public class HeapOOM {static class OOMObject{// 空对象在堆中还需要分配对象头信息(对象类信息引用,持有锁,对象hash码, gc分代年龄等)}public static void main(String[]  args){List<OOMObject> list = new LinkedList<OOMObject>();while(true){list.add(new OOMObject());}}
}

错误信息:java.lang.OutOfMemoryError: GC overhead limit exceeded

出现异常提示信息:java.lang.OutOfMemoryError: GC overhead limit exceeded,这里没有提示说堆还是持久代有问题,虚拟机只是告诉你你的程序花在垃圾回收上的时间太多了,却没有什么见效。默认的话,如果你98%的时间都花在GC上并且回收了才不到2%的空间的话,虚拟机才会抛这个异常。

2. 栈溢出(虚拟机栈,本地方法栈)

参数信息:

-Xss 栈大小

package com.saligia;/**** <pre>*     java -Xss128k**     java -Xss256k -cp jvm-study-1.0.jar com.saligia.JavaVMStackSOF*     stack length : 2293*      Exception in thread "main" java.lang.StackOverflowError*        at com.saligia.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)*        at com.saligia.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)*        at com.saligia.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)*        at com.saligia.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)*        at com.saligia.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)* </pre>* @user : saligia* @date : 2018-05-09*/
public class JavaVMStackSOF {private int stackLength = 1;public void stackLeak(){stackLength ++;stackLeak();}public static void main(String [] args) throws Throwable {JavaVMStackSOF oom  = new JavaVMStackSOF();try{oom.stackLeak();}catch (Throwable e){System.out.println("stack length : " + oom.stackLength);throw e;}}
}

错误信息:Exception in thread "main" java.lang.StackOverflowError

通过不断建立线程的方式也是可以产生内存溢出异常:

系统分配各每个进程的空间都是有限的,总的内存 - Xmx(最大堆) - MaxPerSize(最大方法区容量), 剩下的内存就基本被虚拟机栈和本地方法区瓜分了。

每个线程的虚拟机栈空间越大,允许创建的线程数量就越少,建立线程时就容易把剩下的内存耗尽。

所以,如果是建立过多线程导致的内存溢出,再不能减少线程数的情况下,就只能通过减少栈容量来换取更多的线程

3.方法区和运行时常量池溢出:

错误现象:Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

方法区溢出也是一种比较常见的现象:

  1. 程序使用了CGLib字节码增强和动态扩展语言外
  2. 大量的jsp 或动态产生JSP文件的应用
  3. 基于OSGi的应用。

4. 本机直接内存溢出:

DirectMemory 容量可以通过-XX:MaxDirectMemorySize指定,如果不指定,默认是与java堆大小相等。

由DirectMemory 导致的内存溢出,一个明显的特征就是在Heap Dump 文件中不会看见明显的异常,如果读者发现OOM之后Dump文件很小,而程序中有直接或间接的使用了NIO, 就可以考虑这方面的问题。

1-JVM之Java运行时数据区域相关推荐

  1. JVM学习笔记:Java运行时数据区域

    JVM执行Java程序的过程中,会使用到各种数据区域,这些区域有各自的用途.创建和销毁时间.根据<Java虚拟机规范>,JVM包括下列几个运行时数据区域,如下图所示: 其中红色部分是线程私 ...

  2. Java JVM内存模型(运行时数据区域)详解

    详细介绍了JVM运行时数据区域,包括方法区.堆空间.栈空间.本地方法栈.程序计数器.常量池.直接内存.字面量.符号引用.直接引用. Java程序在运行时,需要在内存中的分配空间.为了提高运算效率,ja ...

  3. Java 运行时数据区域,哪些是线程隔离的?哪些又是公有的?

    来自:会点代码的大叔 JVM 运行时数据区域大致可以分为:程序计数器.虚拟机栈.本地方法栈.堆区.元空间.运行时常量池.直接内存等区域:就是下面这个样子的: 其中有些区域,随着 JDK 版本的升级不断 ...

  4. Java 运行时数据区域

    运行时数据区域 Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁时间.以下是 Java 虚拟机所管理的内存区域: 程序 ...

  5. 一. JVM发展史,运行时数据区域,四大引用

    一.JVM的出现 JVM将字节码解释成不同os下的机器指令,有了jvm,java语言在不同平台上运行时不需要重新编译 虚拟机发展史 (1)Sun Classic classic jvm要么采用纯解释器 ...

  6. Java运行时数据区域

    一.java的运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有 ...

  7. [JVM-1]Java运行时数据区域

    Java虚拟机(JVM)内部定义了程序在运行时需要使用到的内存区域 这些区域都有自己的用途,以及创建和销毁的时间.有些区域随着虚拟机进程的启动而存在,有的区域则依赖用户线程的启动和结束而销毁和建立. ...

  8. 【深入理解JVM】JVM的五大运行时数据区域

    Run-time Data Areas 详细来看: 1.程序计数器(PC) 是线程独享的.是一块较小的内存,是当前线程所执行的字节码的行号指示器,是Java虚拟机规范中唯一没有被规定OOM(OutOf ...

  9. Java内存区域(运行时数据区域)和内存模型(JMM)

    原文作者:czwbig 原文:https://www.cnblogs.com/czwbig/p/11127124.html Java 内存区域和内存模型是不一样的东西,内存区域是指 Jvm 运行时将数 ...

最新文章

  1. 第七章——DMVs和DMFs(1)
  2. 【转】 ubuntu12.04更新源 官网和163等
  3. 从零开始netty学习笔记之BIO
  4. Linux_arm_启动_c语言部分详解,[原创]Linux arm 启动 c语言部分详解第四讲
  5. Educational Codeforces Round 54 (Rated for Div.2)
  6. 包包的结构制图_15种常见领型的结构制图
  7. 从放牛娃到北大博士,这篇论文后记刷屏
  8. word 职称计算机考试大纲,全国职称计算机考试Word2003大纲.doc
  9. DOM(二)——修改内容、属性、样式
  10. java面向对象的理解_java胜于C语言,却又静态面向对象,简单?
  11. 十年了,斯坦福和CMU的这场对决,开启了无人车时代
  12. java word转pdf jacob_java使用jacob.jar将word转pdf
  13. cmd做个定时弹窗_windows如何设置定时关机?
  14. 经典Python面试题之数据库和缓存
  15. 866 数据结构模拟题(一)及解析
  16. PS2接口键盘、鼠标改成USB接口
  17. 广义相对论与狭义相对论的区别
  18. uni-app,原生APP,关于苹果APP集成Sign in with Apple(通过Apple登录)后,APP内注册需要强制绑定手机号,审核被拒问题
  19. 爬虫模拟登陆的几种方法
  20. python numpy.fft.fft和ifft

热门文章

  1. 手把手教你安装 Fedora
  2. 如何让CFree5.0支持C++11
  3. SpringMVC、SpringMVC XML配置(纯XML方式)
  4. 狄利克雷分布通俗讲解
  5. CityMaker学习教程11 创建和移动标签
  6. SQLite Expert 5.X 通用注册版-你的SQL好帮手
  7. Parameter Attribute
  8. 学习四旋翼(三):DMP姿态解算和串级PID控制姿态
  9. 软件测试面试,如何自我介绍?
  10. 碧水风荷录-第一章(未完,正在整理中……)