Reflection:版本对比 v1 → v2
v1(2026-10-04 01:15,朝武芳乃)→ v2(2026-10-04 03:21,mcst12345)
共 24 行变更 · 新增 14 行 · 删除 3 行(左右分栏:左为旧版本,右为新版本)
| 1 | ''本条基于 Java 17(Minecraft 1.20.1 所用版本)。'' | ||
| 2 | |||
| 3 | '''Reflection'''(反射,<code>java.lang.reflect</code>)是在运行时获取类、字段、方法、构造器的信息并调用它们的机制。 | 1 | '''Reflection'''(反射,<code>java.lang.reflect</code>)是在运行时获取类、字段、方法、构造器的信息并调用它们的机制。 |
| 4 | 2 | ||
| ⋯ 省略 9 行未变内容 ⋯ | |||
| 14 | 12 | ||
| 15 | == 在模组中 == | 13 | == 在模组中 == |
| 16 | * Forge 1.20.1 生产环境使用 SRG 名,反射时要写 SRG 名,或使用 <code>ObfuscationReflectionHelper</code> 自动映射。 | ||
| 14 | * 運行時對於mc原版字段/方法需使用中間混淆名,或使用 <code>ObfuscationReflectionHelper</code> 自动映射。 | ||
| 17 | * 反射调用有额外开销,热点代码可改用 [[MethodHandle]]。 | 15 | * 反射调用有额外开销,热点代码可改用 [[MethodHandle]]。 |
| 18 | * 例如通过反射取得 [[ServerLevel]] 的 <code>entityTickList</code>,即可直接操作 [[EntityTickList]]。 | 16 | * 例如通过反射取得 [[ServerLevel]] 的 <code>entityTickList</code>,即可直接操作 [[EntityTickList]]。 |
| 17 | |||
| 18 | '''Reflection''' is a Java mechanism to access classes, methods, fields and their metadata at runtime without knowing what their are. | ||
| 19 | Before JPMS you can use reflection to access nearly everything: unfortunately you can't do that anymore since Java9+. The module system introduced more strict access control, that class A from module A cannot access class B in module B if B isn't declared as "opened" in module B event if B is public. | ||
| 20 | Fortunately there are workarounds to fuck up module system's access control. | ||
| 21 | |||
| 22 | == Commonly used APIs == | ||
| 23 | * <code>Class.forName</code>、<code>getDeclaredField</code>、<code>getDeclaredMethod</code>、<code>getDeclaredConstructor</code> To obtain handles for class/field/method, Constructor can be considered an extension to Method. | ||
| 24 | * <code>Field.get</code> / <code>Field.set</code>、<code>Method.invoke</code>、<code>Constructor.newInstance</code> To actually invoke your handle. | ||
| 25 | * <code>setAccessible(true)</code> Tell JVM to ignore the private/protected access flag and do WTF you want. | ||
| 26 | |||
| 27 | == Notes == | ||
| 28 | getDeclaredField, getDeclaredMethod, getDeclaredConstructor etc. returns cached/copied handles that can be spoofed. To get the true handles you can invoke getDeclaredField0, getDeclaredMethod0, getDeclaredConstructor0, etc. | ||
| 29 | Reflection is known to be suck at performance as it does much work automatically like boxing/unboxing and type cast. MethodHandle/VarHandle will be a better alternative if you know exactly what you need to invoke. | ||