Java基础-JVM堆与栈
首先看一个解析列子
JVM的内存空间:
(1). Heap 堆空间:分配对象 new Student()
(2). Stack 栈空间:临时变量 Student stu
(3).Code 代码区 :类的定义,静态资源 Student.class
eg:Student stu = new Student(); //new 在内存的堆空间创建对象 stu.study(); //把对象的地址赋给stu引用变量
上例实现步骤:
a.JVM加载Student.class 到Code区 b.new Student()在堆空间分配空间并创建一个Student实例 c.将此实例的地址赋值给引用stu, 栈空间
java内存分区
运行时数据区即是java内存,而且数据区要存储的东西比较多,如果不对这块内存区域进行划分管理,会显得比较杂乱无章。程序喜欢有规律的东西,最讨厌杂乱无章的东西。
根据存储数据的不同,java内存通常被划分为5个区域:程序计数器(Program Count Register)、本地方法栈(Native Stack)、方法区(Methon Area)、栈(Stack)、堆(Heap)。
程序计数器(Program Count Register)
又叫程序寄存器。JVM支持多个线程同时运行,当每一个新线程被创建时,它都将得到它自己的PC寄存器(程序计数器)。如果线程正在执行的是一个Java方法(非native),那么PC寄存器的值将总是指向下一条将被执行的指令,如果方法是 native的,程序计数器寄存器的值不会被定义。 JVM的程序计数器寄存器的宽度足够保证可以持有一个返回地址或者native的指针。
栈(Stack):
又叫堆栈。JVM为每个新创建的线程都分配一个栈。也就是说,对于一个Java程序来说,它的运行就是通过对栈的操作来完成的。栈以帧为单位保存线程的状态。
JVM对栈只进行两种操作:以帧为单位的压栈和出栈操作。我们知道,某个线程正在执行的方法称为此线程的当前方法。我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的 Java堆栈里新压入一个帧,这个帧自然成为了当前帧。在此方法执行期间,这个帧将用来保存参数、局部变量、中间计算过程和其他数据。
从Java的这种分配机制来看,堆栈又可以这样理解:栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
其相关设置参数:
-Xss --设置方法栈的最大值
本地方法栈(Native Stack):
存储本地方方法的调用状态。
方法区(Method Area):
当虚拟机装载一个class文件时,它会从这个class文件包含的二进制数据中解析类型信息,然后把这些类型信息(包括类信息、常量、静态变量等)放到方法区中,该内存区域被所有线程共享,如下图所示。本地方法区存在一块特殊的内存区域,叫常量池(Constant Pool),这块内存将与String类型的分析密切相关。
堆(Heap):
Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域。在此区域的唯一目的就是存放对象实例,几乎所有的对象实例都是在这里分配内存,但是这个对象的引用却是在栈(Stack)中分配。
如,执行String s = new String("s")时,需要从两个地方分配内存:在堆中为String对象分配内存,在栈中为引用(这个堆对象的内存地址,即指针)分配内存,如下图所示。
JAVA虚拟机有一条在堆中分配新对象的指令,却没有释放内存的指令,正如你无法用Java代码区明确释放一个对象一样。虚拟机自己负责决定如何以及何时释放不再被运行的程序引用的对象所占据的内存,通常,虚拟机把这个任务交给垃圾收集器(Garbage Collection)。其相关设置参数:
-Xms -- 设置堆内存初始大小
-Xmx -- 设置堆内存最大值
-XX:MaxTenuringThreshold -- 设置对象在新生代中存活的次数
-XX:PretenureSizeThreshold -- 设置超过指定大小的大对象直接分配在旧生代中
Java堆是垃圾收集器管理的主要区域,因此又称为“GC 堆”(Garbage Collectioned Heap)。现在的垃圾收集器基本都是采用的分代收集算法,所以Java堆还可以细分为:新生代(Young Generation)和老年代(Old Generation),如下图所示。分代收集算法的思想:第一种说法,用较高的频率对年轻的对象(young generation)进行扫描和回收,这种叫做minor collection,而对老对象(old generation)的检查回收频率要低很多,称为major collection。这样就不需要每次GC都将内存中所有对象都检查一遍,以便让出更多的系统资源供应用系统使用;另一种说法,在分配对象遇到内存不足时,先对新生代进行GC(Young GC);当新生代GC之后仍无法满足内存空间分配需求时, 才会对整个堆空间以及方法区进行GC(Full GC)。
在这里可能会有读者表示疑问:记得还有一个什么永久代(Permanent Generation)的啊,难道它不属于Java堆?亲,你答对了!其实传说中的永久代就是上面所说的方法区,存放的都是jvm初始化时加载器加载的一些类型信息(包括类信息、常量、静态变量等),这些信息的生存周期比较长,GC不会在主程序运行期对PermGen Space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen Space错误。其相关设置参数:
-XX:PermSize --设置Perm区的初始大小
-XX:MaxPermSize --设置Perm区的最大值
新生代(Young Generation)又分为:Eden区和Survivor区,Survivor区有分为From Space和To Space。Eden区是对象最初分配到的地方;默认情况下,From Space和To Space的区域大小相等。JVM进行Minor GC时,将Eden中还存活的对象拷贝到Survivor区中,还会将Survivor区中还存活的对象拷贝到Tenured区中。在这种GC模式下,JVM为了提升GC效率, 将Survivor区分为From Space和To Space,这样就可以将对象回收和对象晋升分离开来。新生代的大小设置有2个相关参数:
-Xmn -- 设置新生代内存大小。
-XX:SurvivorRatio -- 设置Eden与Survivor空间的大小比例
老年代(Old Generation): 当 OLD 区空间不够时, JVM 会在 OLD 区进行 major collection ;完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现"Out of memory错误" 。
Java基础-JVM堆与栈的更多相关文章
- 十六、JAVA基础(堆和栈)
一.堆和栈 堆和栈都是JAVA中的存储结构,也就是说,都是内存中存放数据的地方. 1.堆:(存放由new创建的对象和数组) 引用类型的变量,内存分配一般在堆上或者常量池(字符串常量,基本数据类型常量) ...
- JAVA基础知识|堆和栈
一.java六个存储数据的地方 1)寄存器(register):这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据需求进行分配.你不能直 ...
- Java基础-JVM调优策略简介
Java基础-JVM调优策略简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.JVM结构分析 1>.JVM结构图 2>.JVM运行时数据区功能说明 JVM管理的内 ...
- java中的堆、栈、常量池
java中的堆.栈.常量池 分类: java2010-01-15 03:03 4248人阅读 评论(5) 收藏 举报 javastring编译器jvm存储equals Java内存分配: 1. 寄存器 ...
- java中的堆与栈
Java 中的堆和栈 Java把内存划分成两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配 . 当在一段代码块定义一个变量时,Java就在栈中 ...
- 详细介绍Java中的堆、栈和常量池
下面主要介绍JAVA中的堆.栈和常量池: 1.寄存器 最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈 存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在 ...
- Java中的堆和栈
Java中的堆和栈 栈内存 存放基本数据类型和引用变量 堆内存 存放运行时创建的对象 一般来说,通过new关键字创建出来的对象都放在堆内存中 由于JVM是基于堆栈的虚拟机,而每个Java程序都运行在一 ...
- java中的堆、栈、常量池以及String类型的两种声明
参考自http://blog.sina.com.cn/s/blog_798b04f90100ta67.html http://www.cnblogs.com/fguozhu/articles/2661 ...
- (转)Java里的堆(heap)栈(stack)和方法区(method)(精华帖,多读读)
[color=red][/color]<一> 基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收. 引用数据类型,需要用new来创建,既在栈 ...
随机推荐
- JSON对象和字符串之间的相互转换
比如我有两个变量,我要将a转换成字符串,将b转换成JSON对象: var a={"name":"tom","sex":"男&quo ...
- C语言中,&和&&都是做什么的?
&按位&&逻辑与 逻辑运算符把各个运算的变量(或常量)连接起来组成一个逻辑表达式.逻辑运算符有4个,它们分别是: !(逻辑非). ||(逻辑或).&&(逻辑与) ...
- View (三) 视图绘制流程完全解析
相 信每个Android程序员都知道,我们每天的开发工作当中都在不停地跟View打交道,Android中的任何一个布局.任何一个控件其实都是直接或间 接继承自View的,如TextView.Butto ...
- Volley(五)—— 自定义Request
详细解读Volley(四)—— 自定义Request Volley中提供了几个Request,如果我们有特殊的需求,完全可以自定义Request的,自定义Request自然要继承Request,那么本 ...
- jq 获取table元素,ajax 静态填加数据
知识点: 1.jq如何操作table->操作html内的元素 2. this 怎么使用 问题: 1.点击 修改 后,自动刷新了.判断取值,提示错误.正确出不来 2.ajax传值操作如何保密 ht ...
- 10Spring_AOP编程(传统编程)
注意我写这篇文章的思路,要想做切面编程,包含两个部分,通知和切点,通知是你要做哪些增强,切点是指你要拦截哪些方法.先介绍通知的定义再去介绍切点的定义.这篇文章我取名叫做Spring_AOP编程(传统编 ...
- Rdlc报表出现空白页解决方法(转)
在使用RDLC报表时,碰到这种情况:当只有一页数据时,报表确显示两页,第二页除了报表头之外数据为空.然后,当有多页数据时,最后一页为空. 这个问题很奇怪,网上有很多解决方案,以下的方法可以解决此问题. ...
- Android应用程序窗口(Activity)的窗口对象(Window)的创建过程分析(转)
在前文中,我们分析了Android应用程序窗口的运行上下文环境的创建过程.由此可知,每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一 ...
- EasyUI Tree判断节点是否是叶
方法1: $('#domaincatalog').tree('isLeaf', node.target); 返回true或false ,true表示是叶节点, false即不是 方法2:官方文档中: ...
- 20135326、20135303-linux实验一实验报告
北京电子科技学院(BESTI) 实 验 报 告 课程:信息安全系统设计基础 班级:1353 姓名:王亦可 .魏昊卿 学号:20135326.20135303 成绩: ...