C
C
CoreModTutor
Search
K

JavaAgent

虽然FML从未使用过JavaAgent来对Minecraft进行修改,但是这也是一种合理的动态修改方式。 JavaAgent由JVM进行支持,可以在class文件被加载时对其进行动态的修改。

制作方法

JavaAgent由以下几部分组成——premain方法、ClassFileTransformer接口。

premain

premain方法会在Java的入口方法main前执行。 一个典型的写法如下:
package com.example;
import java.lang.instrument.Instrumentation;
public class ExampleAgent {
public static void premain(String args, Instrumentation instrumentation){
//TODO: 在此补充代码
}
}
这个方法可以获得一个Instrumentation的实例,通过这个实例我们可以注册ClassFileTransformer
ExampleTransformer transformer = new ExampleTransformer();
instrumentation.addTransformer(transformer);
premain方法和main方法一样,需要写入Manifest才能使JVM执行,我们可以通过修改gradle.build的方式加入:
jar {
manifest {
attributes([
"Premain-Class": "com.example.ExampleAgent"
])
}

ClassFileTransformer

这个接口只有一个方法transform,需要返回修改完后的class文件byte数组,这个方法会在ClassLoaderdefineClass时被调用,参数如下:
  • loader,当前使用的ClassLoader
  • className,当前加载的class名称
  • classBeingRedefined,为retransform设计,重新加载前的Class对象
  • protectionDomain,保护的域
  • classfileBuffer,class文件的byte数组
一个没有任何作用的ClassFileTransformer如下:
package com.example;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
public class ExampleTransformer implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
//TODO: 可以在此写ASM代码
return classfileBuffer;
}
}

安装方法

在游戏的JVM参数中加入:
-javaagent:filename=args
  • filename为jar的文件名
  • args为传入premain方法的参数

弊端

  • 需要用户修改JVM参数来使用JavaAgent,相对于其他安装方法较为麻烦
  • 优先级过低,一般情况下都是最后一个对类进行修改