Java参数传递原理和JVM详解

很多人再刚接触Java参数传递的时候,会一脸的问号????,到底参数是怎么传递的呢?我们首先要知道Java虚拟机中运行时数据区的分布情况:
在这里插入图片描述

虚拟机中各区域的作用

程序计数器:

    程序计数器的主要作用就是控制程序的运行。每一个线程都需要一个独立的程序计数器,虚拟机通过程序计数器来判断那个线程执行。这个区域占用内存极小,是 “线程私有”的内存区域.

虚拟机栈:

    虚拟机栈也是 “线程私有”,生命周期和线程相同。每个方法再执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接等信息。局部变量表存放编译期可知的各种基本类型(存值)和对象引用类型(存引用)。总而言之, 虚拟机栈就是存储栈帧信息。(若栈帧中变量是基本类型存的是值,引用类型存的是引用)我们通常讲的栈指的就是虚拟机栈。

本地方法栈:

    本地方法栈的作用和虚拟机栈差不多,都是存放栈帧。那为什么要在内存中开辟一个本地方法栈区域呢?这是因为虚拟机栈只服务于虚拟机执行Java方法,而操作系统只支持C语言和汇编语言,要想让操作系统将Java程序跑起来,就得靠C语言和汇编语言来实现。也就是说当你虚拟机栈执行中压栈的同时,将相应的C语言和汇编语言方法压入本地方法栈。有的虚拟机甚至将本地方法栈和虚拟机栈合二为一。

方法区:

    方法区是用于存储已被虚拟机加载的类信息、常量、静态变量等(总之,一般属于类的信息都存放在方法区),在JDK1.7之前的版本,常量池就是存放在方法区中,在之后的版本,常量池就被移出方法区了,属于一个单独的内存空间。

堆:

    Java堆是Java虚拟机管理的最大一块内存空间了, 主要存储所有的对象实例和数组。Java堆是所有线程所共享的一块内存区域(这里的共享是相对栈来说的,栈是每个线程都独有,也就是说每个线程都会产生一个自己的栈,而堆是将所有对象都放到了一个堆里,只不过线程访问时是有限制的)

参数传递

现在我们已经了解了虚拟机各个区域的作用,那么我们来看看Java参数传递过程具体是怎么是实现的:
  • 基本类型

    基本类型的数据都存放在栈中:

    在这里插入图片描述
    所以基本类型的复制都是深度复制,对一个基本类型的改变不会对另外一个基本类型产生任何影响。

  • 引用类型

引用类型所声明的变量(该变量实际上是在方法中存储的是内存地址值)是放在方法的栈中,该变量所指向的对象是放在堆类存中的。引用类型有两种方式访问对象:
    1.通过句柄访问对象:(这种方式的优点是变量中存储的是稳定的句柄地址:当对象数据改变时,不需要改变变量所指的地址,即1的指针,只需要改变句柄中的实例数据指针,即2的指针。那为什么不用改变句柄中类型数据的指针呢?那是因为垃圾收集时,只会移动堆中的数据,并不会对方法区进行回收)。
在这里插入图片描述
    2.通过直接指针访问对象:(这种方式的优点是速度快:因为它节省了一次指针定位开销的时间,当这类开销积少成多也是一项非常可观的执行成本)。
在这里插入图片描述

相关推荐
©️2020 CSDN 皮肤主题: 岁月 设计师:pinMode 返回首页