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

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

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 在不重建容器的情况下,日志文件默认会一直追加,时间一长会逐渐占满服务器的硬盘的空间,内存消耗也会一直增加,本篇来了解一些控制日志文件的方法. 清理单个文件 运行时控制 全局配置 Dock ...

  2. post数据到第三方,中文乱码

    1.项目中发现 测试环境 推送正文,数据正常 2.生产到腾讯云之后,中文推送过去乱码,但是post 接口的 时候,指定了 编码格式. 3.后查看日志,发现日志中记录的中文就是乱码 4.排查cs代码文件 ...

  3. 深入理解Hadoop读书笔记-2

    背景 公司的物流业务系统目前实现了使用storm集群进行过门事件的实时计算处理,但是还有一个需求,我们需要存储每个标签上传的每条明细数据,然后进行定期的标签报表统计,这个是目前的实时计算框架无法满足的 ...

  4. 使用benchmarksql测试数据库处理能力

    我们所处行业的核心应用业务,当前还是传统的OLTP业务,应用系统使用 java 开发,并且不建议使用存储过程,使用 benchmarksql 压测数据库最公平,既可以测试数据库性能,也可以测试JDBC ...

  5. spring的控制反转(IoC)

    ioc的作用: 削减计算机程序的耦合(解除我们代码中的依赖关系 解耦的思路: 第一步:使用反射来创建对象,而避免使用new关键字. 第二步:通过读取配置文件来获取要创建的对象全限定类名

  6. MySQL 的索引类型有哪些?

    MySQL 的索引类型 MySQL 提供多种索引类型,用于优化数据查询性能.每种索引类型在存储结构.适用场景和性能特性方面各不相同. 1. 常见的索引类型 (1)B+树索引 结构:基于 B+ 树实现, ...

  7. 基于CARLA与PyTorch的自动驾驶仿真系统全栈开发指南

    引言:自动驾驶仿真的价值与技术栈选择 自动驾驶作为AI领域最具挑战性的研究方向之一,其开发流程需要经历"仿真测试-闭环验证-实车部署"的完整链路.其中,高保真仿真平台为算法迭代提供 ...

  8. 3d xna fbx winfrom 读取

    本文通过参考网上资源做的一个例子. 本程序的功能就是通过xna 将3d 图像显示到winfrom 对他进行旋转操作. 首先我们先准备好两个文件夹 model  文件夹放fbx文件,textures 放 ...

  9. Java编程--String类和基本数据类型的相互转换

    基本数据类型:byte.short.int.long.char.float.double.boolean 基本数据类型->String:利用String类提供的ValueOf(基本类型)方法转换 ...

  10. 下载mysql-connector-java-8.*.*.jar

    各个版本mysql驱动jar包下载:http://central.maven.org/maven2/mysql/mysql-connector-java/ 直达下载链接:https://dev.mys ...