Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

readme.md

[TOC]

JVM

参考来自尚硅谷,侵权请联系

整体结构

image-20220505171516152

执行流程

image-20220505171717177

生命周期

启动

image-20220505181014122

执行

image-20220505181045554

退出

image-20220505181812782

JIT

即时编译器:会找到程序中的热点代码(执行次数比较多的),加到缓存中,下次直接从缓存中取。

命令解释

jps:打印当前程序中执行的进程

javap -v 类名.class:反编译某个类

iconst_2: 定义常量2
istore_1: 保存在操作数栈栈中,1是一个索引位置
iload_1: 加载保存的数,索引1的位置
iadd: 求和操作



chapter01

  1. 反编译命令:javap -v 类名.class

    image-20220505175236879

  2. 栈和寄存器的指令集架构

    image-20220505180455205

StackStruTest

image-20220505180253705

类加载子系统

Class Loader Subsystem

简略:

image-20220506162346841

详细:

image-20220506162514499

内容

类加载子系统作用

image-20220506163312713

类加载器角色

image-20220506163517766

类的加载过程

image-20220506163545969

  1. 加载

    image-20220506163901174

  2. 链接

    image-20220506164149516

类加载器分类

image-20220507161508300

  1. 虚拟机自带的加载器

    image-20220507164136206

    image-20220507164039917

    image-20220507164302919

  2. 用户自定义类加载器

    image-20220507165112064

    自定义类加载器的实现步骤:

    image-20220507165554223

    public class CustomClassLoader extends ClassLoader {
        
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
    
            try {
                byte[] result = getClassFromCustomPath(name);
                if(result == null){
                    throw new FileNotFoundException();
                }else{
                    return defineClass(name,result,0,result.length);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
    
            throw new ClassNotFoundException(name);
        }
    
        private byte[] getClassFromCustomPath(String name){
            //从自定义路径中加载指定类:细节略
            //如果指定路径的字节码文件进行了加密,则需要在此方法中进行解密操作。
            return null;
        }
    
        public static void main(String[] args) {
            CustomClassLoader customClassLoader = new CustomClassLoader();
            try {
                Class<?> clazz = Class.forName("One",true,customClassLoader);
                Object obj = clazz.newInstance();
                System.out.println(obj.getClass().getClassLoader());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

关于classLoader

image-20220507170206810

image-20220507170417836

获取classloader的途径

image-20220507170705923

双亲委派机制

image-20220507171229161

工作原理

image-20220507171633144

优先找上层去处理,上层能够处理就处理,不能处理就交由子类去处理。

优缺点

优点

image-20220507172322817

沙箱安全机制

image-20220507172626289

其他

image-20220507173049161

对类加载器的引用

image-20220507173124527

运行时数据区

image-20220508161102741

image-20220508161229833

经典的布局:

image-20220508161635858

具体一点;

image-20220508161722838

image-20220508161902193

  1. 95%是对堆区进行优化的;5%是优化方法区。

  2. 其余的虚拟机栈和本地方法栈没有什么要优化的。

  3. 一个RunTime类对应一个虚拟机,也相当于一个运行时数据区

线程

image-20220508162821759

如果run方法不是正常结束的话,java线程会结束运行,但是本地线程要看情况:

  1. 本地线程需要决定jvm是不是要终止
  2. jvm要不要终止,取决于当前线程是不是最后一个非守护线程。如果当前程序中只剩下都是守护线程的话,那么jvm就可以退出;如果是非守护线程,jvm就要被停掉
    1. 线程分为:守护线程、普通线程
    2. User Thread(普通线程):不随主线程的结束而结束,直到自己运行完
    3. Daemon Thread(守护线程) :当前JVM存在普通线程时,守护线程就还可以工作(除非自己结束)

JVM系统线程

image-20220508163842201

程序计数器(PC寄存器)

PC Register介绍

最详细的是官网, 8和之后的版本内存方面变化不大,主要是在垃圾回收方面区别。

image-20220508164329843

image-20220508164637212

image-20220508165110654

image-20220508165215170

  1. PC和栈没有垃圾回收区域
  2. PC没有溢出;但是栈有可能会溢出OOM超出内存(栈满)
  3. 方法区和堆区有可能溢出,也有垃圾回收GC

举例说明

image-20220508165632117

image-20220508170325487

两个常见问题

  1. image-20220508170548645

  2. 意思是问:PC寄存器为什么每个线程都有一份?

    image-20220508170700643

    简单来说:如果PC共享

    当前线程执行到第5行时,CPU切换执行线程2,那么PC就会被改变到第7行,那再切换回来执行线程1的时候就会出错,应该从第5行开始执行,但现在被线程2执行后改变了不是5.

image-20220508171659517

并发:同一时间段内

并行:同时执行(多核CPU的时候)

虚拟机栈

官网

概述

image-20220510163936397

image-20220510164315195

基本内容

image-20220510165957289

image-20220510170120962

但是会有OOM内存溢出的异常

image-20220510170540063

image-20220510172558031

栈的存储单位

image-20220510172933628

运行原理

image-20220510173037970

image-20220510173836023

image-20220510173912646

抛出异常指的是:

没有处理的异常,即没有try、catch的的;如果try了还是属于正常的返回return。

栈帧的内部结构

image-20220510180717780

image-20220510181317931

局部变量表

image-20220513163845307

image-20220513165411335

image-20220513173159875

image-20220513173232947

静态方法中,不允许有this。this变量不存在当前方法的局部变量表中

image-20220513174355408

image-20220513174658369

image-20220513175147055

操作数栈

image-20220514151618834

image-20220514152213513

image-20220514152542702

代码追踪

对上面操作数栈的演示

image-20220514152800233

image-20220514153019431

image-20220514153043008

image-20220514153131988

iload_1:从局部变量表索引为1的位置取出数据放入到操作数栈中

(i表示int ; bi表示byte)

字节码指令由执行引擎翻译解释为机器指令

image-20220514155221143

栈顶缓存技术

image-20220514160622626

动态链接image-20220514160811013

方法区与栈的关联结构:(右一是堆区,右二是方法区)

image-20220514161728178

image-20220514162035846

方法的调用:解析与分派

image-20220514162448717

image-20220514163158399

早期和晚期对应于静态和动态链接

image-20220514163415328

虚方法与非虚方法:

image-20220514163531302

子类对象的多态性的使用前提:

  1. 类的继承关系
  2. 方法的重写(主要是这个,不然没有重写,那么其实相当于就是父类)

image-20220514164015441

方法返回地址

一些附加信息

栈的相关面试题

工具

  1. Binary viewer:查看二进制文件的

  2. Bytecode viewer:查看字节码文件的(是个jar包,双击直接打开)

    是一款基于图形界面的 Java 反编译器,Java 字节码编辑器,APK 编辑器,APK 反编译器,Dex 编辑器,DEX 反编译器,其集成了 6 个 Java 反编译库(包含 Procyon、CFR 和 Fernflower),Andorid 反编译类库和字节码类库。不仅如此,它还是一款 Hex 查看器,代码搜索器和代码调试器。除此之外,它还具备 Smali 和 Baksmali 等汇编器的相关功能。 它完全用 Java 编写,并且是开源的。 它目前由 Konloch 维护和开发。 还有一个插件系统可以让您与加载的类文件进行交互,例如您可以编写一个字符串反混淆器、恶意代码搜索器或其他您能想到的东西。 您可以使用预先编写的插件之一,也可以编写自己的插件。 它支持 Groovy、Python 和 Ruby 脚本。 一旦插件被激活,它会将文件系统中加载的每个类的 ClassNode ArrayList 发送到执行函数,这允许用户使用 ASM 完全处理它。

  3. Jclasslib bytecode viewer:字节码分析工具(idea也有类似的插件;在菜单栏中的view

    image-20220506180608114