Java虚拟机 平行系列二

2.3 Java虚拟机栈,压栈帧 执行方法的操作过程

3、垃圾回收机制和垃圾回收算法

3.1、垃圾回收机制

3.2、垃圾回收算法

3.2.1、标记-清除

3.2.2、标记-复制

3.2.3、标记-整理


基于咕泡学院Jack老师视频

相关视频:https://ke.qq.com/course/466802?taid=3966307809042290

主要内容:

1、什么是运行时数据区;

2、运行时数据区为什么要这么划分;

3、方法的执行和Java虚拟机栈详解;

4、垃圾回收机制和垃圾回收算法;

1、准备工作

======

Person.java文件

class Person {

private String name = “Jack”;

private int age;

private final double salary = 100;

private static String address;

private final static String hobby = “Programming”;

// private Object obj = new Object();

public void say() {

System.out.println(“Person say…”);

}

public static int calc(int op1, int op2) {

op1 = 3;

int result = op1 + op2;

// Object o = obj;

return result;

}

public static void main(String[] args) {

System.out.println(calc(1,2));

}

}

通过javac命令生成class文件

文件位置:

2、运行时数据区

========

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5

Java8 运行时数据区官方文档。

2.1、什么是运行时数据区


2.2、运行时数据区可以划分为几个区域?为什么要这么划分?


class文件中到底有多少数据类型?

对象,常量,静态变量,普通的成员变量,方法,局部变量,父类 …

Java官方文档可以看到以下目录:

2.5. Run-Time Data Areas

  • 2.5.1. The pc Register

  • 2.5.2. Java Virtual Machine Stacks

  • 2.5.3. Heap:   对象【普通的成员变量】,数组 --》堆   new Person();   new Student();    Class clazz;

  • 2.5.4. Method Area:类的信息【创建的时间,元数据信息】、常量、静态变量、即时编译器编译之后的代码

  • 2.5.5. Run-Time Constant Pool

  • 2.5.6. Native Method Stacks

Heap:堆

其实就是存储Java对象的。

The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated.

Java虚拟机具有一个在所有Java虚拟机线程之间共享的_堆_。堆是运行时数据区,从中分配了所有类实例和数组的内存。

private int age; ----> 普通变量【普通的成员变量】存储在哪里?

如果我要调用普通变量,是不是要先创建对象.age  —> 随着对象存储在堆内存。

Java虚拟机具有一个在所有Java虚拟机线程之间共享的_堆_。堆是运行时数据区,从中分配了所有类实例和数组的内存。

堆是在虚拟机启动时创建的。对象的堆存储由自动存储管理系统(称为_垃圾收集器_)回收;对象永远不会显式释放。Java虚拟机不假定特定类型的自动存储管理系统,可以根据实现者的系统要求选择存储管理技术。堆的大小可以是固定的,也可以根据计算的需要进行扩展,如果不需要更大的堆,则可以将其收缩。堆的内存不必是连续的。

Java虚拟机实现可以为程序员或用户提供对堆的初始大小的控制,并且,如果可以动态扩展或收缩堆,则可以控制最大和最小堆大小。

以下异常情况与堆相关联:

  •         如果计算需要的堆多于自动存储管理系统可以提供的堆,则Java虚拟机将抛出一个 OutOfMemoryError

Method Area:方法区

The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the “text” segment in an operating system process. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization.

Java虚拟机具有在所有Java虚拟机线程之间共享的_方法区域_。该方法区域类似于常规语言的编译代码的存储区域,或者类似于操作系统过程中的“文本”段。它存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码,包括用于类和实例初始化以及接口初始化的特殊方法(第2.9节)。

Java虚拟机具有在所有Java虚拟机线程之间共享的_方法区域_。该方法区域类似于常规语言的编译代码的存储区域,或者类似于操作系统过程中的“文本”段。它存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码,包括用于类和实例初始化以及接口初始化的特殊方法(第2.9节)。

方法区域是在虚拟机启动时创建的。尽管方法区域在逻辑上是堆的一部分,但是简单的实现可以选择不进行垃圾回收或压缩。该规范没有规定方法区域的位置或用于管理已编译代码的策略。方法区域可以是固定大小的,或者可以根据计算的需要进行扩展,如果不需要更大的方法区域,则可以缩小。方法区域的内存不必是连续的。

Java虚拟机实现可以为程序员或用户提供对方法区域初始大小的控制,以及在方法区域大小可变的情况下,可以控制最大和最小方法区域大小。

以下异常条件与方法区域相关联:

  •        如果无法提供方法区域中的内存来满足分配请求,则Java虚拟机将抛出一个OutOfMemoryError

Heap和Method Area总结:

1、is shared among all java Virtual Machine threads. —>所有线程所共享的区域–>这两块数据中的数据是线程非安全的,因为可能会被多个线程用到同一个数据。

