一 、JVM(数据类型、堆、栈)

目录

 

数据类型

基本类型

引用数据类型

Java中的参数传递时传值呢?还是传引用?

但是传引用的错觉是如何造成的呢?

操作系统的堆和栈

为什么jvm的内存是分布在操作系统的堆中呢?

java虚拟机的生命周期

java虚拟机与main方法的关系

GC

 jvm

 jvm内存结构与操作系统内存布局进行类比说明

运行时数据区图


数据类型

基本类型

基本类型的变量保存原始值,即:他代表的值就是数值本身

包括:

byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。

short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。

int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。

long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。

float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。

double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。

boolean:只有true和false两个取值。

char:16位,存储Unicode码,用单引号赋值。

returnAddress 数据只存在于字节码层面,与编程语言无关,也就是说,我们在 Java 语言中是不会直接与 returnAddress 类型的数据打交道的。

引用数据类型

引用类型的变量保存引用值。

“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址的位置

包括:

类类型,接口类型和数组。

Java中的参数传递时传值呢?还是传引用

      Java中没有指针的概念, 程序运行永远都是在栈中进行的,因而参数传递时,只存在传递基本类型和对象引用的问题。不会直接传对象本身。Java在方法调用传递参数时,因为没有指针,所以它都是进行传值调用

但是传引用的错觉是如何造成的呢?

      在运行栈中,基本类型和引用的处理是一样的,都是传值。所以,如果是传引用的方法调用,也同时可以理解为“传引用值”的传值调用,即引用的处理跟基本类型是完全一样的。但是当进入被调用方法时,被传递的这个引用的值,被程序解释(或查找)到堆中的对象,这个时候才对应到真正的对象。如果此时进行修改,修改的是引用对应的对象,而不是引用本身,即:修改的是堆中的数据。所有这个修改是可以保持的。

      对象,从某种意义上说,是由基本类型组成的。可以把一个对象看作为一棵树,对象的属性如果也是对象,则也是一颗树(即非叶子节点),基本类型则作为树的叶子节点。程序参数传递时,被传递的值本身都是不能进行修改的,但是,如果这个值是一个非叶子节点(即一个对象引用),则可以修改这个节点下面的所有内容。

堆和栈中,栈是程序运行最根本的东西。程序运行可以没有堆,但是不能没有栈。而堆是为栈进行数据存储服务,说白了堆就是一块共享的内存。不过,正是因为堆和栈的分离的思想,才使得Java的垃圾回收成为可能。

     Java中,栈的大小通过-Xss来设置,当栈中存储数据比较多时,需要适当调大这个值,否则会出现java.lang.StackOverflowError异常。常见的出现这个异常的是无法返回的递归,因为此时栈中保存的信息都是方法返回的记录点。

操作系统的堆和栈

一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表。

由操作系统自动分配释放,存放函数的参数值,局部变量值等。操作方式与数据结构中的栈相类似。

为什么jvm的内存是分布在操作系统的堆中呢?

因为操作系统的栈是操作系统管理的,它随时会被回收,所以如果jvm放在栈中,那java的一个null对象就很难确定会被谁回收了,那gc的存在就一点意义都莫有了,而要对栈做到自动释放也是jvm需要考虑的,所以放在堆中就最合适不过了。

java虚拟机的生命周期

声明周期起点是当一个java应用main函数启动时虚拟机也同时被启动,而只有当在虚拟机实例中的所有非守护进程都结束时,java虚拟机实例才结束生命。

java虚拟机与main方法的关系

main函数就是一个java应用的入口,main函数被执行时,java虚拟机就启动了。启动了几个main函数就启动了几个java应用,同时也启动了几个java的虚拟机。

GC

虚拟机的gc(垃圾回收机制)就是一个典型的守护线程。

GC垃圾回收机制不是创建的变量为空是就被立刻回收,而是超出变量的作用域后就被自动回收。

 jvm

 jvm内存结构与操作系统内存布局进行类比说明

上图表明:

  • jvm内存是存在于计算机内存中,并根据自身需求将内存划分为:pc寄存器、虚拟机栈、本地方法栈、jvm堆以及方法区,这些区域共同组成了运行时数据区,其中gc主要发生在堆区,栈由jvm自行管理
  • pc寄存器:其主要职责是指示线程要执行的下一条指令的地址,具体执行过程参考下文:Class文件的执行过程
  • 栈:主要是有栈帧组成,每个栈帧代表一个方法,且位于栈顶的栈帧是当前正在执行的方法。
  • 堆:java中一切皆对象,所有对象都是在堆中生成,有gc垃圾回收器进行回收
  • 方法区:类似计算机的硬盘,主要存放class文件,其中class文件基本组织结构可以参考Class文件的内存信息
     

运行时数据区图

 

上图表明:

方法区和堆是线程共享的,虚拟机栈、本地方法栈和程序计数器都是线程私有的,这里的程序计数器是线程私有的是因为线程可以被切换暂停的,当恢复运行时由程序计数器执行接着执行的指令地址。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章