diff --git a/pom.xml b/pom.xml index d047a4602..1b6cc29e2 100644 --- a/pom.xml +++ b/pom.xml @@ -267,7 +267,7 @@ --> com.alibaba.ttl.threadpool.agent.TtlAgent ${project.artifactId}-${project.version}.jar - false + true true false diff --git a/pom4ide.xml b/pom4ide.xml index 7ad45ea9a..b421882dc 100644 --- a/pom4ide.xml +++ b/pom4ide.xml @@ -267,7 +267,7 @@ --> com.alibaba.ttl.threadpool.agent.TtlAgent ${project.artifactId}-${project.version}.jar - false + true true false diff --git a/src/main/java/com/alibaba/ttl/threadpool/agent/TtlAgent.java b/src/main/java/com/alibaba/ttl/threadpool/agent/TtlAgent.java index 67c7cce64..7be727ad9 100644 --- a/src/main/java/com/alibaba/ttl/threadpool/agent/TtlAgent.java +++ b/src/main/java/com/alibaba/ttl/threadpool/agent/TtlAgent.java @@ -1,5 +1,6 @@ package com.alibaba.ttl.threadpool.agent; +import com.alibaba.ttl.spi.TtlEnhanced; import com.alibaba.ttl.threadpool.agent.internal.logging.Logger; import com.alibaba.ttl.threadpool.agent.internal.transformlet.JavassistTransformlet; import com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.TtlExecutorTransformlet; @@ -143,6 +144,17 @@ public static void premain(final String agentArgs, @NonNull final Instrumentatio logger.info("[TtlAgent.premain] end"); + if (isRetransformLoadedClasses() && inst.isRetransformClassesSupported()) { + for (Class clazz : inst.getAllLoadedClasses()) { + if (!inst.isModifiableClass(clazz)) continue; + if (clazz.isAssignableFrom(TtlEnhanced.class)) continue; + if (clazz.isPrimitive() || clazz.isArray() || clazz.isInterface() || clazz.isAnnotation()) continue; + + logger.info("retransform class: " + clazz); + inst.retransformClasses(clazz); + } + } + ttlAgentLoaded = true; } catch (Exception e) { String msg = "Fail to load TtlAgent , cause: " + e.toString(); @@ -168,10 +180,21 @@ public static boolean isTtlAgentLoaded() { return ttlAgentLoaded; } + private static final String TTL_AGENT_RETRANSFORM_LOADED_CLASSES_KEY = "ttl.agent.retransform.loaded.classes"; + private static final String TTL_AGENT_ENABLE_TIMER_TASK_KEY = "ttl.agent.enable.timer.task"; private static final String TTL_AGENT_DISABLE_INHERITABLE_FOR_THREAD_POOL = "ttl.agent.disable.inheritable.for.thread.pool"; + /** + * Whether timer task is enhanced by ttl agent, check {@link #isTtlAgentLoaded()} first. + * + * @since 2.13.0 + */ + public static boolean isRetransformLoadedClasses() { + return isBooleanOptionSet(kvs, TTL_AGENT_RETRANSFORM_LOADED_CLASSES_KEY, true); + } + /** * Whether disable inheritable for thread pool is enhanced by ttl agent, check {@link #isTtlAgentLoaded()} first. * diff --git a/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/TtlAgentEnhanced.java b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/TtlAgentEnhanced.java new file mode 100644 index 000000000..27cb28c75 --- /dev/null +++ b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/TtlAgentEnhanced.java @@ -0,0 +1,15 @@ +package com.alibaba.ttl.threadpool.agent.internal.transformlet; + +/** + * a Ttl marker/tag interface, for ttl enhanced class by {@link com.alibaba.ttl.threadpool.agent.TtlAgent} + * + * @author Jerry Lee (oldratlee at gmail dot com) + * @see com.alibaba.ttl.threadpool.agent.TtlAgent + * @see com.alibaba.ttl.threadpool.agent.internal.transformlet.JavassistTransformlet + * @see com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.TtlExecutorTransformlet + * @see com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.TtlForkJoinTransformlet + * @see com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.TtlTimerTaskTransformlet + * @since 2.13.0 + */ +public interface TtlAgentEnhanced { +} diff --git a/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlExecutorTransformlet.java b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlExecutorTransformlet.java index 3493a6373..472b010b2 100644 --- a/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlExecutorTransformlet.java +++ b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlExecutorTransformlet.java @@ -16,6 +16,7 @@ import java.util.Set; import java.util.concurrent.Callable; +import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.addTtlAgentEnhancedInterfaceForClass; import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.signatureOfMethod; /** @@ -59,6 +60,8 @@ public TtlExecutorTransformlet(boolean disableInheritableForThreadPool) { public void doTransform(@NonNull final ClassInfo classInfo) throws IOException, NotFoundException, CannotCompileException { final CtClass clazz = classInfo.getCtClass(); if (EXECUTOR_CLASS_NAMES.contains(classInfo.getClassName())) { + if (!addTtlAgentEnhancedInterfaceForClass(classInfo)) return; + for (CtMethod method : clazz.getDeclaredMethods()) { updateSubmitMethodsOfExecutorClass_decorateToTtlWrapperAndSetAutoWrapperAttachment(method); } @@ -72,6 +75,8 @@ public void doTransform(@NonNull final ClassInfo classInfo) throws IOException, } if (!clazz.subclassOf(clazz.getClassPool().get(THREAD_POOL_EXECUTOR_CLASS_NAME))) return; + if (!addTtlAgentEnhancedInterfaceForClass(classInfo)) return; + logger.info("Transforming class " + classInfo.getClassName()); final boolean modified = updateBeforeAndAfterExecuteMethodOfExecutorSubclass(clazz); diff --git a/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlForkJoinTransformlet.java b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlForkJoinTransformlet.java index 3ec7a6ab5..6798a63a6 100644 --- a/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlForkJoinTransformlet.java +++ b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlForkJoinTransformlet.java @@ -36,9 +36,13 @@ public TtlForkJoinTransformlet(boolean disableInheritableForThreadPool) { @Override public void doTransform(@NonNull final ClassInfo classInfo) throws IOException, NotFoundException, CannotCompileException { if (FORK_JOIN_TASK_CLASS_NAME.equals(classInfo.getClassName())) { + if (!addTtlAgentEnhancedInterfaceForClass(classInfo)) return; + updateForkJoinTaskClass(classInfo.getCtClass()); classInfo.setModified(); } else if (disableInheritableForThreadPool && FORK_JOIN_POOL_CLASS_NAME.equals(classInfo.getClassName())) { + if (!addTtlAgentEnhancedInterfaceForClass(classInfo)) return; + updateConstructorDisableInheritable(classInfo.getCtClass()); classInfo.setModified(); } diff --git a/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlTimerTaskTransformlet.java b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlTimerTaskTransformlet.java index f9f9b3f3b..e69bc85b1 100644 --- a/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlTimerTaskTransformlet.java +++ b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/TtlTimerTaskTransformlet.java @@ -8,6 +8,7 @@ import java.io.IOException; +import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.addTtlAgentEnhancedInterfaceForClass; import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.doTryFinallyForMethod; /** @@ -43,6 +44,8 @@ public void doTransform(@NonNull final ClassInfo classInfo) throws IOException, } if (!clazz.subclassOf(clazz.getClassPool().get(TIMER_TASK_CLASS_NAME))) return; + if (!addTtlAgentEnhancedInterfaceForClass(classInfo)) return; + logger.info("Transforming class " + classInfo.getClassName()); updateTimerTaskClass(clazz); diff --git a/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/Utils.java b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/Utils.java index 0203f6c61..629cd1a37 100644 --- a/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/Utils.java +++ b/src/main/java/com/alibaba/ttl/threadpool/agent/internal/transformlet/impl/Utils.java @@ -1,13 +1,16 @@ package com.alibaba.ttl.threadpool.agent.internal.transformlet.impl; import com.alibaba.ttl.TtlRunnable; +import com.alibaba.ttl.threadpool.agent.internal.transformlet.TtlAgentEnhanced; import com.alibaba.ttl.spi.TtlAttachments; import com.alibaba.ttl.spi.TtlEnhanced; import com.alibaba.ttl.threadpool.agent.internal.logging.Logger; +import com.alibaba.ttl.threadpool.agent.internal.transformlet.ClassInfo; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import javassist.*; +import java.io.IOException; import java.lang.reflect.Modifier; import static com.alibaba.ttl.TransmittableThreadLocal.Transmitter.capture; @@ -116,4 +119,15 @@ private static boolean isAutoWrapper(@Nullable Runnable ttlAttachments) { return value; } + + public static boolean addTtlAgentEnhancedInterfaceForClass(ClassInfo classInfo) throws NotFoundException, IOException { + final CtClass clazz = classInfo.getCtClass(); + final CtClass ttlAgentEnhancedClass = clazz.getClassPool().get(TtlAgentEnhanced.class.getName()); + + if (clazz.subclassOf(ttlAgentEnhancedClass)) return false; + + clazz.addInterface(ttlAgentEnhancedClass); + classInfo.setModified(); + return true; + } }