2、The heap is created on virtual machine start-up.  The method area is created on virtual machine start-up.  —> Heap和Method Area的创建是跟虚拟机进程相关的。

3、If a computation requires more heap than can be made available by the automatic storage management system, the Java Virtual Machine throws an OutOfMemoryError. If memory in the method area cannot be made available to satisfy an allocation request, the Java Virtual Machine throws an OutOfMemoryError.  —>  Heap和Method Area的大小可以通过JVM参数来控制,当他们的内存大小不够用的时候,就会抛出 OutOfMemoryError.

Java程序启动的话,会有一个Java进程,Java程序的灵魂应该就是线程的执行。(另一个是面向对象)。

Java Virtual Machine Stacks:Java虚拟机堆栈

方法的执行一定是由线程来执行的。

T1 T2 T3 T4 线程执行方法的过程应该可以用一个数据结构表示:栈 -->  先进后出。

Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.

每个Java虚拟机线程都有一个私有_Java虚拟机堆栈_,与该线程同时创建。

每个Java虚拟机线程都有一个私有_Java虚拟机堆栈_,与该线程同时创建。Java虚拟机堆栈存储框架(第2.6节)。Java虚拟机堆栈类似于C之类的常规语言的堆栈:它保存局部变量和部分结果,并在方法调用和返回中起作用。因为除了推送和弹出帧外,从不直接操纵Java虚拟机堆栈,所以可以为堆分配帧。Java虚拟机堆栈的内存不必是连续的。

在第一版_中的Java ®虚拟机规范,Java虚拟机堆被称为_Java堆栈_。_

该规范允许Java虚拟机堆栈具有固定大小,或者根据计算要求动态扩展和收缩。如果Java虚拟机堆栈的大小固定,则在创建每个Java虚拟机堆栈时可以独立选择它们的大小。

Java虚拟机实现可以为程序员或用户提供对Java虚拟机堆栈的初始大小的控制,并且在动态扩展或收缩Java虚拟机堆栈的情况下,可以控制最大和最小大小。

以下异常条件与Java虚拟机堆栈相关:

  •          如果线程中的计算需要比允许的Java虚拟机更大的堆栈,则Java虚拟机将抛出StackOverflowError
  •          如果可以动态扩展Java虚拟机堆栈,并尝试进行扩展,但是可以提供足够的内存来实现扩展,或者如果没有足够的内存来为新线程创建初始Java虚拟机堆栈,则Java虚拟机机器抛出一个OutOfMemoryError

Native Method Stacks:本地方法堆栈

other than the Java programming language). Native method stacks may also be used by the implementation of an interpreter for the Java Virtual Machine’s instruction set in a language such as C. Java Virtual Machine implementations that cannot load native methods and that do not themselves rely on conventional stacks need not supply native method stacks. If supplied, native method stacks are typically allocated per thread when each thread is created.

This specification permits native method stacks either to be of a fixed size or to dynamically expand and contract as required by the computation. If the native method stacks are of a fixed size, the size of each native method stack may be chosen independently when that stack is created.

A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of the native method stacks, as well as, in the case of varying-size native method stacks, control over the maximum and minimum method stack sizes.

The following exceptional conditions are associated with native method stacks:

  • If the computation in a thread requires a larger native method stack than is permitted, the Java Virtual Machine throws a StackOverflowError.
  • If native method stacks can be dynamically expanded and native method stack expansion is attempted but insufficient memory can be made available, or if insufficient memory can be made available to create the initial native method stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

从修饰词Native就可以看出,这个栈是存储C语言方法的地方。

Java虚拟机的实现可以使用俗称“ C堆栈”的常规堆栈来支持native方法(以Java编程语言以外的其他语言编写的方法)。解释程序的实现也可以使用诸如C之类的语言来解释Java虚拟机的指令集,以使用native 本机方法栈。无法加载方法并且自身不依赖于常规堆栈的Java虚拟机实现不需要提供本机方法栈。如果提供,通常在创建每个线程时为每个线程分配本机方法堆栈。

该规范允许本机方法堆栈具有固定大小,或者根据计算要求动态扩展和收缩。如果本机方法堆栈的大小固定,则在创建每个本机方法堆栈的大小时可以独立选择。

Java虚拟机实现可以为程序员或用户提供对本机方法堆栈的初始大小的控制,以及在本机方法堆栈大小变化的情况下,对最大和最小方法堆栈大小的控制。

以下异常条件与本机方法堆栈相关联:

  • 如果线程中的计算需要比允许的更大的本机方法堆栈,则Java虚拟机将抛出StackOverflowError
  • 如果可以动态扩展本机方法堆栈并尝试进行本机方法堆栈扩展,但可以提供足够的内存,或者可以提供足够的内存来为新线程创建初始本机方法堆栈,则Java虚拟机将抛出OutOfMemoryError

The pc Register:程序计数器

