Skip to content

Commit

Permalink
Merge branch 'mercyblitz:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Kurok1 committed Dec 3, 2022
2 parents 654e5b0 + 9d3c3d0 commit c8d815e
Showing 1 changed file with 300 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
# 主要内容
## Java Instrument 机制
理解 Java Instrument 机制,并掌握字节码提升编程
#### Java ClassLoading
##### Class Loading
##### Class Definition
##### Resource Loading
#### Java Reflection
#### Java Dynamic Proxy
#### Java Bytecode
#### Java Agent

- JProfiler
- Pinpoint
- Skywalking



## Web 服务链路重构
基于字节码提升工具 Spring Cloud Open Feign 以及 Spring WebMVC
## 第三方服务链路重构
重构 Redis、JDBC 以及 MyBatis 服务链路实现


##

# 关联技术
## Byte Buddy
Byte Buddy is a code generation and manipulation library for creating and modifying Java classes during the runtime of a Java application and without the help of a compiler.
## Java Instrumentation
### 官方文档
[https://docs.oracle.com/javase/8/docs/technotes/guides/instrumentation/index.html](https://docs.oracle.com/javase/8/docs/technotes/guides/instrumentation/index.html)
## Java Reflection
在面向对象的编程模型中,提供一个中元数据的编程方法
### 官方文档
[https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/index.html](https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/index.html)

### 元信息(Meta)
Java 8 之前存放在永久代,Java 8+ 开始存放在 Metaspace(可使用 JVM 之外的内存)
#### Class - 类对象

- Class 对象是由 ClassLoader 来加载(验证、加载以及存储)
- ClassLoader 相当于 Class 的一个字典(Map),每个 Class 在它所加载的 ClassLoader 是一个单例
- 相同全类名的 Class 对象可能在一个 JVM 进程中存在多个,取决于多少个 ClassLoader 加载过(它)。
> Spring Boot devtools 工具的话,可能会遇到一个问题 Class A 不是 Class A
- 如果需要卸载某个 Class 的话,需要 GC 掉某个 ClassLoader,比如 Java Based 某些编译工具,Groovy - ClassLoader
- 成员:
- 字段 - Field
- 可执行成员 - Executable
- 构造器 - Constructor
- 方法 - Method
#### Field - 字段
#### Constructor - 构造器
#### Method - 方法

- 一个 Method 属于一个 Class 对象,单个 Class 对象属于某个 ClassLoader,一个 Method 在一个 ClassLoader 仅有一个,Method 对象在 ClassLoader 是单例共享对象,可是 Java 对象至少存在一个

##### 实例代码
```java
class A {

@Override
public String toString(){
return "A";
}

private String getDescription(){
return "...";
}

}

public class Main {

public static void main(String[] args){

Method toStringMethod = ... ; // A 类 toString() 方法,该方法是继承于 Object#toString()
Method getDescriptionMethod = ... ;//
// Java 反射默认不会打破 Java 面向对象封装性,
// 所以当 toStringMethod 被调用时,不会报错
// 相反,getDescriptionMethod 被调用时,会报错
// Java 反射在运行时做可访问性,需要得到当前调用栈的上下文,以当前为例:
// Main#main -> A#getDescription
// 因此,当 getDescriptionMethod 被调用时,运行时需要获得 Caller Class,
// 即 Main Class

// 编译时检查
A a = new A();
a.toString(); // 编译时检查可访问性,因为该方法是 public 方法,所以编译通过

a.getDescription(); // 编译时检查可访问性,由于该方法是 private 方法,所以编译不通过
}

}
```

## Java ClassLoader
### Java ClassLoading
### Resource Loading

## Java Tool API
### Java Compiler
Dubbo Service 自动代码生成 Swager API
Dubbo Service 通过反射获取元信息 -> 生成 Java Source 内容 -> 编译成 Java Class -> 注册到 Swagger 中心
#### Java 编译过程
生成语法分析树
Java 注解处理
字节代码生成

### Java Annotation Processor(APT)
#### 核心 API
##### 处理器接口 - javax.annotation.processing.Processor
#### 参考实现

- Dubbo dubbo-metadata-processor
- Spring Framework - spring-context-indexer
- Spring Boot - spring-boot-configuration-processor


### Java Debugger API(JDB)

## Java Tool Interface
[https://docs.oracle.com/javase/8/docs/technotes/guides/jvmti/index.html](https://docs.oracle.com/javase/8/docs/technotes/guides/jvmti/index.html)

## Java Runtime Code Generation
### Java Dynamic Proxy
#### 核心 API
##### 代理工厂 API - java.lang.reflect.Proxy
###### 依赖

- ClassLoader - 加载 Interfaces ,定义并加载新生成的 Java 代理类
- Interfaces - 新生成的 Java 代理类实现的接口(集合)
- InvocationHandler - Interfaces 方法的调用拦截器(还需要包括 java.lang.Object)
###### 核心方法
查找并且生成 Java 代理类 - java.lang.reflect.Proxy#getProxyClass0
```java
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}

// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
```
内部使用 API

- java.lang.reflect.WeakCache
- K - ClassLoader
- P - Class[] 接口集合
- V - 生成代理 Class
##### 代理类工厂 API - java.lang.reflect.Proxy.ProxyClassFactory

- 类命名
- 固定前缀:$Proxy

##### 代理类生成器 API - sun.misc.ProxyGenerator
###### 配置参数

- Java System Property 保存字节生成文件 - sun.misc.ProxyGenerator.saveGeneratedFiles
###### 主要方法

- 生成 Class 文件 - generateClassFile
```java
/*
* Record that proxy methods are needed for the hashCode, equals,
* and toString methods of java.lang.Object. This is done before
* the methods from the proxy interfaces so that the methods from
* java.lang.Object take precedence over duplicate methods in the
* proxy interfaces.
*/
addProxyMethod(hashCodeMethod, Object.class);
addProxyMethod(equalsMethod, Object.class);
addProxyMethod(toStringMethod, Object.class);

/*
* Now record all of the methods from the proxy interfaces, giving
* earlier interfaces precedence over later ones with duplicate
* methods.
*/
for (Class<?> intf : interfaces) {
for (Method m : intf.getMethods()) {
addProxyMethod(m, intf);
}
}

```

- 添加代理方法 - addProxyMethod
```java
private void addProxyMethod(Method m, Class<?> fromClass) {
String name = m.getName();
Class<?>[] parameterTypes = m.getParameterTypes();
Class<?> returnType = m.getReturnType();
Class<?>[] exceptionTypes = m.getExceptionTypes();

String sig = name + getParameterDescriptors(parameterTypes);
List<ProxyMethod> sigmethods = proxyMethods.get(sig);
if (sigmethods != null) {
for (ProxyMethod pm : sigmethods) {
if (returnType == pm.returnType) {
/*
* Found a match: reduce exception types to the
* greatest set of exceptions that can thrown
* compatibly with the throws clauses of both
* overridden methods.
*/
List<Class<?>> legalExceptions = new ArrayList<>();
collectCompatibleTypes(
exceptionTypes, pm.exceptionTypes, legalExceptions);
collectCompatibleTypes(
pm.exceptionTypes, exceptionTypes, legalExceptions);
pm.exceptionTypes = new Class<?>[legalExceptions.size()];
pm.exceptionTypes =
legalExceptions.toArray(pm.exceptionTypes);
return;
}
}
} else {
sigmethods = new ArrayList<>(3);
proxyMethods.put(sig, sigmethods);
}
sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
exceptionTypes, fromClass));
}
```

- 生成的实例代码
```java
public final class $Proxy32 extends Proxy implements RedisConnection {

private final h; //

private static Method isPipelinedMethod = ... ;

public $Proxy32(InvocationHandler h){
this.h = h;
}

public boolean isPipelined(){
this.h.invoke(this,isPipelinedMethod,new Object[0]);
}
//...
}
```
### Java 注解实现
隶属于 Java Dynamic Proxy
```java
public final class $Proxy6 extends Proxy implements ContextConfiguration {
private static Method m1;
private static Method m3;
private static Method m9;
private static Method m5;
private static Method m7;
private static Method m10;
private static Method m2;
private static Method m11;
private static Method m8;
private static Method m6;
private static Method m0;
private static Method m4;

public $Proxy6(InvocationHandler var1) throws {
super(var1);
}

...
public final Class annotationType() throws {
try {
return (Class)super.h.invoke(this, m11, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
...
}
```
###


### ASM
Java 字节码“汇编”,可认为字节码生成框架的“鼻祖”或“元祖”

###
### CGLIB
### Javassist


## Java 5 -> Java 6

## Java 工具
### JProfiler
### JRebel

0 comments on commit c8d815e

Please sign in to comment.