首先上图,了解一下大概结构

1、程序计数器

程序计数器(Program Counter)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。

如果线程正在执行的是一个Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址(方法区的地址);如果正在执行的是Natvie 方法,这个计数器值则为空(Undefined)。

2、Java 虚拟机栈

与程序计数器一样,Java 虚拟机栈也是线程私有的,它的生命周期与线程相同。是一个后进先出的数据结构,用来描述Java 方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame )用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double、reference、returnAddress 。其中64 位长度的long 和double 类型的数据会占用2 个局部变量空间(Slot),其余的数据类型只占用1 个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

在Java 虚拟机规范中,如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError 异常,虚拟机栈大小可以通过JVM选项-Xss来进行调整。

3、本地方法栈

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,是为虚拟机使用到的Native 方法服务,本地方法栈区域也会抛出StackOverflowError 和OutOfMemoryError异常。

4、Java 堆

Java 堆是Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。但是随着JIT 编译器的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也渐渐变得不是那么“绝对”了。

根据Java 虚拟机规范的规定,Java 堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms 控制)。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError 异常。

  • Eden区 —— 新对象或者生命周期很短的对象会存储在这个区域中,这个区的大小可以通过-XX:NewSize和-XX:MaxNewSize参数来调整。新生代GC(垃圾回收器)会清理这一区域。
  • Survivor区 —— 那些历经了Eden区的垃圾回收仍能存活下来的依旧存在引用的对象会待在这个区域。这个区的大小可以由JVM参数-XX:SurvivorRatio来进行调节。
  • 老年代 —— 那些在历经了Eden区和Survivor区的多次GC后仍然存活下来的对象(当然了,是拜那些挥之不去的引用所赐)会存储在这个区里。这个区会由一个特殊的垃圾回收器来负责。年老代中的对象的回收是由老年代的GC(major GC)来进行的。

4、方法区

方法区(Method Area)与Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java 堆区分开来。

      • 持久代 —— 这个区域会存储包括类定义,结构,字段,方法(数据及代码)以及常量在内的类相关数据。它可以通过-XX:PermSize及-XX:MaxPermSize来进行调节。如果它的空间用完了,会导致java.lang.OutOfMemoryError: PermGen space的异常,使用String 类的intern() 方法可以将String动态加入到常量池。事实上,持久代已经被彻底删除了,取代它的是另一个内存区域也被称为 元空间。
      • 元空间 ---- 是本地堆内存中的一部分,可以通过-XX:MetaspaceSize和-XX:MaxMetaspaceSize来进行调整,当到达XX:MetaspaceSize所指定的阈值后会开始进行清理该区域,

如果本地空间的内存用尽了会收到java.lang.OutOfMemoryError: Metadata space的错误信息。持久代相关的JVM参数-XX:PermSize及-XX:MaxPermSize将会被忽略掉。代码缓存——这个缓存区域是用来存储编译后的代码。编译后的代码就是本地代码(硬件相关的),它是由JIT(Just In Time)编译器生成的,这个编译器是Oracle HotSpot JVM所特有的。

5、直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError 异常出现,

在JDK 1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用Native 函数库直接分配堆外内存,然后通过一个存储在Java 堆里面的DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java 堆和Native 堆中来回复制数据。

显然,本机直接内存的分配不会受到Java 堆大小的限制,但是,既然是内存,则肯定还是会受到本机总内存(包括RAM 及SWAP 区或者分页文件)的大小及处理器寻址空间的限制。服务器管理员配置虚拟机参数时,一般会根据实际内存设置-Xmx等参数信息,但经常会忽略掉直接内存,使得各个内存区域的总和大于物理内存限制,从而导致动态扩展时出现OutOfMemoryError异常。

http://ifeve.com/jvm-permgen-where-art-thou/
http://blog.csdn.net/javastart/article/details/50868029

