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, ...
随机推荐
- PageRank与TrustRank影响因素分析
PageRank(PR)里的page不是指网页,而是指Google创始人拉里?佩奇(Larry Page),是他在2001年申请的专利中以自己名字命名的,Google的PageRank根据网站的外部链 ...
- javascript中的this指向问题
在深入学习JavaScript之后,我们越来越多的会遇到函数或者在对象内部中,对于this的指向问题的疑惑,其实基本上每一个编程语言中都有一个this,这个this的指向都是大同小异,你也可以汉化它的 ...
- Bootstrap 3 管理模板
下面这 10 个模板是从最新的 Bootstrap 3 管理模板人工挑选出来的,用来构建网站的后台管理界面,这些模板都是在最近 2 个月内发布. 1. Curo – Admin Template Cu ...
- SpringMVC学习系列(9) 之 实现注解式权限验证
对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servlet中的过滤器Filter来实现.但借助于Spring MV ...
- NSMutableAttributedString 富文本删除线的用法
#import <UIKit/UIKit.h> //价格 NSString *priceStr = @"99元 剁手价66元"; NSMutableAttributed ...
- BigDecimal 的roundMode 舍位模式
roundMode是指舍位时候的模式,传参数的时候用BigDecimal.ROUND_XXXX_XXX, 有: 以下例子是setScale(0,BigDecimal.ROUND_XXXX_XXX) ...
- flex loaderInfo为null在creationComplete事件中
原文: http://yunzhongxia.iteye.com/blog/1152670 Flex4中application变为FlexGlobals.topLevelApplication,很 ...
- Hbase预分区种子生成
提前生成Hbase预分区种子,在创建Hbase表时也进行相应的预分区,同时设置预分区的个数,预分区的范围对应Hbase监控页面的Region Server的start key与End key,从而使数 ...
- 如何查看oracle数据库告警日志
目标:查看alert日志 su - oracle cd $ORACLE_BASE/diag/rdbms/LXY/LXY/trace tail -100f alert_LXY.log 我的ORACLE_ ...
- 【javascript基础】6、new与构造函数
前言 上篇说创建对象的时候提到了带返回值的构造函数,那里没有和大家说这个问题,今天就和大家一起学习构造函数和new操作符.我也是最近才稍微弄明白点这个构造函数,以前总是忽略一些问题,现在就是想到哪块不 ...