下面列出了java.lang.instrument.Instrumentation#retransformClasses ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static void agentmain(String agentArgs, Instrumentation inst)
throws ClassNotFoundException, UnmodifiableClassException,
InterruptedException {
final ColaTransformer transformer = new ColaTransformer(convert(agentArgs));
if(!isLock(transformer)){
return;
}
try {
inst.addTransformer(transformer, true);
Set<Class<?>> oriClassSet = searchClass(inst, transformer.getArgs().getClassName(), 1000);
final Class<?>[] classArray = new Class<?>[oriClassSet.size()];
System.arraycopy(oriClassSet.toArray(), 0, classArray, 0, oriClassSet.size());
inst.retransformClasses(classArray);
}finally {
inst.removeTransformer(transformer);
}
System.out.println("agentmain DONE");
}
public static void retransformClasses(Instrumentation inst, ClassFileTransformer transformer,
Set<Class<?>> classes) {
try {
inst.addTransformer(transformer, true);
for (Class<?> clazz : classes) {
try {
inst.retransformClasses(clazz);
} catch (Throwable e) {
String errorMsg = "retransformClasses class error, name: " + clazz.getName();
if (ClassUtils.isLambdaClass(clazz) && e instanceof VerifyError) {
errorMsg += ", Please ignore lambda class VerifyError: https://github.com/alibaba/arthas/issues/675";
}
logger.error(errorMsg, e);
}
}
} finally {
inst.removeTransformer(transformer);
}
}
private void retransform(Instrumentation instrumentation) {
final String lambdaMetaFactoryName = "java.lang.invoke.InnerClassLambdaMetafactory";
try {
final Class<?> lamdbaFactoryClazz = Class.forName(lambdaMetaFactoryName, false, null);
logger.info("retransformClasses:{}", lamdbaFactoryClazz);
final ClassFileTransformer classFileTransfomrer = new InnerClassLambdaMetafactoryTransformer();
instrumentation.addTransformer(classFileTransfomrer, true);
try {
instrumentation.retransformClasses(lamdbaFactoryClazz);
} finally {
instrumentation.removeTransformer(classFileTransfomrer);
}
} catch (Exception e) {
logger.warn("retransform fail class:{}", lambdaMetaFactoryName, e);
}
}
public static void initialReweave(Set<PointcutClassName> pointcutClassNames,
Class<?>[] initialLoadedClasses, Instrumentation instrumentation) {
if (!instrumentation.isRetransformClassesSupported()) {
return;
}
Set<Class<?>> classes = getExistingModifiableSubClasses(pointcutClassNames,
initialLoadedClasses, instrumentation);
for (Class<?> clazz : classes) {
if (clazz.isInterface()) {
continue;
}
try {
instrumentation.retransformClasses(clazz);
} catch (UnmodifiableClassException e) {
// IBM J9 VM Java 6 throws UnmodifiableClassException even though call to
// isModifiableClass() in getExistingModifiableSubClasses() returns true
logger.debug(e.getMessage(), e);
}
}
}
public static void premain(String agentArgs, Instrumentation inst) throws ClassNotFoundException {
preloadClasses();
inst.addTransformer(new SnoopInstructionTransformer(), true);
if (inst.isRetransformClassesSupported()) {
for (Class clazz : inst.getAllLoadedClasses()) {
try {
String cname = clazz.getName().replace(".","/");
if (shouldExclude(cname) == false) {
if (inst.isModifiableClass(clazz)) {
inst.retransformClasses(clazz);
} else {
println("[WARNING] Could not instrument " + clazz);
}
}
} catch (Exception e){
if (verbose) {
println("[WARNING] Could not instrument " + clazz);
e.printStackTrace();
}
}
}
}
}
public static void premain(String args, Instrumentation instrumentation) {
if (!instrumentation.isRetransformClassesSupported()) {
System.out.println("Class retransformation is not supported.");
return;
}
System.out.println("Calling lambda to ensure that lambda forms were created");
Agent.lambda.run();
System.out.println("Registering class file transformer");
instrumentation.addTransformer(new Agent());
for (Class c : instrumentation.getAllLoadedClasses()) {
if (c.getName().contains("LambdaForm") &&
instrumentation.isModifiableClass(c)) {
System.out.format("We've found a modifiable lambda form: %s%n", c.getName());
try {
instrumentation.retransformClasses(c);
} catch (UnmodifiableClassException e) {
throw new AssertionError("Modification of modifiable class " +
"caused UnmodifiableClassException", e);
}
}
}
}
private static void reloadClasses(Instrumentation inst) {
for (Class<?> loadedClass : inst.getAllLoadedClasses()) {
if (Transformer.needsTransform(loadedClass.getName())) {
try {
inst.retransformClasses(loadedClass);
} catch (Throwable e) {
log.log(Level.WARNING, "Failed instrumenting " + loadedClass.getName() + ". Shared secret extraction might fail.", e);
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
return;
}
throw new IllegalStateException(e);
}
}
}
}
/**
* Ensures that the given sampler will be invoked every time a constructor for class c is invoked.
*
* @param c The class to be tracked
* @param sampler the code to be invoked when an instance of c is constructed
* @throws UnmodifiableClassException if c cannot be modified.
*/
public static void instrumentClass(Class<?> c, ConstructorCallback<?> sampler)
throws UnmodifiableClassException {
// IMPORTANT: Don't forget that other threads may be accessing this
// class while this code is running. Specifically, the class may be
// executed directly after the retransformClasses is called. Thus, we need
// to be careful about what happens after the retransformClasses call.
synchronized (samplerPutAtomicityLock) {
List<ConstructorCallback<?>> list = samplerMap.get(c);
if (list == null) {
CopyOnWriteArrayList<ConstructorCallback<?>> samplerList =
new CopyOnWriteArrayList<ConstructorCallback<?>>();
samplerList.add(sampler);
samplerMap.put(c, samplerList);
Instrumentation inst = AllocationRecorder.getInstrumentation();
Class<?>[] cs = new Class<?>[1];
cs[0] = c;
inst.retransformClasses(c);
} else {
list.add(sampler);
}
}
}
public static void enhance(Instrumentation inst, ClassFileTransformer transformer, Set<Class<?>> classes)
throws UnmodifiableClassException {
try {
inst.addTransformer(transformer, true);
int size = classes.size();
Class<?>[] classArray = new Class<?>[size];
arraycopy(classes.toArray(), 0, classArray, 0, size);
if (classArray.length > 0) {
inst.retransformClasses(classArray);
}
} finally {
inst.removeTransformer(transformer);
}
}
private static void reloadClass(Class seleClass) throws Exception {
if (!isLoaded) {
startUp();
}
Instrumentation inst = instrumentation();
inst.retransformClasses(seleClass);
}
public synchronized static Map<String, Object> removeDebugClassByTraceId(String traceId,boolean isForce) throws NotFoundException {
String className = null;
logger.debug("ready remove "+traceId);
Map<String, Object> rtn = DebugTool.removeTraceInfo(traceId);
for (Map.Entry<String, DebugInfo> entry : debugClassInfos.entrySet()) {
if (traceId.equals(entry.getValue().getTraceId())) {
className = entry.getKey();
break;
}
}
if (className == null) {
throw new NotFoundException("no debug class found by traceid "+traceId);
}
if(rtn != null || isForce) {
try {
Class seleClass = Class.forName(className.replace('/', '.'));
debugClassInfos.remove(className);
needRecoverClasses.put(className, needDebugClasses.remove(className));
Instrumentation inst = instrumentation();
inst.retransformClasses(seleClass);
} catch (Throwable e) {
logger.error("recover debug class failed!", e);
}
}
return rtn;
}
public static void agentmain(@SuppressWarnings("unused") String args, Instrumentation inst) throws Exception {
if (inst.isRedefineClassesSupported() && inst.isRetransformClassesSupported()) {
inst.addTransformer(new Redefiner(), true);
Class<?>[] allClasses = inst.getAllLoadedClasses();
for (int i = 0; i < allClasses.length; i++) {
Class<?> c = allClasses[i];
if (c == Intrinsic.class) {
inst.retransformClasses(new Class<?>[]{c});
}
}
}
}
public static void premain(String agentArgs, Instrumentation inst) throws Exception {
LoggingTransformer t = new LoggingTransformer();
inst.addTransformer(t, true);
{
Class demoClass = Class.forName("RedefineLeak$Tester");
for (int i = 0; i < 10000; i++) {
inst.retransformClasses(demoClass);
}
}
System.gc();
}
public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
try {
instrumentation.retransformClasses(to_redefine);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
try {
instrumentation.retransformClasses(to_redefine);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void agentmain(@SuppressWarnings("unused") String args, Instrumentation inst) throws Exception {
if (inst.isRedefineClassesSupported() && inst.isRetransformClassesSupported()) {
inst.addTransformer(new FooTransformer(), true);
Class<?>[] allClasses = inst.getAllLoadedClasses();
for (int i = 0; i < allClasses.length; i++) {
Class<?> c = allClasses[i];
if (c == Foo.class) {
inst.retransformClasses(new Class<?>[]{c});
}
}
}
}
private static void transform(Class<?> clazz, ClassLoader classLoader, Instrumentation instrumentation) {
AtmTransformer dt = new AtmTransformer(clazz.getName(), classLoader);
instrumentation.addTransformer(dt, true);
try {
instrumentation.retransformClasses(clazz);
} catch (Exception ex) {
throw new RuntimeException("Transform failed for class: [" + clazz.getName() + "]", ex);
}
}
/**
* 对象增强
*
* @param inst inst
* @param adviceId 通知ID
* @param isTracing 可跟踪方法调用
* @param skipJDKTrace 是否忽略对JDK内部方法的跟踪
* @param classNameMatcher 类名匹配
* @param methodNameMatcher 方法名匹配
* @return 增强影响范围
* @throws UnmodifiableClassException 增强失败
*/
public static synchronized EnhancerAffect enhance(
final Instrumentation inst,
final int adviceId,
final boolean isTracing,
final boolean skipJDKTrace,
final Matcher classNameMatcher,
final Matcher methodNameMatcher) throws UnmodifiableClassException {
final EnhancerAffect affect = new EnhancerAffect();
// 获取需要增强的类集合
final Set<Class<?>> enhanceClassSet = GlobalOptions.isDisableSubClass
? SearchUtils.searchClass(inst, classNameMatcher)
: SearchUtils.searchSubClass(inst, SearchUtils.searchClass(inst, classNameMatcher));
// 过滤掉无法被增强的类
filter(enhanceClassSet);
// 构建增强器
final Enhancer enhancer = new Enhancer(adviceId, isTracing, skipJDKTrace, enhanceClassSet, methodNameMatcher, affect);
try {
inst.addTransformer(enhancer, true);
// 批量增强
if (GlobalOptions.isBatchReTransform) {
final int size = enhanceClassSet.size();
final Class<?>[] classArray = new Class<?>[size];
arraycopy(enhanceClassSet.toArray(), 0, classArray, 0, size);
if (classArray.length > 0) {
inst.retransformClasses(classArray);
logger.info("Success to batch transform classes: " + Arrays.toString(classArray));
}
} else {
// for each 增强
for (Class<?> clazz : enhanceClassSet) {
try {
inst.retransformClasses(clazz);
logger.info("Success to transform class: " + clazz);
} catch (Throwable t) {
logger.warn("retransform {} failed.", clazz, t);
if (t instanceof UnmodifiableClassException) {
throw (UnmodifiableClassException) t;
} else if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new RuntimeException(t);
}
}
}
}
} finally {
inst.removeTransformer(enhancer);
}
return affect;
}
/**
* 对象增强
*
* @param inst inst
* @param adviceId 通知ID
* @param isTracing 可跟踪方法调用
* @param skipJDKTrace 是否忽略对JDK内部方法的跟踪
* @param classNameMatcher 类名匹配
* @param methodNameMatcher 方法名匹配
* @return 增强影响范围
* @throws UnmodifiableClassException 增强失败
*/
public synchronized EnhancerAffect enhance(final Instrumentation inst) throws UnmodifiableClassException {
// 获取需要增强的类集合
this.matchingClasses = GlobalOptions.isDisableSubClass
? SearchUtils.searchClass(inst, classNameMatcher)
: SearchUtils.searchSubClass(inst, SearchUtils.searchClass(inst, classNameMatcher));
// 过滤掉无法被增强的类
filter(matchingClasses);
logger.info("enhance matched classes: {}", matchingClasses);
affect.setTransformer(this);
try {
ArthasBootstrap.getInstance().getTransformerManager().addTransformer(this, isTracing);
// 批量增强
if (GlobalOptions.isBatchReTransform) {
final int size = matchingClasses.size();
final Class<?>[] classArray = new Class<?>[size];
arraycopy(matchingClasses.toArray(), 0, classArray, 0, size);
if (classArray.length > 0) {
inst.retransformClasses(classArray);
logger.info("Success to batch transform classes: " + Arrays.toString(classArray));
}
} else {
// for each 增强
for (Class<?> clazz : matchingClasses) {
try {
inst.retransformClasses(clazz);
logger.info("Success to transform class: " + clazz);
} catch (Throwable t) {
logger.warn("retransform {} failed.", clazz, t);
if (t instanceof UnmodifiableClassException) {
throw (UnmodifiableClassException) t;
} else if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new RuntimeException(t);
}
}
}
}
} catch (Throwable e) {
logger.error("Enhancer error, matchingClasses: {}", matchingClasses, e);
affect.setThrowable(e);
}
return affect;
}
protected void retransformClasses(Instrumentation instrumentation, Set<String> ownPackages) {
log.info("Re-transforming existing classes...");
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
for (Class<?> clazz : instrumentation.getAllLoadedClasses()) {
String className = clazz.getName();
if (instrumentation.isModifiableClass(clazz)) {
if (isClassLoaderParent(systemClassLoader, clazz.getClassLoader())) {
if (log.isTraceEnabled()) {
log.trace("Skip re-transforming boot or extension/platform class: " + className);
}
continue;
}
boolean isOwnClass = false;
for (String ownPackage : ownPackages) {
if (className.startsWith(ownPackage)) {
isOwnClass = true;
break;
}
}
if (isOwnClass) {
if (log.isDebugEnabled()) {
log.debug("Skip re-transforming class (agent class): " + className);
}
continue;
}
if (log.isDebugEnabled()) {
log.debug("Re-transforming class: " + className);
}
try {
instrumentation.retransformClasses(clazz);
} catch (Throwable e) {
log.error("Error re-transofrming class "+ className, e);
}
} else {
if (log.isDebugEnabled()) {
log.debug("Non-modifiable class (re-transforming skipped): " + className);
}
}
}
log.info("Existing classes was re-transormed");
}