《深入理解Java虚拟机》一书总结(一)

1、概念

  • 1.1、首先说何为Java虚拟机?

Java虚拟机从字面意思直接理解就是运行Java的虚拟机器,既然是虚拟的,那么就是从物理层面来说是不存在于实际的一个机器,它不像电脑这种机器,是实际存在的,而是人们想象的一个机器,因为它能像机器一样做机器可以做的事情。

  • 1.2、为什么要使用Java虚拟机

我们都知道Java语言是一种高级语言,我们可以从Java语言的特性中进行分析,Java特性包括面向对象、平台独立性、可移植性、支持多线程等。从列出的特性中我们可以从可移植性进行分析。
可移植性可以理解为Java代码可以在在一台机器上运行,也可以将代码复制到其它机器上运行,最终代码执行结果相同。而保证这个可移植性就要保证Java语言在不同机器上的各个类型是相同的,比如在32位机器上御64位机器上不会对Java代码造成影响。
C语言在32位和64位机器上类型长度是不同的,例如long类型在32位机器中长度为4,在64位机器中长度为8;但是Java语言不会存在这种问题。在32位和64位机器中,类型长度都是相同的。
而为了保证Java语言中类型的不变性,就将Java语言运行在Java虚拟机中,通过Java虚拟机编译Java代码,识别Java语言中的各个类型,最终再转换为机器可以识别的语言。所以Java虚拟机的作用主要是编辑Java代码,将编译好的Java代码转换为机器可识别的语言等。
所以本质上Java虚拟机就是一套编写好的代码,这个代码处于运行状态时可以编译Java代码,实现像机器一样的功能。

  • 1.3、Java虚拟机类型

我们现在最熟悉的Java虚拟机应该是HotSpot VM,这是JDK1.3之后默认的虚拟机。现在通过查看Java虚拟机模型也可以看到该默认的虚拟机。
通过查看Java VisualVM可以看到默认的JVM就是HotSpot VM。
《深入理解Java虚拟机》一书总结(一)_第1张图片

2、内存区域

一下会通过JVM来代替Java虚拟机。
说完了概念再来说一下JVM的内存区域,既然JVM也是一套代码,那么这套代码也有自己的架构,通过架构我们才可以分析JVM的各个点是做什么的!
内存区域图如下:
《深入理解Java虚拟机》一书总结(一)_第2张图片

  • 2.1、堆

堆是JVM的内存区域中占据容量最大的一块区域,它是线程共享的一块区域,主要存放的数据为对象。并且平时我们创建的对象都是首先在堆上进行分配空间的,一个对象占用多少内存都是在首先在堆中来进行分配的。
并且堆也是垃圾回收的主要区域,当分配的对象生命周期结束,那么就需要通过垃圾回收器来将这个对象进行回收,避免一直占用堆中的内存。
若对象一直不回收,堆的可用容量达到的阈值,那么就会抛出OutOfMemoryError异常。告诉开发者堆中的内存已经使用完,没有多余的内存可以给对象分配了,同时也无法再扩展了。

  • 2.2、方法区

方法区也是一块内存共享的区域,该区域中主要存放的数据为被虚拟机加载的类信息、常量、静态变量。平时我们创建的类、或者类中设定的常量或者静态变量,这些数据都是存放在方法区中的。
并且方法区也是需要垃圾回收器回收的第二块区域,垃圾回收器也会回收掉不用的常量或者静态变量这些数据。
同时方法区也会有设定的阈值,当方法区内存已满,并且不可再扩展时,也会抛出OutOfMemoryError的异常。

  • 2.2.1、运行时常量池

运行时常量池是方法区的一部分,该区域主要用于存放编译器生成的各种字面量以及符号的引用。编译器和运行期时都可以将常量放入常量池中,并且常量池的内存是有限的,所以使用完并且无法扩展时将会抛出OutOfMemoryError的异常。

  • 2.3、虚拟机栈

虚拟机栈是一块线程私有的内存区域,在该区域中主要存放的数据为局部变量表(方法参数以及方法内部定义的局部变量)、操作栈、方法返回地址等。
每个执行的方法都会对应一个栈帧,这个帧栈中就存放着执行方法的所有数据,例如参数、方法中的局部变量、返回地址等信息,也就是一个执行的方法都会在虚拟机栈中生成一个帧栈。
该区域对应的是正在执行的方法,因此当线程请求的栈深度大于虚拟机所允许的深度,那么就会抛出StackOverflowError的异常。
同时虚拟机栈也是有一定的阈值的,无法动态扩展,那么当内存已经满时,并且无法扩展时就会抛出OutOfMemoryError的异常。

  • 2.4、本地方法栈

本地方法栈也是一块线程私有的内存区域,该区域中主要存放的数据为虚拟机用到的native方法服务,例如我们所使用的UnSafe类,这个类中有compareAndSwap方法,这个方法就是native方法,这些native方法服务就是存放在本地方法栈中。
该区域中也会像虚拟机栈一样抛出StackOverflowError和OutOfMemoryError异常。

  • 2.5、程序计数器

程序计数器也是线程私有的,并且从字面意思可以理解到该区域主要功能为计数,它也的确是一个起到一个计数的功能,程序计数器主要记录的是线程执行的字节码的行号,也就是可以记录代码执行到哪一行。
该区域中不会抛出异常信息。

你可能感兴趣的:(《Java后端知识体系》系列)