1.Java内存区域
Java虚拟机在执行java程序的过程中会把他管理的内存划分为若干个不同的数据区域各自用途、创建以及销毁时间各不相同。有的随着虚拟机进行的启动而存在,有的区域依赖于线程的启动和结束而建立以及销毁。如图:

1.程序计数器
Jvm将这个计数看作当前线程(意味着只能支持单线程)执行某条字节码的行号指示器,会根据计数器的值来选取下一条需要执行的字节码指令。这个属于线程私有,不可共享,如果共享会导致计数混乱,无法准确的执行当前线程需要执行的语句。
如果一个线程正在执行java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果执行的是Native方法,这个计数器的值为空(Undefined)。
该区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError的情况,因为只需要表示计数器的值,这个值大小是恒定的。
注:一个Native Method就是一个Java调用非Java代码的接口。一个Native Method是这样一个Java的方法:该方法的实现由非Java语言实现,比如C或C++。
2.Java虚拟机栈
栈内存就是指虚拟机栈。Java中每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
虚拟机栈表述的是Java方法执行的内存模型:每个方法在执行的同时,都会创建一个栈帧(Stack Frame),用于存放局部变量表、操作数栈、动态链接、方法出口等。口头所说的“栈内存”就是虚拟机栈中局部变量表部分,局部变量表存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,不同于对象本身,可能指向一个对象起始地址的引用指针,也可能指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。
其中64位长度的long和double类型的数据会占用两个局部变量空间,其余数据类型只有一个。局部变量表所需的内存空间在编译期间完成分配。
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。
3.本地方法栈
虚拟机栈用来执行java方法,而本地方法栈用来执行本地方法。
抛出异常的情况和虚拟机栈一样会抛出StackOverflowError异常和OutOfMemoryError异常。
4.Java堆
是jvm中内存最大、线程共享的一块区域。所有线程共享的一块内存区域,在虚拟机启动时创建。唯一的目的是存储对象实例。这里也是垃圾收集器主要收集的区域(GC堆:GarbageCollected Heap)。由于现代垃圾收集器都采用的是分代收集算法,所以java堆也分为新生代和老年代。
线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB),与存放内容无关,都存的是对象实例。
Java堆可以处于物理上不连续的内存空间中,只要逻辑上连续即可。可以通过参数-Xmx(jvm最大可用内存)和-Xms(jvm初始内存)来调整堆内存,如果在堆中没有内存完成实例分配,并且堆也扩大至无法继续扩展时,会出现OutOfMemoryError的错误。
5.方法区("永久代")
Jvm中内存共享的一片区域,用来存储类信息、常量、静态变量、class文件。垃圾收集器也会对这部分区域进行回收,比如常量池的清理和类型的卸载,但是效果不理想。其 实现想像堆一样-XX:MaxPermSize设定管理这部分内存,而不用专门为该区进行内存管理编写代码。但是容易造成内存溢出,有逐步改为Native Memory来实现方法区的规划了,JDK1.7中已经把原本放在永久代的字符串常量池移出。
方法区内存不够用的时候,也会抛出OutOfMemoryError错误。
6.运行时常量池
运行时常量池是方法区的一部分(Runtime Constant Pool)。Class文件除了有类的版本、字段、方法、接口等信息,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这些内容在类加载后进入方法区的运行时常量池存放。
Java虚拟机堆Class文件有严格规定,但是对运行时常量池没有,一般来说除了保存Class文件中描述的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。运行期间也可将新的常量放入池中,如String类的inter()方法。
代码示例:
public class Test {
public static void main(String[] args){
String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);
}
}
在jdk1.6中,代码输出结果为false,false;在jdk1.7中,代码输出结果为true,false。 为什么会出现不一样的结果呢? 因为在jdk1.6中,intern()方法会把首次遇到的字符串实例复制到方法区中,然后返回方法区中这个字符串实例的引用,而StringBuilder创建的字符串实例在堆上,
因此两者返回的肯定不是同一个引用,所以两个数据结果都为false。 而在jdk1.7中,intern()方法不再复制实例,只是在常量池中记录首次出现的实例的引用,因此如果该字符串是首次出现的,那么intern()返回的结果
和StringBuilder创建的是同一实例。所以第一个输出的结果为true。但是因为“java”这个字符串在执行StringBuilder.toString()以前已经出现过了,
常量池中存的不是str2实例的引用,不符合“首次出现”原则,因此返回的结果不是指向同一个实例,即输出为false。
属于方法区,自然也受方法区限制,当常量池无法再申请到内存时会抛出OutOfMemoryError错误。
7.直接内存
直接内存(Direct Memory)不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的数据区域。
在JDK1.4中加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,可以使用Native函数库直接分配堆外内存,通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。在一些场景中避免在Java堆和Native堆中来回复制数据。
本级直接内存不会受Java堆大小限制,受本机总内存大小以及处理器寻址空间限制,动态扩展时超过物理内存限制会出现OutOfMemoryError异常。
总体概括如图:

1.Java内存区域的更多相关文章
- 【转】Java内存管理:深入Java内存区域
转自:http://www.cnblogs.com/gw811/archive/2012/10/18/2730117.html 本文引用自:深入理解Java虚拟机的第2章内容 Java与C++之间有一 ...
- Java 内存区域和GC机制分析
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java虚拟机2:Java内存区域及对象
几个计算机的概念 为以后写文章考虑,也为巩固自己的知识和一些基本概念,这里要理清楚几个计算机中的概念. 1.计算机存储单位 从小到大依次为位Bit.字节Byte.千字节KB.兆M.千兆GB.TB,相邻 ...
- Java 内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java系列笔记(3) - Java 内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java 内存区域划分
JVM的内存区域划分 学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的 ...
- Java内存管理:深入Java内存区域
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C和C++程序开发的开发人员来说,在内存管理领域,他们既是拥有最高权力的皇帝 ...
- 2016021801 - Java内存区域学习笔记
根据<深入理解java虚拟机>学习归纳整理学习笔记 程序计数器 用途:当前线程的字节码文件的行号指示器.(当前机场负责控制飞机降落的空管员:当前线程表示当前机场, 所执行的字节码等同于被等 ...
- Java 内存区域和GC机制--备用
Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 ...
- JAVA内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
随机推荐
- 第三节:视图(Views)和模板(Templates)
目录 概览 编写视图 编辑视图实际做一些事情 抛出404异常 使用模板系统 移除在代码中的硬编码网址 Url名称的命名空间 概览 视图是Django应用的网页的“类型”,一般服务于特定的功能并且有特定 ...
- 字符数组,字符指针,字符串常量,以及sizeof的一些总结
1.以字符串形式出现的,编译器都会为该字符串自动添加一个\0作为结尾 如在代码中写"abc",编译器帮你存储的是"abc\0". 2.数组的类型是由该数组所存放 ...
- innodb insert buffer 插入缓冲区的理解
今天在做一个大业务的数据删除时,看到下面的性能曲线图 在删除动作开始之后,insert buffer 大小增加到140.对于这些状态参数的说明 InnoDB Insert Buffer 插入缓冲,并不 ...
- Web前端图表绘制JQuery插件jqplot
在此之前使用了Chart.js.Highcharts,首先了解一下这两款插件的优势与不足,然后再来了解jqplot. 1.Chart Chart中文官网:http://chartjs.cn/ 1.1优 ...
- python中threading模块详解(一)
python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...
- JVM参数(三)打印所有XX参数及值
本篇文章基于Java 6(update 21oder 21之后)版本, HotSpot JVM 提供给了两个新的参数,在JVM启动后,在命令行中可以输出所有XX参数和值. -XX:+PrintFlag ...
- ruby formatting time
%Y%m%d => 20071119 Calendar date (basic) %F => 2007-11-19 Calendar date (extended) %Y-%m => ...
- 图的存储,搜索,遍历,广度优先算法和深度优先算法,最小生成树-Java实现
1)用邻接矩阵方式进行图的存储.如果一个图有n个节点,则可以用n*n的二维数组来存储图中的各个节点关系. 对上面图中各个节点分别编号,ABCDEF分别设置为012345.那么AB AC AD 关系可以 ...
- logstash 1.5.3 配置使用redis做续传
logstash是ELK中的一员大将, redis插件也是<The Logstash Book>中介绍的一个很好用的玩意儿. 之前,用比较小的集群部署的时候,没有介入redis中间件,所以 ...
- 压测 linux + jexus + mono + asp.net mvc
环境: 1.centos 7 + jexus 5.8.1 + mono 4.4.2 + asp.net mvc 4 做了一点小优化: 一.调整文件描述符数量限制编辑 /etc/security/lim ...