关于JVM内存模型的一些总结的更多相关文章

  1. JVM内存模型、指令重排、内存屏障概念解析

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  2. JVM内存模型和性能优化 转

    JVM内存模型和性能优化 JVM内存模型优点 内置基于内存的并发模型:      多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于 ...

  3. JVM内存模型和性能优化

    JVM内存模型优点 内置基于内存的并发模型:      多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于数据库锁. 多核并行计算模 ...

  4. JVM初探 -JVM内存模型

    JVM初探 -JVM内存模型 标签 : JVM JVM是每个Java开发每天都会接触到的东西, 其相关知识也应该是每个人都要深入了解的. 但接触了很多人发现: 或了解片面或知识体系陈旧. 因此最近抽时 ...

  5. JVM内存模型和关键参数设置

    一. JVM内存模型: Jvm内存模型是学好Java很重要的一部分,该部分学习能让我们在系统运维的时候,或者优化服务器的时候能够有方法,懂原理. 二. Jvm关键参数: 1. 堆大小设置参数: -Xm ...

  6. 记录JVM内存模型,参数含义和优化

    一.JVM内存模型 (图片来自网络) 根据Java虚拟机规范,JVM将内存划分为: New(年轻代) Tenured(年老代) Perm (永久代) 其中New和Tenured属于堆内存,堆内存会从J ...

  7. 【转】JVM内存模型

    http://longdick.iteye.com/blog/473866 图解JVM内存模型 博客分类: JVM JVM活动SUN  /** *  转载请注明作者longdick    http:/ ...

  8. jvm内存模型和内存分配

    1.什么是jvm? (1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的. (2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和 ...

  9. JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集

    (转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...

  10. Java基础知识强化100:JVM 内存模型

    一. JVM内存模型总体架构图:  方法区和堆由所有线程共享,其他区域都是线程私有的 二. JVM内存模型的结构分析: 1. 类装载器(classLoader) 类装载器,它是在java虚拟机中用途是 ...

随机推荐

  1. shell之路【第三篇】流程控制

    if语句 if ... fi 语句: if ... else ... fi 语句: if ... elif ... else ... fi 语句. 注意: expression 和方括号([ ])之间 ...

  2. 浅谈测试rhel7新功能时的感受及遇到的问题【转载】

    半夜起来看世界杯,没啥激情,但是又怕错误意大利和英格兰的比赛,就看了rhel7 相关新功能的介绍. rhel7的下载地址: https://access.redhat.com/site/downloa ...

  3. C陷阱与缺陷 第二章

    有关运算符优先级   1. "<<" 和 "+" data8 = data4H << 4 +data4L; 这里本意是让高四位的数据,左 ...

  4. cordova环境配置步骤

    1.安装node.js环境 官网: http://nodejs.org/ 2.sudo npm install -g cordova(一般会失败,需要用FQ安装或者用淘宝镜像安装,可以用FQ就可以不用 ...

  5. doclint in jdk8

    http://blog.joda.org/2014/02/turning-off-doclint-in-jdk-8-javadoc.html Turning off doclint in JDK 8 ...

  6. MyBatis-执行插入语句的时候返回主键ID到传入的参数对象中

    <!-- 保存项目信息 --> <insert id="saveItem" parameterType="pd" useGeneratedKe ...

  7. wpf 类似TextBlock外观的Button的样式

    <Style x:Key="noborderbtnStyle" TargetType="{x:Type Button}"> <Setter P ...

  8. JSP中文编码问题

    这个乱码问题是最简单的乱码问题.一般新会出现.就是页面编码不一致导致的乱码. <%@ page language="java" pageEncoding="UTF- ...

  9. CI 路由设置

    $route['news/show/(:num)']='news/show/$1';   前边是匹配 网址   后边是  指定控制器 在application/config/文件夹下有routes.p ...

  10. Integer比较值的时候小心使用

    package integerdemo; public class IntegerDemo { public static void main(String[] args) { //-128--127 ...