java虚拟机存储区

方法区和堆区是数据共享区。

栈区:数据不共享。方法参数、局部变量、参与运算的中间结果、返回值等等都在栈区中。

堆区:数据共享。存放对象。

方法区存放类型信息,类型信息包括:字段信息、方法信息、该类型的常量池、类变量、一个到类ClassLoader的引用,一个到Class类的引用。这部分数据是共享的,是一个Java虚拟机实例或者说一个Java程序共享的。

当一个类被多个不同的ClassLoader加载的时候,需要对ClassLoader标识。同时也要标识一个Class类,他的完全限定名。

public class Test {

    int a;
    int b;
    public static void main(String[] args) {
        int c = 20;
        Test test = new Test();
        test.change(test,c);
        System.out.println(test.a+" first "+c);
    }

    public void change(Test t,int c){
        c=50;
        t.a=10;
        t = new Test();
        t.a=20;
        System.out.println(t.a+" second");
    }
}

结果是:

20 second
10 first 20

main方法和change方法会在java栈中开辟两个栈帧,一个方法对应一个栈帧,当前栈帧代表调用当前的方法,每个栈帧会有他的数据结构,他的数据结构就是在前面提到的栈区存放的东西。

main方法接受一个args参数和定义两个局部变量。

int c = 20;那么会在这个栈帧定义一个值为20,名为c的变量。暂时可以这么理解,更细的话就要看他执行的时机了。

Test test  = new Test();

这样一new做的事情可以多了。先看右边,他在堆区开辟一个存储空间,这个存储空间有地址值,并且这块空间持有一个类型信息在方法区的引用。那么方法区的那块空间就描述着该类的类型信息了,包括字段、方法、类变量等等,上面有。

左边是一个Test类型的引用,他持有的是堆区那块地址值。

当main方法调用change时,是把上面传过去呢?其实是把值传过去了,把对象的地址值和20传过去了。

change方法接受这两个参数,他就会为这两个参数在栈区中开辟两块存储空间,用来存储这两个参数,在这里没有定义方法的局部变量。

这时t=传进来的地址值,c=20;

现在变化来了,改变他们的值。c=50;他这里改变改变的是谁的值呢。其实是改变了属于change方法这个栈帧的变量值。而没有改变到main方法栈帧的变量值。所以在打印的时候c还是20,不要因为变量名而迷惑了。

下一步:t.a=10;这时候这个a是属于传进来对象的,也就是第一个对象。他的a被改变了,等于10。

再下一步:t = new Test();这时候堆区就有两个对象了,这个t的值不再是以前对象的地址值了,而是新的对象的地址值了,那这个新的对象也有自己的成员字段和方法,等等。

最后t.a=20;改变的是新对象的a变量,而不是以前的。

所以结果就这样了。

Java中方法参数的传递都是传值,引用数据类型传的是地址值,字符串传的是"内容",基本数据类型就是普通的值。

时间: 2024-12-23 06:24:09

java虚拟机存储区的相关文章

面试 -- Java内存布局【图】以及java各种存储区【详解】

一.Java内存布局浅谈 1. 总述 我们知道,线程是操作系统调度的基本单元.所有线程共享父进程的堆空间,而每个线程都有自己的栈空间和程序计数器.所以,Java虚拟机也看以看作是一个独立的进程,里面的内存空间分为线程共享空间和线程独有空间.Java虚拟机内存布局如下: 2. 所有线程共享的内存空间 (1)堆空间:JVM规范中规定,所有对象实例以及数组都要在堆上进行分配.一般来说,堆空间都有一个默认大小,取决于JVM实现,而且可以根据需要动态扩展.当创建对象需要在堆上分配空间,而且堆本身的空间不够

java虚拟机内存区常用名词解释

