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, ...
随机推荐
- SQL Server使用convert对datetime日期数据进行获取
来源:http://database.51cto.com/art/201007/211883.htm 备注:本文的语法讲解确实是比较乱,似乎格式不太严谨.参考时还是以实例验证为准比较好 以下的文章主要 ...
- CSS之圣杯布局与双飞翼布局
圣杯布局 三行等高 HTML: <!DOCTYPE html><html><head> <meta charset="utf-8"& ...
- mysql优化思路
/* mysql优化思路 1.数据库设计 2.sql语句优化 3.数据库参数设置 4.恰当的硬件资源和操作系统 数据库设计 数据的3NF( ...
- Debian系统常用配置
每一次安装Linux之后总需要设置一下系统,下面把常用的设置总结一下,方便以后使用: 1.系统安装包选择 每一次找Linux的安装包时,总会纠结一下选哪个好,我在这里总结一下:安装Debian选择对应 ...
- Tcpdump非常实用的抓包12实例
1.过滤主机---------------------------------------------------------------- - 抓取所有经过 eth1,目的或源地址是 192.168 ...
- 如何修改SVN已提交项目的message log
直接在TortoiseSVN中修改过往日志,会提示: DAV request failed;it's possible that the repository's pre-revprop-change ...
- FreeMarker模板引擎
现在开发的项目,也是基于SOA架构,每个功能接口都是用WebService实现,Web服务的通信协议就是用XML来传输. 以前写WebService都是自动生成XML,没想到这项目竟然要自己定义XML ...
- python(27)requests 爬取网页乱码,解决方法
最近遇到爬取网页乱码的情况,找了好久找到了种解决的办法: html = requests.get(url,headers = head) html.apparent_encoding html.enc ...
- EditText----
==============01 editText属性 1.输入法Enter键图标的设置: 软件盘的界面替换只有一个属性android:imeOptions,这个属性的可以取的值有normal,a ...
- gerrit 解决中文乱码相关配置(转载)
From:http://www.cnblogs.com/Jerryshome/archive/2012/04/19/2457170.html 计划在团队中采用code review,因为一直是用git ...