java虚拟(一)--java内存区域和常量池概念
一、java运行时数据区
也可以称为java内存区域,和java内存模型不是一回事,不要弄混,这里基于jdk1.8之前

1.1、方法区
线程共享,类装载过程中产生的java.lang.Class对象保存在方法区,而不是堆,请参考《深入理解java虚拟机》P215
jdk1.8之前HotSpot通过永久带实现方法区,为了把GC可以像堆一样管理内存,能够复用代码,1.8移除永久带,通过本地内存实现方法区,
其他虚拟机没有永久带的概念,因为更容易出现内存溢出
主要存放类信息、常量、静态变量、即时编译后的代码等
垃圾回收主要是针对常量池回收和类型的卸载,这块区域的回收很难,尤其是类型卸载,可以选择不进行垃圾回收,但是回收很有必要的
PS:jdk1.8及以后,方法区被移除,通过元空间实现,而元空间使用的是直接内存,可以使用参数:-XX:MetaspaceSize来指定元数据区的大小
1.2、虚拟机栈
线程私有,生命周期和线程相同,每执行一个方法都会创建一个栈帧,从执行到结束,对应着栈帧在虚拟机栈的入栈到出栈过程,可以类比
数据结构中的栈,java方法两种返回方式:
1、return语句
2、抛出异常
这两种方式都会导致栈帧被弹出
栈帧:
保存着局部变量表、操作数栈、方法出入口等
局部变量表:
用来保存方法参数和返回值,也就是基本数据类型、对象的引用、returnAddress类型(指向一个字节码指令的地址)
double和long占用两个局部变量空间(variable slot),其余占用1个,slot空间大小在编译期间就确定,方法运行期间无法改变
PS:可能出现Stack OverflowError、OutOfMemoryError错误
1.3、本地方法栈
线程私有,和虚拟机栈相似,一个为Java方法服务,一个为了本地方法服务,本地方法栈中方法实现的语言、方式等没有规定,由具体的虚拟机
确定,在HotSpot中只有栈,没有虚拟机栈和本地方法栈的区别。
本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态链接、出口信息。
PS:可能出现Stack OverflowError、OutOfMemoryError错误
1.4、堆
线程共享,这是虚拟机内存最大的一块区域,也是GC的主要区域,几乎所有的对象和数组都保存在这里
内存回收的角度分为:
新生代:Eden Space、From Survivor、To Survivor
老年代:
1、主要用来保存大对象(可以通过-XX:PretenureSizeThreshold 设置大对象的阀值)
2、或者从新生代经过15次 minor GC存活下来的对象(-XX:MaxTenuringThreshold)
3、第二条不是绝对的,VM动态判断,如果Survivor空间中相同年龄所有对象大小的综合大于Survivor空间的一半,年龄大于或等于该
年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold要求的年龄
默认Eden Space:From Survivor:To Survivor=8:1:1,可以通过-XX:SurvivorRatio调节,一般不需要新生代和老年代默认是1:2,
可以通过-XX:NewRatio调节
PS:进一步划分的目的是更好地回收内存,或者更快地分配内存。
1.5、程序计数器
线程私有,是一块很小的内存区域,记录着当前虚拟机字节码指令的地址(对于JNI,值为undefined),字节码解释器通过改变计数器的值来
选择下一条执行的字节码,分支、循环、跳转、异常处理、线程恢复等功能都要依靠计数器。
线程上下文切换的时候,为了能够恢复到正确的执行位置,需要每个线程都拥有一个独立的线程计数器,互不影响。
PS:唯一一个没有规定OOM的区域
1.6、直接内存
不属于Java内存区域,有可能出现OOM,jdk1.4出现了NIO,它可以通过Native函数库分配堆外内存,通过Java堆中的DirectByteBuffer对象
作为引用进行操作,在某些场景明显提高性能,以为避免了Java堆和Native堆来回复制数据。
直接内存的分配不受Java堆大小限制,而是收到本机总内存的限制。
1.7、本地内存
就是JMM的概念了,后面写JMM的时候再讲
二、常量池
2.1、字符串常量池
在HotSpot中通过StringTable类实现功能,StringTable是一个hash表,默认长度大小1009,被所有类共享。字符串常量由字符组成,保存在
StringTable上面。在jdk1.6当中,StringTable的长度是固定1009,如果存放在StringTable中的字符串很多,造成hash冲突的几率很大,链表过
长,当通过String.intern()查找String Pool时,性能就会降低。
在jdk1.7当中,StringTable的长度可以通过-XX:StringTableSize设置
存放的内容:
String.intern()主要是为了复用字符串常量,节省内存空间
在jdk1.6及以前的版本,存放的都是字符串常量,使用""声明的字符串都存储在这,例如:String str = "abc";
在jdk1.7之后,String.intern()发生变化,返回对象的引用,因此除了字符串常量,也可以存放堆中字符串常量的引用
PS:在jdk1.7之后,字符串常量池从方法区转移到堆中
2.2、class常量池
首先java代码通过javac编译成class文件,class文件中保存着类的相关信息(版本,类、字段、方法、接口等信息),除此之外,还有Class
常量池,用来存放编译器产生的各种字面量(Literal)和符号引用(Symbolic References),每个class文件都有一个class常量池。
字面量:1.String 2.基本数据类型 3.声明final的常量
符号引用:1.类和方法的全限定名(类似于com.cfets.**.**这种) 2.字段的名称和描述符 3.方法的名称和描述符
2.3、运行时常量池
就是class常量池被加载到方法区之后的版本,区别就是:字面量可以通过String.intern()动态添加,符号引用解析为直接引用(类加载的
解析阶段)
当类加载到内存之中,jvm会把class常量池的内存存放到运行时常量池,所以,运行时常量池也是每个class都有的。
符号引用:上述有说明。以一组符号来描述所引用的目标,只要能定位到目标,无论是任何形式的字面量,和jvm实现的内存布局无关。
直接引用:直接指向目标的指针、相对偏移量或者间接定位到目标的句柄,句柄和指针对应对象的访问定位方式,和jvm实现的内存布局有关。
PS:JDK1.7及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池
java虚拟(一)--java内存区域和常量池概念的更多相关文章
- Java中常用的内存区域
在Java中主要存在4块内存空间,这些内存空间的名称及作用如下. 1. 栈内存空间: 保存所有对象名称(更准确的说是保存了引用的堆内存空间的地址). 2. 堆内存空间: 保存每个对象的具体属性内容 ...
- java中的堆、栈、常量池
java中的堆.栈.常量池 分类: java2010-01-15 03:03 4248人阅读 评论(5) 收藏 举报 javastring编译器jvm存储equals Java内存分配: 1. 寄存器 ...
- 详细介绍Java中的堆、栈和常量池
下面主要介绍JAVA中的堆.栈和常量池: 1.寄存器 最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈 存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在 ...
- JVM学习笔记(一):Java虚拟机和虚拟机内存区域
为什么Java程序需要运行在虚拟机上 因为Java在设计之初的跨平台特性,我们知道Java程序是运行在Java虚拟机上的.如果你要问为什么Java程序要运行在虚拟机上,我可以反问你几个问题. 为什么买 ...
- Java虚拟机运行时内存区域简析
figure:first-child { margin-top: -20px; } #write ol, #write ul { position: relative; } img { max-wid ...
- 【java】JVM的内存区域划分
学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的呢? 由于Java程序是交由JVM执行 ...
- java运行时的内存区域
1.概述 java虚拟机在执行java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线 ...
- java中的常用内存区域总结
<开发实战经典> (1)栈内存空间:保存所有的对象名称 (2)堆内存空间:保存每个对象的具体属性内容 (3)全局数据区:保存static类型的属性 (4)全 ...
- Java内存中的常量池
1,java内存模型简介 <深入理解java虚拟机>里将java内存分为如下五个模块: 堆-堆是所有线程共享的,主要用来存储对象. 其中,堆可分为:新生代和老年代两块区域.使用NewRat ...
随机推荐
- Go语言核心之美 3.2-slice切片
Slice(切片)是长度可变的元素序列(与之相应,上一节中的数组是不可变的),每一个元素都有同样的类型.slice类型写作[]T.T是元素类型.slice和数组写法非常像,差别在于slice没有指定长 ...
- linux句柄泄露问题查看
背景: 我们在开发linux在线server的时候常常会遇会句柄泄露的问题.由于在linux系统设计里面遵循一切都是文件的原则.即磁盘文件.文件夹.网络套接字.磁盘.管道等,全部这些都是文件.在我们进 ...
- ubuntu系统下,下载Android源码
博主电脑的Windows的 是用的vmware装的ubuntu kylin.vmware随便找都能找到尽量安装最新版本号的,而unbuntu在官方站点下载即可了,安装vmware的时候建议关闭安全类 ...
- 20170626_oracle_数据库设计
数据库设计的定义:规划数据库中数据对象以及之间关系的过程. 为什么进行数据库设计? 空间 完整性 程序开发 数据库设计前提知识: 范式: 1NF:第一范式 第一范式的目标是确保每列的原子性 如果每列都 ...
- centos ifconfig 无法使用问题
centos ifconfig 无法使用问题 # ifconfig bash: ifconfig: command not found # yum search ifconfig Loaded plu ...
- iOS 开发 公司开发者账号,在多台Mac上合作开发,共用一个账号和证书--图文详解
参考 导出证书申请的MAC里的Xcode的开发者账号 .developerprofile 导出的开发者账号文件.developerprofile 导出PKCS12既是.p12文件 所拷贝的资料, .d ...
- C# winfrom TCP 服务端和客户端(链接)
1.C#Winform TCP 之服务端: 可以参考下面链接,比较好.第二个链接可以看看,提供了一个思路. http://www.cnblogs.com/guolebin7/archive/2013/ ...
- hdoj--2187--悼念512汶川大地震遇难同胞——老人是真饿了(贪心)
悼念512汶川大地震遇难同胞--老人是真饿了 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
- 10.04 FZSZ模拟Day1 总结
今天轮到FZSZ出题了,这可是连续两年捧杯NOI的学校了…… 可想而知今天题难度有多大……不过似乎还要庆幸出题的是一位叫Anzhe Wang 的大神而不是fjzzq? T1.permutation 期 ...
- JavaScript代码优化新工具UglifyJS
jQuery 1.5 发布的时候 john resig 大神说所用的代码优化程序从Google Closure切换到UglifyJS,新工具的压缩效果非常令人满意. UglifyJS 是一个服务端no ...