JVM基础:深入学习JVM堆与JVM栈
转自:http://developer.51cto.com/art/201009/227812.htm
JVM栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;JVM堆解决的是数据存储的问题,即数据怎么放、放在哪儿,另外JVM堆中存的是对象。JVM栈中存的是基本数据类型和JVM堆中对象的引用。
JVM基础概念:JVM堆与JVM栈
数据类型
Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,即:他代表的值就是数值本身;而引用类型的变量保存引用值。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址的位置。
基本类型包括:byte,short,int,long,char,float,double,Boolean,returnAddress
引用类型包括:类类型,接口类型和数组。
JVM堆与JVM栈
JVM堆和JVM栈是程序运行的关键,很有必要把他们的关系说清楚。
JVM栈是运行时的单位,而JVM堆是存储的单位。
JVM栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;JVM堆解决的是数据存储的问题,即数据怎么放、放在哪儿。
在Java中一个线程就会相应有一个线程JVM栈与之对应,这点很容易理解,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程JVM栈。而
JVM堆则是所有线程共享的。JVM栈因为是运行单位,因此里面存储的信息都是跟当前线程(或程序)相关信息的。包括局部变量、程序运行状态、方法返回值
等等;而JVM堆只负责存储对象信息。
为什么要把JVM堆和JVM栈区分出来呢?JVM栈中不是也可以存储数据吗?
第一,从软件设计的角度看,JVM栈代表了处理逻辑,而JVM堆代表了数据。这样分开,使得处理逻辑更为清晰。分而治之的思想。这种隔离、模块化的思想在软件设计的方方面面都有体现。
第二,JVM堆与JVM栈的分离,使得JVM堆中的内容可以被多个JVM栈共享(也可以理解为多个线程访问同一个对象)。这种共享的收益是很多的。
一方面这种共享提供了一种有效的数据交互方式(如:共享内存),另一方面,JVM堆中的共享常量和缓存可以被所有JVM栈访问,节省了空间。
第三,JVM栈因为运行时的需要,比如保存系统运行的上下文,需要进行地址段的划分。由于JVM栈只能向上增长,因此就会限制住JVM栈存储内容的
能力。而JVM堆不同,JVM堆中的对象是可以根据需要动态增长的,因此JVM栈和JVM堆的拆分,使得动态增长成为可能,相应JVM栈中只需记录JVM
堆中的一个地址即可。
第四,面向对象就是JVM堆和JVM栈的完美结合。其实,面向对象方式的程序与以前结构化的程序在执行上没有任何区别。但是,面向对象的引入,使得
对待问题的思考方式发生了改变,而更接近于自然方式的思考。当我们把对象拆开,你会发现,对象的属性其实就是数据,存放在JVM堆中;而对象的行为(方
法),就是运行逻辑,放在JVM栈中。我们在编写对象的时候,其实即编写了数据结构,也编写的处理数据的逻辑。不得不承认,面向对象的设计,确实很美。
在Java中,Main函数就是JVM栈的起始点,也是程序的起始点。
程序要运行总是有一个起点的。同C语言一样,java中的Main就是那个起点。无论什么java程序,找到main就找到了程序执行的入口:)
JVM堆中存什么?JVM栈中存什么?
JVM堆中存的是对象。JVM栈中存的是基本数据类型和JVM堆中对象的引用。一个对象的大小是不可估计的,或者说是可以动态变化的,但是在JVM栈中,一个对象只对应了一个4btye的引用(JVM堆JVM栈分离的好处:))。
为什么不把基本类型放JVM堆中呢?因为其占用的空间一般是1~8个字节——需要空间比较少,而且因为是基本类型,所以不会出现动态增长的情况——
长度固定,因此JVM栈中存储就够了,如果把他存在JVM堆中是没有什么意义的(还会浪费空间,后面说明)。可以这么说,基本类型和对象的引用都是存放在
JVM栈中,而且都是几个字节的一个数,因此在程序运行时,他们的处理方式是统一的。但是基本类型、对象引用和对象本身就有所区别了,因为一个是JVM栈
中的数据一个是JVM堆中的数据。最常见的一个问题就是,Java中参数传递时的问题。
Java中的参数传递时传值呢?还是传引用?
要说明这个问题,先要明确两点:
1.不要试图与C进行类比,Java中没有指针的概念
2.程序运行永远都是在JVM栈中进行的,因而参数传递时,只存在传递基本类型和对象引用的问题。不会直接传对象本身。
明确以上两点后。Java在方法调用传递参数时,因为没有指针,所以它都是进行传值调用(这点可以参考C的传值调用)。因此,很多书里面都说Java是进行传值调用,这点没有问题,而且也简化的C中复杂性。
但是传引用的错觉是如何造成的呢?在运行JVM栈中,基本类型和引用的处理是一样的,都是传值,所以,如果是传引用的方法调用,也同时可以理解为
“传引用值”的传值调用,即引用的处理跟基本类型是完全一样的。但是当进入被调用方法时,被传递的这个引用的值,被程序解释(或者查找)到JVM堆中的对
象,这个时候才对应到真正的对象。如果此时进行修改,修改的是引用对应的对象,而不是引用本身,即:修改的是JVM堆中的数据。所以这个修改是可以保持的
了。
对象,从某种意义上说,是由基本类型组成的。可以把一个对象看作为一棵树,对象的属性如果还是对象,则还是一颗树(即非叶子节点),基本类型则为树
的叶子节点。程序参数传递时,被传递的值本身都是不能进行修改的,但是,如果这个值是一个非叶子节点(即一个对象引用),则可以修改这个节点下面的所有内
容。
JVM堆和JVM栈中,JVM栈是程序运行最根本的东西。程序运行可以没有JVM堆,但是不能没有JVM栈。而JVM堆是为JVM栈进行数据存储服务,说白了JVM堆就是一块共享的内存。不过,正是因为JVM堆和JVM栈的分离的思想,才使得Java的垃圾回收成为可能。
Java中,JVM栈的大小通过-Xss来设置,当JVM栈中存储数据比较多时,需要适当调大这个值,否则会出现java.lang.StackOverflowError异常。常见的出现这个异常的是无法返回的递归,因为此时JVM栈中保存的信息都是方法返回的记录点。
JVM基础:深入学习JVM堆与JVM栈的更多相关文章
- JVM基础系列第14讲:JVM参数之GC日志配置
说到 Java 虚拟机,不得不提的就是 Java 虚拟机的 GC(Garbage Collection)日志.而对于 GC 日志,我们不仅要学会看懂,而且要学会如何设置对应的 GC 日志参数.今天就让 ...
- JVM基础系列第11讲:JVM参数之堆栈空间配置
JVM 中最重要的一部分就是堆空间了,基本上大多数的线上 JVM 问题都是因为堆空间造成的 OutOfMemoryError.因此掌握 JVM 关于堆空间的参数配置对于排查线上问题非常重要. tips ...
- JVM基础系列第9讲:JVM垃圾回收器
前面文章中,我们介绍了 Java 虚拟机的内存结构,Java 虚拟机的垃圾回收机制,那么这篇文章我们说说具体执行垃圾回收的垃圾回收器. 总的来说,Java 虚拟机的垃圾回收器可以分为四大类别:串行回收 ...
- JVM基础系列第8讲:JVM 垃圾回收机制
在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由<Java 虚拟机规范>指定的,每个 Java 虚拟机可能都有不同的实现.其实涉及到 Java 虚拟机的内存, ...
- JVM基础系列第13讲:JVM参数之追踪类信息
我们都知道 JVM 在启动的时候会去加载类信息,那么我们怎么得知他加载了哪些类,又卸载了哪些类呢?我们这一节就来介绍四个 JVM 参数,使用它们我们就可以清晰地知道 JVM 的类加载信息. 为了方便演 ...
- JVM基础系列第7讲:JVM 类加载机制
当 Java 虚拟机将 Java 源码编译为字节码之后,虚拟机便可以将字节码读取进内存,从而进行解析.运行等整个过程,这个过程我们叫:Java 虚拟机的类加载机制.JVM 虚拟机执行 class 字节 ...
- JVM基础系列第10讲:垃圾回收的几种类型
我们经常会听到许多垃圾回收的术语,例如:Minor GC.Major GC.Young GC.Old GC.Full GC.Stop-The-World 等.但这些 GC 术语到底指的是什么,它们之间 ...
- JVM基础系列第6讲:Java 虚拟机内存结构
看到这里,我相信大家对于一个 Java 源文件是如何变成字节码文件,以及字节码文件的含义已经非常清楚了.那么接下来就是让 Java 虚拟机运行字节码文件,从而得出我们最终想要的结果了.在这个过程中,J ...
- JVM类加载过程学习总结
JVM类加载过程学习总结 先不说JVM类加载的原理,先看实例: NormalTest类,包含了一个静态代码块,执行的任务就是打印一句话. /** * 在正常类加载条件下,看静态代码块是否会执行 * @ ...
- JVM基础系列第15讲:JDK性能监控命令
查看虚拟机进程:jps 命令 jps 命令可以列出所有的 Java 进程.如果 jps 不加任何参数,可以列出 Java 程序的进程 ID 以及 Main 函数短名称,如下所示. $ jps 6540 ...
随机推荐
- Flips测试类(page43)
测试用例:所用java类: StdOut,StdIn , Counter, StdRandom, public class Flips { public static void main(String ...
- Oracle DBA需掌握的命令集锦(推荐)
第一章:日志管理 1.forcing log switches sql> alter system switch logfile; 2.forcing checkpoints sql> a ...
- ES6:JavaScript 新特性
我相信,在ECMAScript.next到来的时候,我们现在每天都在写的JavaScript代码将会发生巨大的变化.接下来的一年将会是令JavaScript开发者们兴奋的一年,越来越多的特性提案将被最 ...
- jQuery无缝循环开源多元素动画轮播jquery.slides插件
详细内容请点击 初始化插件: 一款基于jQuery无缝轮播图插件,支持图内元素动画,可以自定义动画类型$(".slideInner").slide({slideContainer: ...
- External Table
CREATE TABLE AS SELECT,使用Oracle9i的External Table Oracle 9i 的一项新特性就是 External Table,它就象通常的数据库表一样,拥有字 ...
- PHP和CS的引用传值
PHP的引用传值 function change_value($num){ $num+=2; } $age = 3; change_value(&$age); echo $age; CS的引用 ...
- PowerDesigner的数据类型
用PowerDesigner 15 设计个数据库,每个字段的数据类型设计真是头大,根据字段意思看用哪个类型最合适还得仔细研究呀.贴几个数据类型表格收藏一下^_^ Numeric data types ...
- iOS UIView常用方法和属性
UIView常用方法 addSubView: // 添加子视图 insertSubview: atIndex // 视图插入到指定索引位置 insertSubview:aboveSubview: // ...
- SQL中char、varchar、nvarchar
char char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值.当你输入的字符大于指定的数时,它会截取超出的字符. nvarcha ...
- 关于windows的svchost进程的问题(年代有点久远)
这是N年前写的一篇关于svchost的blog,虽然写的不好却是我第一次写的技术类blog, 发上来做开博第一篇吧. ***************************************** ...