几分钟应该看不完,私密马赛, 俺是标题党

既然来了, 看看吧, 球球你了

Java类加载器

类的生命周期和加载过程

  • 加载 加载所有的.class文件/jar文件/网络流 →字节流 (JVM 与java.lang.classLoader协作)

存储于Metaspace/Method Area

  • 校验 确保 class 文件里的字节流信息符合当前虚拟机的要求,不会危害虚拟机的安全
  • 准备 设置变量默认值 分配内存
  • 解析 解析常量池符号引用转换为直接引用,主要有以下四种:类或接口的解析、字段解析、类方法解析、接口方法解析 链接相关参数, 方法索引(为后续初始化和运行提供直接引用)
  • 初始化 执行类构造器 <clinit> 方法 初始化

类加载时机


类加载机制


JVM方法调用

方法于JVM构成 : 类名, 方法名, 方法描述符{参数类型, 返回参数类型}

JVM方法查询

子类的静态方法会隐藏(注意与重写区分)父类中的同名、同描述符的静态方法 Interface 同理

虚方法调用

  • 虚拟方法表 链接时建立class的虚方法(非static, final)表

分离invokinterfaceinvokevirtual原因

class A
1: method1
2: method2
class B extends A
1: method1
2: method2
3: method3
class B extends A implements X
1: method1
2: method2
3: method3
4: methodX
class C implements X
1: methodC
2: methodX

  • 内联缓存

         *-只是缓存并非内联(嵌入内部)*

执行过程中,如果碰到已缓存的类型,内联缓存便会直接调用该类型所对应的目标方法。


  • 劣化为超多态状态

JVM处理异常

异常基本概念

因为异常总是动态的, 实时的, 所以我们总是new exception()



如何捕获异常

每个method都会维护一张 Exception table

  Exception table:
from to target type
0 3 6 Class java/lang/Exception

Java 7 的 Suppressed 异常以及语法糖