虚拟机内存区常见名词: 栈帧(Frames): 栈帧是用来存储数据和部分结果,以及执行动态链接.方法返回值和异常信息的. 每次方法的调用都会生成一个栈帧,然后将该栈帧进行压栈.当方法结束后,该栈帧将会出栈.被销毁. 无论是正常结束还是异常结束. 每个栈帧都是自己的局部变量表.操作数栈.以及对当前方法类的运行时常量池的引用. 由当前线程创建的帧不能被其它线程引用. 局部变量(Local Variables): 每个栈帧包含一个叫局部变量的变量数组,它的长度在编译的时候确定. 单个局部变量可以保存类

深入Java虚拟机(程序运行)

引子:打开黑匣子 心中有数 老实说,对于C++的整个编译运行过程,我并没有全面的了解,好几次被问住了,看来是汇编没有学好,但是在看完<深入Java虚拟机>之后,对于Java代码到运行的每一个细节,有了更全面的认识. 描述一下整体的流程:程序员根据Java API编写Java程序,各种类文件,用一个Java编译器编译Java程序为class文件,class文件通过一定的分发方式被Java虚拟机装载.连接.初始化,变成Java虚拟机方法区的Class类,然后被实例化为堆区的对象,随着虚拟机的执行,

Java虚拟机 运行时数据区

Java在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途.创建和销毁的时间,有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,有些则是与线程一一对应,随线程的开始和结束而创建和销毁. Java虚拟机所管理的内存将会包括以下几个运行时数据区域 程序计数器(Program Counter Register) 它是一块较小的内存空间,它的作用可以看做是当先线程所执行的字节码的信号指示器. 每一条JVM线程都有自己的PC寄存器,各条线程之间互不影响,独立存

Java 虚拟机运行时数据区介绍

引言 Java 虚拟机(Virtual Machine)在执行 Java 程序时, 会将它所管理的内存划分为不同的数据区,这些分块有不同的功能,理解它们各自的特点,对于深入理解java程序运行机制和调优Java代码,具有重要意义.其实个人觉得,理解 Java 虚拟机的原理,也没想象中的复杂(也许我的想法有点天真啊^_^),它的运行机制,就像一个小型操作系统,这也许就是虚拟机的来源吧. Java VM运行时数据区结构图 运行时数据区域解释 本地方法栈 该区域所发挥的作用与虚拟机栈类似,只不过它是为

《深入理解Java虚拟机》笔记01 -- 运行时数据区

运行时数据区示意图 1. 程序计数器 占用一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器.主要用来记录线程执行到哪条语句了,分支.循环.跳转.异常处理.线程恢复等功能都需要依赖这个计数器来完成. 如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址:如果正在执行的时Native方法,这个计数器值则为空.此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域. 2. Java 虚拟机栈 线程私有,生命

【Java虚拟机结构(第2部分)运行时数据区】摘要

<Java虚拟机规范(Java SE 7版)>作者:Tim Lindholm.Frank Yellin.Gilad Bracha.Alex Buckley 摘要:第二章 Java虚拟机结构(第2部分) 本规范描述的是一种抽象化的虚拟机的行为,而不是任何一种被广泛使用的虚拟机实现. 2.5 运行时数据区 Java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁.另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而

java虚拟机:方法区

一.方法区简介 方法区,Method Area, 对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为"永久代"(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已.对于其他虚拟机(如BEA JRockit.IBM J9等)来说是不存在永久代的概念的. 主要存放已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据(比如spr

Java虚拟机运行时数据区结构

本文部分参考自<Java虚拟机规范(Java SE 7版)>的中译本和周志明的<深入理解Java虚拟机>,另加个人理解.原书对Java虚拟机运行时数据区描述只有6页,同时参考其他网络网资料,个人能力所限,不排除存在认知错误. JVM将程序运行期间使用的内存划分为若干个运行时数据区,其中一些会随着虚拟机启动而创建,随着虚拟机退出而销毁.另外一些与线程一一对应,随着线程开始而创建,随着线程结束而销毁.数据区划分如下图所示意: Java堆(Java Heap) 在JVM中,Java堆是可