The Java Virtual Machine can support many threads of execution at once (JLS §17). Each Java Virtual Machine thread has its own pc (program counter) register. At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method (§2.6) for that thread. If that method is not native, the pc register contains the address of the Java Virtual Machine instruction currently being executed. If the method currently being executed by the thread is native, the value of the Java Virtual Machine’s pc register is undefined. The Java Virtual Machine’s pc register is wide enough to hold a returnAddress or a native pointer on the specific platform.

Java虚拟机可以一次支持多个执行线程(JLS§17)。每个Java虚拟机线程都有其自己的 pc(程序计数器)寄存器。在任何时候,每个Java虚拟机线程都在执行单个方法的代码,即该线程的当前方法(第2.6节)。如果不是 native,则该pc寄存器包含当前正在执行的Java虚拟机指令的地址。如果线程当前正在执行的方法是native,则Java虚拟机的pc 寄存器值未定义。Java虚拟机的pc寄存器足够宽,可以returnAddress在特定平台上保存一个或本机指针。

Run-Time Constant Pool:运行时常量池

ranging from numeric literals known at compile-time to method and field references that must be resolved at run-time. The run-time constant pool serves a function similar to that of a symbol table for a conventional programming language, although it contains a wider range of data than a typical symbol table.

Each run-time constant pool is allocated from the Java Virtual Machine’s method area (§2.5.4). The run-time constant pool for a class or interface is constructed when the class or interface is created (§5.3) by the Java Virtual Machine.

The following exceptional condition is associated with the construction of the run-time constant pool for a class or interface:

  • When creating a class or interface, if the construction of the run-time constant pool requires more memory than can be made available in the method area of the Java Virtual Machine, the Java Virtual Machine throws an OutOfMemoryError.

See §5 (Loading, Linking, and Initializing) for information about the construction of the run-time constant pool.

_运行时常量池_是的每个类或每个接口的运行时表示constant_pool在表class文件(§4.4)。它包含多种常量,范围从编译时已知的数字文字到必须在运行时解析的方法和字段引用。运行时常量池的功能类似于常规编程语言的符号表,尽管它包含的数据范围比典型的符号表还大。

每个运行时常量池都是从Java虚拟机的方法区(Method Area 第2.5.4节)分配的。由Java虚拟机创建类或接口(第5.3节)时,将为类或接口构造运行时常量池。

以下异常条件与类或接口的运行时常量池的构造相关联:

  • 创建类或接口时,如果运行时常量池的构造所需的内存超过Java虚拟机的方法区域中可用的内存,则Java虚拟机将抛出OutOfMemoryError

有关 运行时常量池的构造信息请参见§5(加载,链接和初始化

之所以没有运行时常量池,是因为运行时常量池是由方法区分配的,可以理解为运行时常量池包含在方法区中。

方法区,包含了运行时常量池

Method Area

JDK1.7  之前 —>  Perm Space 永久代

JDK1.8  之后 —>  Meta Space 元空间

2.3 Java虚拟机栈,压栈帧 执行方法的操作过程


可以对class文件进行反编译,就能够看到字节码指令,就能够看到方法执行的过程

命令:javap -c Person.class

class com.ph.jvm.Person {

com.ph.jvm.Person();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object.“”😦)V

4: aload_0

5: ldc #2 // String Jack

7: putfield #3 // Field name:Ljava/lang/String;

10: aload_0

11: ldc2_w #4 // double 100.0d

14: putfield #6 // Field salary:D

17: return

public void say();

Code:

0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;

3: ldc #8 // String Person say…

5: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

8: return

public static int calc(int, int);

Code:

0: iconst_3

1: istore_0

2: iload_0

3: iload_1

4: iadd

5: istore_2

6: iload_2

7: ireturn

public static void main(java.lang.String[]);

Code:

0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;

3: iconst_1

4: iconst_2

5: invokestatic #10 // Method calc:(II)I

8: invokevirtual #11 // Method java/io/PrintStream.println:(I)V

11: return

}

下面对calc()方法进行分析:

public static int calc(int op1, int op2) {

op1 = 3;

int result = op1 + op2;

// Object o = obj;

return result;

}

public static int calc(int, int);

Code:

0: iconst_3 —> 3(int)值入栈。

1: istore_0 —> 将栈顶int类型值保存到局部变量0中。 # 3这个数值从操作数栈中弹出来,赋值给局部变量中的op1

2: iload_0 —> 从局部变量0中装载int类型值入栈。

3: iload_1 —> 从局部变量1中装载int类型值入栈。

4: iadd —> 将栈顶两long类型数相加,结果入栈。

5: istore_2 —> 将栈顶int类型值保存到局部变量2中。

6: iload_2 —> 从局部变量2中装载int类型值入栈。

7: ireturn —> void函数返回。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
—> void函数返回。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-jpUwdLKK-1714849862330)]

[外链图片转存中…(img-Ae6pv4wS-1714849862331)]

[外链图片转存中…(img-QrKnJ2ys-1714849862331)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值