support retransform

This commit is contained in:
yushijinhun 2018-02-17 21:39:33 +08:00
parent bfa2629ff7
commit 83dcd8380f
No known key found for this signature in database
GPG key ID: 5BC167F73EA558E4
3 changed files with 81 additions and 7 deletions

View file

@ -27,7 +27,10 @@ jar {
'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
'Git-Commit': gitInfo.gitHashFull,
'Git-IsClean': gitInfo.isCleanTag,
'Premain-Class': 'org.to2mbn.authlibinjector.javaagent.AuthlibInjectorPremain'
'Premain-Class': 'org.to2mbn.authlibinjector.javaagent.AuthlibInjectorPremain',
'Agent-Class': 'org.to2mbn.authlibinjector.javaagent.AuthlibInjectorPremain',
'Can-Retransform-Classes': true,
'Can-Redefine-Classes': true
)
}
}

View file

@ -15,7 +15,7 @@ import org.to2mbn.authlibinjector.transform.YggdrasilKeyTransformUnit;
public final class AuthlibInjector {
private static final String[] nonTransformablePackages = new String[] { "java.", "javax.", "com.sun.",
public static final String[] nonTransformablePackages = new String[] { "java.", "javax.", "com.sun.",
"com.oracle.", "jdk.", "sun.", "org.apache.", "com.google.", "oracle.", "com.oracle.", "com.paulscode.",
"io.netty.", "org.lwjgl.", "net.java.", "org.w3c.", "javassist.", "org.xml.", "org.jcp.", "paulscode.",
"com.ibm.", "joptsimple.", "org.to2mbn.authlibinjector." };

View file

@ -1,21 +1,92 @@
package org.to2mbn.authlibinjector.javaagent;
import static org.to2mbn.authlibinjector.AuthlibInjector.bootstrap;
import static org.to2mbn.authlibinjector.AuthlibInjector.debug;
import static org.to2mbn.authlibinjector.AuthlibInjector.info;
import static org.to2mbn.authlibinjector.AuthlibInjector.nonTransformablePackages;
import java.lang.instrument.Instrumentation;
import java.util.Arrays;
public class AuthlibInjectorPremain {
public static void premain(String arg, Instrumentation instrumentation) {
try {
info("launched from javaagent");
if (arg != null && !arg.isEmpty()) {
System.setProperty("org.to2mbn.authlibinjector.config", arg);
}
bootstrap(instrumentation::addTransformer);
info("launched from premain");
initInjector(arg, instrumentation, false);
} catch (Throwable e) {
// prevent the exception being thrown to VM
e.printStackTrace();
}
}
public static void agentmain(String arg, Instrumentation instrumentation) {
try {
info("launched from agentmain");
initInjector(arg, instrumentation, true);
} catch (Throwable e) {
// prevent the exception being thrown to VM
e.printStackTrace();
}
}
public static void initInjector(String arg, Instrumentation instrumentation, boolean needsRetransform) {
setupConfig(arg);
boolean retransformSupported = instrumentation.isRetransformClassesSupported();
boolean retransformEnabled = retransformSupported && needsRetransform;
bootstrap(x -> instrumentation.addTransformer(x, retransformEnabled));
if (needsRetransform) {
if (retransformSupported) {
info("start retransforming");
doRetransform(instrumentation);
} else {
info("retransforming is not supported");
}
}
}
private static void setupConfig(String arg) {
if (arg != null && !arg.isEmpty()) {
System.setProperty("org.to2mbn.authlibinjector.config", arg);
}
}
private static void doRetransform(Instrumentation instrumentation) {
try {
long t0 = System.currentTimeMillis();
Class<?>[] classToRetransform = getClassesToRetransform(instrumentation);
if (classToRetransform.length > 0) {
instrumentation.retransformClasses(classToRetransform);
}
long t1 = System.currentTimeMillis();
info("retransforming finished in {0}ms", t1 - t0);
} catch (Throwable e) {
info("unable to retransform");
e.printStackTrace();
}
}
private static Class<?>[] getClassesToRetransform(Instrumentation instrumentation) {
Class<?>[] loadedClasses = instrumentation.getAllLoadedClasses();
Class<?>[] dest = new Class[loadedClasses.length];
int idx = 0;
for (Class<?> clazz : loadedClasses) {
if (instrumentation.isModifiableClass(clazz)) {
boolean toRetransform = true;
for (String nonTransformablePackage : nonTransformablePackages) {
if (clazz.getName().startsWith(nonTransformablePackage)) {
toRetransform = false;
break;
}
}
if (toRetransform) {
dest[idx++] = clazz;
}
}
}
debug("loaded {0} classes, {1} to retransform", loadedClasses.length, idx);
return Arrays.copyOf(dest, idx);
}
}