try {
in0 = new FileInputStream(new File("in0.txt"));
...
try {
in1 = new FileInputStream(new File("in1.txt"));
...
try {
in2 = new FileInputStream(new File("in2.txt"));
...
} finally {
if (in2 != null) in2.close();
}
} finally {
if (in1 != null) in1.close();
}
} finally {
if (in0 != null) in0.close();
try (Foo foo0 = new Foo("Foo0");          // try-with-resources语法糖优化后
Foo foo1 = new Foo("Foo1"); // 该语法糖下自动使用suppressed异常
Foo foo2 = new Foo("Foo2")) {
throw new RuntimeException("Initial");
} **suppressed异常**允许将一个异常附于另一个异常之上。因此,抛出的异常可以附带多个异常的信息

JVM实现反射机制

依赖于 JVM 的类加载器和运行时数据结构(如方法表、字段表)

怎么用

应用

  • IDE 每当我们敲入点号时,IDE 便会根据点号前的内容,动态展示可以访问的字段或者方法
  • Java调试器 在调试过程中枚举某一对象所有字段的值
  • Spring framework IOC

Method.invoke

本地实现, 委派实现, 动态实现(均由MethodAccessor抽象)

getMethod会形成一份class内方法的的拷贝 -避免在热点代码中使用getMethod

取消委派实现, 关闭检查时目标方法的权限可以小幅度提升性能

public final class Method extends Executable {
...
public Object invoke(Object obj, Object... args) throws ... {
... // 权限检查
MethodAccessor ma = methodAccessor;
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
}
  • 本地实现
// v0 版本
import java.lang.reflect.Method; public class Test {
public static void target(int i) {
new Exception("#" + i).printStackTrace();
} public static void main(String[] args) throws Exception {
Class<?> klass = Class.forName("Test");
Method method = klass.getMethod("target", int.class);
method.invoke(null, 0);
}
} # 不同版本的输出略有不同,这里我使用了 Java 10。
$ java Test
java.lang.Exception: #0
at Test.target(Test.java:5)
**本地实现** at java.base/jdk.internal.reflect.NativeMethodAccessorImpl .invoke0(Native Method)
**↑** at java.base/jdk.internal.reflect.NativeMethodAccessorImpl. .invoke(NativeMethodAccessorImpl.java:62)
**委派实现** at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.i .invoke(DelegatingMethodAccessorImpl.java:43)
**↑
invoke** at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at Test.main(Test.java:131
  • 委派实现

作为invoke实现的中间件

选择method invoke本地实现还是动态实现

  • 动态实现(纯java字节码, 无需重新从java→c++→java)

优势在于避免了 JNI ( java native interface )的切换开销,但它的缺点是生成字节码耗时

// 动态实现的伪代码,这里只列举了关键的调用逻辑,其实它还包括调用者检测、参数检测的字节码。
package jdk.internal.reflect; public class GeneratedMethodAccessor1 extends ... {
@Overrides
public Object invoke(Object obj, Object[] args) throws ... {
Test.target((int) args[0]);
return null;
}
}
Method method1 = Test.class.getMethod("target", int.class);
Method method2 = Test.class.getMethod("target", int.class);

JVM实现invokedynamic

方法句柄(Method Handle)

class Foo {
private static void bar(Object o) {
..
}
public static Lookup lookup() {
return MethodHandles.lookup();
}
} // 获取方法句柄的不同方式
MethodHandles.Lookup l = Foo.lookup(); // 具备 Foo 类的访问权限
Method m = Foo.class.getDeclaredMethod("bar", Object.class);
MethodHandle mh0 = l.unreflect(m); MethodType t = MethodType.methodType(void.class, Object.class);
MethodHandle mh1 = l.findStatic(Foo.class, "bar", t);

方法句柄的操作


如果你看完了, 非常感谢你对我付出的认可

几分钟了解下java虚拟机--02的更多相关文章

  1. 带着新人看java虚拟机02

    上一节是把大概的流程给过了一遍,但是还有很多地方没有说到,后续的慢慢会涉及到,敬请期待! 这次我们说说垃圾收集器,又名gc,顾名思义,就是收集垃圾的容器,那什么是垃圾呢?在我们这里指的就是堆中那些没人 ...

  2. go实现java虚拟机02

    上一篇通过flag包实现了命令行参数的解析,其实就是将输入的参数保存到一个结构体中,上一篇说过的例如java -classpath hello.jar HelloWorld这种命令,那么HelloWo ...

  3. 每日一问:你了解 Java 虚拟机结构么?

    对于从事 C/C++ 程序员开发的小伙伴来说,在内存管理领域非常头疼,因为他们总是需要对每一个 new 操作去写配对的 delete/free 代码.而对于我们 Android 乃至 Java 程序员 ...

  4. java虚拟机理解探索1

    以下内容源于个人对<深入java虚拟机>的理解总结 基本概念: java虚拟机可以指一种抽象规范,也可以指一种具体实现,亦可以指一个java虚拟机实例. 虚拟机生命周期: 一个java虚拟 ...

  5. 深入java虚拟机学习 -- 内存管理机制

    前面说过了类的加载机制,里面讲到了类的初始化中时用到了一部分内存管理的知识,这里让我们来看下Java虚拟机是如何管理内存的. 先让我们来看张图 有些文章中对线程隔离区还称之为线程独占区,其实是一个意思 ...

  6. 谈谈java虚拟机

    本文可作为北京圣思元深入java虚拟机的课堂笔记. 先看一个令人dan teng的面试题 public class Singleton { public static Singleton s=new ...

  7. JVM基础系列第2讲:Java 虚拟机的历史

    说起 Java 虚拟机,许多人就会将其与 HotSpot 虚拟机等同看待.但实际上 Java 虚拟机除了 HotSpot 之外,还有 Sun Classic VM.Exact VM.BEA JRock ...

  8. day 05JVM和深入理解java虚拟机

    -----------------Java 虚拟机发展史 PS: Sun公司有 HotSpot, BEA公司有JRockit,IBM有 J9  这三个是高性能VM 在Oracle收购Sun和BEA这两 ...

  9. java虚拟机的内存机制

    我们都知道,java程序的跨平台性离不开java虚拟机,虚拟机隔绝了底层操作系统,使得java程序可以直接运行在虚拟机之上.所以,对java的学习,离不开对java虚拟机的学习与了解.下面简单整理下j ...

  10. 深入理解Java虚拟机—内存管理机制

    前面说过了类的加载机制,里面讲到了类的初始化中时用到了一部分内存管理的知识,这里让我们来看下Java虚拟机是如何管理内存的. 先让我们来看张图 有些文章中对线程隔离区还称之为线程独占区,其实是一个意思 ...

随机推荐

  1. 学习 Docker 如何查看镜像信息?

    学习 Docker 如何查看镜像信息? 一.images 命令列出镜像 通过使用如下两个命令,列出本机已有的镜像: docker images 或: docker image ls 如下图所示: 对上 ...

  2. WebGL 的简易入门教程

    目录 前言 第一节 绘制出了一个点 效果演示 逐行解释 向量类型 第二节 动态传递点数据 变量修饰符 完整代码 第三节 缓冲区和画线 类型化数组 绘制的方式 完整代码 第四节 彩色线段 精度修饰符 完 ...

  3. Fetch 别名查找

       if (PlanClass.Attributes.Contains("new_excelcolor_avg"))                                ...

  4. C# Socket的使用方法 及 简单实例

    核心: 在服务器端和客户端的两个Socket实例,共同维持一个连接,而我们还需要一个服务端绑定了特定端口号的固定的serverSocket,用来监听远方clientSocket的申请,并为这个申请建立 ...

  5. CDS是一个企业级的持续交付和DevOps自动化开源平台

    CDS是一个企业级的持续交付和DevOps自动化开源平台 弹性 CDS资源/worker是按需启动的,以确保用户的等待时间较短,并且不会过度消耗空闲资源 可扩展的 在CDS中,任何类型的操作(Kube ...

  6. 探秘Transformer系列之(24)--- KV Cache优化

    探秘Transformer系列之(24)--- KV Cache优化 目录 探秘Transformer系列之(24)--- KV Cache优化 0x00 前言 0x01 背景知识 1.1 度量指标 ...

  7. 什么是 Java 中的 JIT(Just-In-Time)?

    Java 中的 JIT(Just-In-Time)编译器 1. JIT 的定义 JIT(Just-In-Time)编译器是一种用于 Java 虚拟机(JVM)的动态编译技术.它在 Java 程序运行时 ...

  8. 至美!看AXUI如何美化原始HTML标签(reset/normalize)

    前言:不只是重置,而是重塑 在前端开发中,我们每天都会接触大量的原生 HTML 标签,例如 <button>.<input>.<a>.<table>.& ...

  9. chrome “从 Google 获取图片说明”

    右键菜单"从 Google 获取图片说明"多余去掉. 设置-高级-使用硬件加速模式(如果可用)-关闭 在用户使用上firefox完胜chrome,但是firefox的开发人员工具相 ...

  10. vue3 基础-Mixin

    本篇开始来学习一波 vue 中的一些复用性代码的基础操作, 首先来介绍关于代码 "混入" mixin 的写法. 直观理解这个 mixin 就是一个 js 对象去 "混入& ...