下面列出了怎么用java.lang.instrument.ClassDefinition的API类实例代码及写法,或者点击链接到github查看源代码。
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
/**
* Saves changed by retransforming classes.
*
* @throws ClassNotFoundException
* When the modified class couldn't be found.
* @throws UnmodifiableClassException
* When the modified class is not allowed to be modified.
* @throws ClassFormatError
* When the modified class is not valid.
*/
public void save() throws ClassNotFoundException, UnmodifiableClassException, ClassFormatError {
// Classes to update
Set<String> dirty = new HashSet<>(getDirtyClasses());
if(dirty.isEmpty()) {
Log.info("There are no classes to redefine.", dirty.size());
return;
}
Log.info("Preparing to redefine {} classes", dirty.size());
ClassDefinition[] definitions = new ClassDefinition[dirty.size()];
int i = 0;
for (String name : dirty) {
String clsName = name.replace('/', '.');
Class<?> cls = Class.forName(clsName, false, ClasspathUtil.scl);
byte[] value = getClasses().get(name);
if (value == null)
throw new IllegalStateException("Failed to fetch code for class: " + name);
definitions[i] = new ClassDefinition(cls, value);
i++;
}
// Apply new definitions
instrumentation.redefineClasses(definitions);
// We don't want to continually re-apply changes that don't need to be updated
getDirtyClasses().clear();
Log.info("Successfully redefined {} classes", definitions.length);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
/**
* Redefine the supplied set of classes using the supplied bytecode.
*
* This method operates on a set in order to allow interdependent changes to more than one class at the same time
* (a redefinition of class A can require a redefinition of class B).
*
* @param reloadMap class -> new bytecode
* @see java.lang.instrument.Instrumentation#redefineClasses(java.lang.instrument.ClassDefinition...)
*/
public void hotswap(Map<Class<?>, byte[]> reloadMap) {
if (instrumentation == null) {
throw new IllegalStateException("Plugin manager is not correctly initialized - no instrumentation available.");
}
synchronized (reloadMap) {
ClassDefinition[] definitions = new ClassDefinition[reloadMap.size()];
String[] classNames = new String[reloadMap.size()];
int i = 0;
for (Map.Entry<Class<?>, byte[]> entry : reloadMap.entrySet()) {
classNames[i] = entry.getKey().getName();
definitions[i++] = new ClassDefinition(entry.getKey(), entry.getValue());
}
try {
LOGGER.reload("Reloading classes {} (autoHotswap)", Arrays.toString(classNames));
synchronized (hotswapLock) {
instrumentation.redefineClasses(definitions);
}
LOGGER.debug("... reloaded classes {} (autoHotswap)", Arrays.toString(classNames));
} catch (Exception e) {
throw new IllegalStateException("Unable to redefine classes", e);
}
reloadMap.clear();
}
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void redefineClasses(Map<Class<?>, byte[]> classes)
throws ClassNotFoundException, UnmodifiableClassException {
if (PluginManager.getInstance().getInstrumentation() == null) {
throw new IllegalStateException(
"Instrumentation agent is not properly installed!");
}
ClassDefinition[] definitions = new ClassDefinition[classes.size()];
int i = 0;
for (Map.Entry<Class<?>, byte[]> entry : classes.entrySet()) {
definitions[i++] = new ClassDefinition(entry.getKey(),
entry.getValue());
URL classResource = getClassResource(entry.getKey());
try (OutputStream fileWriter = new FileOutputStream(
new File(classResource.toURI()))) {
fileWriter.write(entry.getValue());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
PluginManager.getInstance().getInstrumentation()
.redefineClasses(definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
public void
redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException {
if (!isRedefineClassesSupported()) {
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
}
if (definitions == null) {
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
}
for (int i = 0; i < definitions.length; ++i) {
if (definitions[i] == null) {
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
}
}
if (definitions.length == 0) {
return; // short-circuit if there are no changes requested
}
redefineClasses0(mNativeAgent, definitions);
}
/**
* 重新热加载Class
* @param clazzDefines 有过变更的文件信息
* @throws UnmodifiableClassException 不可修改的 Class 异常
* @throws ClassNotFoundException Class未找到异常
*/
public static void reloadClass(Map<Class, byte[]> clazzDefines) throws UnmodifiableClassException, ClassNotFoundException {
for(Map.Entry<Class, byte[]> clazzDefine : clazzDefines.entrySet()){
Class clazz = clazzDefine.getKey();
byte[] classBytes = clazzDefine.getValue();
ClassDefinition classDefinition = new ClassDefinition(clazz, classBytes);
try {
Logger.info("[HOTSWAP] class:" + clazz + " will reload.");
TEnv.instrumentation.redefineClasses(classDefinition);
} catch (Exception e) {
Logger.error("[HOTSWAP] class:" + clazz + " reload failed", e);
}
}
}
/**
* Re-apply all mixins to the supplied list of target classes.
*
* @param targets Target classes to re-transform
* @return true if all targets were transformed, false if transformation
* failed
*/
private boolean reApplyMixins(List<String> targets) {
IMixinService service = MixinService.getService();
for (String target : targets) {
String targetName = target.replace('/', '.');
MixinAgent.logger.debug("Re-transforming target class {}", target);
try {
Class<?> targetClass = service.getClassProvider().findClass(targetName);
byte[] targetBytecode = MixinAgent.classLoader.getOriginalTargetBytecode(targetName);
if (targetBytecode == null) {
MixinAgent.logger.error("Target class {} bytecode is not registered", targetName);
return false;
}
targetBytecode = MixinAgent.this.classTransformer.transformClassBytes(null, targetName, targetBytecode);
MixinAgent.instrumentation.redefineClasses(new ClassDefinition(targetClass, targetBytecode));
} catch (Throwable th) {
MixinAgent.logger.error("Error while re-transforming target class " + target, th);
return false;
}
}
return true;
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f);
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodWithAnnotationsAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f.getAbsolutePath());
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodInBacktraceAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f);
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodWithAnnotationsAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f.getAbsolutePath());
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodInBacktraceAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f);
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodWithAnnotationsAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f.getAbsolutePath());
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodInBacktraceAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f);
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodWithAnnotationsAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f.getAbsolutePath());
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodInBacktraceAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
@Override
public void redefine(ClassBytecodes[] cbcs) throws ClassInstallException, NotImplementedException, EngineTerminationException {
int count = cbcs.length;
boolean[] status = new boolean[cbcs.length];
int success = 0;
NbRemoteLoader ldr = prepareClassLoader();
for (int i = 0; i < count; i++) {
String name = cbcs[i].name();
byte[] replaceBytecode = cbcs[i].bytecodes();
Long id = ldr.getClassId(name);
if (id != null) {
Class defined = ldr.getClassOfId(id);
try {
agent.getInstrumentation().redefineClasses(
new ClassDefinition(defined, replaceBytecode)
);
status[i] = true;
success++;
} catch (ClassNotFoundException | UnmodifiableClassException ex) {
Logger.getLogger(AgentWorker.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (success < count) {
throw new ClassInstallException("Could not redefine classes", status);
}
}
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f);
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodWithAnnotationsAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
private static void doRedefine(Class<?> clazz) throws Exception {
// Load the second version of this class.
File f = new File(clazz.getName() + ".class");
System.out.println("Reading test class from " + f.getAbsolutePath());
InputStream redefineStream = new FileInputStream(f);
byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream);
ClassDefinition redefineParamBlock = new ClassDefinition(
clazz, redefineBuffer);
RedefineMethodInBacktraceAgent.getInstrumentation().redefineClasses(
new ClassDefinition[] {redefineParamBlock});
}
static void redefine() {
if (instr == null) {
System.out.println("NOT REDEFINED");
return;
}
ClassDefinition cd = new ClassDefinition(CLS, getClassFile(1));
try {
instr.redefineClasses(cd);
} catch (Exception e) {
throw new Error(e);
}
System.out.println("REDEFINED");
}