Skip to content

Commit

Permalink
fix: work-around ClassCircularityError:
Browse files Browse the repository at this point in the history
  • Loading branch information
oldratlee committed Dec 18, 2021
1 parent 3db9753 commit c55acbd
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 8 deletions.
4 changes: 2 additions & 2 deletions scripts/run-agent-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ logAndRun "${JAVA_CMD[@]}" -cp "$(getClasspathWithoutTtlJar)" \
blueEcho 'Run agent check for Timer/TimerTask, default "ttl.agent.enable.timer.task"'
logAndRun "${JAVA_CMD[@]}" -cp "$(getClasspathWithoutTtlJar)" \
"-javaagent:$(getTtlJarPath)=ttl.agent.logger:STDOUT" \
com.alibaba.ttl.threadpool.agent.check.timer.TimerAgentCheck
com.alibaba.test.ttl.threadpool.agent.check.timer.TimerAgentCheck

blueEcho 'Run agent check for Timer/TimerTask, explicit "ttl.agent.enable.timer.task"'
logAndRun "${JAVA_CMD[@]}" -cp "$(getClasspathWithoutTtlJar)" \
"-javaagent:$(getTtlJarPath)=ttl.agent.logger:STDOUT,ttl.agent.enable.timer.task:true" \
com.alibaba.ttl.threadpool.agent.check.timer.TimerAgentCheck
com.alibaba.test.ttl.threadpool.agent.check.timer.TimerAgentCheck
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.util.List;
import java.util.logging.Level;

import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.isClassUnderPackage;

/**
* TTL {@link ClassFileTransformer} of Java Agent
*
Expand Down Expand Up @@ -51,8 +53,10 @@ public final byte[] transform(@Nullable final ClassLoader loader, @Nullable fina
if (classFile == null) return NO_TRANSFORM;

final String className = toClassName(classFile);
if (isClassUnderPackage(className, "com.alibaba.ttl")) return NO_TRANSFORM;
if (isClassUnderPackage(className, "java.lang")) return NO_TRANSFORM;

ClassInfo classInfo = new ClassInfo(className, classFileBuffer, loader);
final ClassInfo classInfo = new ClassInfo(className, classFileBuffer, loader);

for (JavassistTransformlet transformlet : transformletList) {
transformlet.doTransform(classInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ public static void setLoggerImplType(String type) {
else loggerImplType = 0;
}

/**
* Only for test code
*/
public static void setLoggerImplTypeIfNotSetYet(String type) {
if (loggerImplType == -1) setLoggerImplType(type);
}

public static Logger getLogger(Class<?> clazz) {
if (loggerImplType == -1) throw new IllegalStateException("TTL logger implementation type is NOT set!");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.Set;
import java.util.concurrent.Callable;

import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.isClassAtPackageJavaUtil;
import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.signatureOfMethod;

/**
Expand Down Expand Up @@ -58,6 +59,11 @@ public TtlExecutorTransformlet(boolean disableInheritableForThreadPool) {

@Override
public void doTransform(@NonNull final ClassInfo classInfo) throws IOException, NotFoundException, CannotCompileException {
// work-around ClassCircularityError:
// https://github.com/alibaba/transmittable-thread-local/issues/278
// https://github.com/alibaba/transmittable-thread-local/issues/234
if (isClassAtPackageJavaUtil(classInfo.getClassName())) return;

final CtClass clazz = classInfo.getCtClass();
if (EXECUTOR_CLASS_NAMES.contains(classInfo.getClassName())) {
for (CtMethod method : clazz.getDeclaredMethods()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.io.IOException;

import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.doTryFinallyForMethod;
import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.isClassAtPackageJavaUtil;

/**
* TTL {@link JavassistTransformlet} for {@link java.util.TimerTask}.
Expand All @@ -27,7 +28,12 @@ public class TtlTimerTaskTransformlet implements JavassistTransformlet {

@Override
public void doTransform(@NonNull final ClassInfo classInfo) throws IOException, NotFoundException, CannotCompileException {
if (TIMER_TASK_CLASS_NAME.equals(classInfo.getClassName())) return; // No need transform TimerTask class
// work-around ClassCircularityError:
if (isClassAtPackageJavaUtil(classInfo.getClassName())) return;

// TimerTask class is checked by above logic.
//
// if (TIMER_TASK_CLASS_NAME.equals(classInfo.getClassName())) return; // No need transform TimerTask class

final CtClass clazz = classInfo.getCtClass();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,25 @@ private static boolean isAutoWrapper(@Nullable Runnable ttlAttachments) {

return value;
}

@NonNull
public static String getPackageName(@NonNull String className) {
final int idx = className.lastIndexOf('.');
if (-1 == idx) return "";

return className.substring(0, idx);
}

public static boolean isClassAtPackage(@NonNull String className, @NonNull String packageName) {
return packageName.equals(getPackageName(className));
}

public static boolean isClassUnderPackage(@NonNull String className, @NonNull String packageName) {
String packageOfClass = getPackageName(className);
return packageOfClass.equals(packageName) || packageOfClass.startsWith(packageName + ".");
}

public static boolean isClassAtPackageJavaUtil(@NonNull String className) {
return isClassAtPackage(className, "java.util");
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.alibaba.ttl.threadpool
@file:Suppress("PackageDirectoryMismatch")

// Change the package out of com.alibaba.ttl
// so agent will transform MyThreadPoolExecutor
package com.alibaba.test.ttl.threadpool

import com.alibaba.support.junit.conditional.ConditionalIgnoreRule
import com.alibaba.support.junit.conditional.ConditionalIgnoreRule.ConditionalIgnore
import com.alibaba.support.junit.conditional.IsAgentRun
import com.alibaba.support.junit.conditional.NoAgentRun
import com.alibaba.ttl.TtlRunnable
import com.alibaba.ttl.threadpool.TtlExecutors
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Rule
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@file:JvmName("TimerAgentCheck")
@file:Suppress("PackageDirectoryMismatch")

package com.alibaba.ttl.threadpool.agent.check.timer
package com.alibaba.test.ttl.threadpool.agent.check.timer

import com.alibaba.*
import com.alibaba.ttl.testmodel.Task
Expand Down Expand Up @@ -39,7 +40,7 @@ fun main() {

// child Inheritable
assertChildTtlValues(tag, task.copied)
// child do not effect parent
// child do not affect parent
assertParentTtlValues(copyTtlValues(ttlInstances))

printHead("TimerAgentCheck OK!")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package com.alibaba.ttl.threadpool.agent.internal.transformlet.impl;

import com.alibaba.ttl.threadpool.agent.internal.logging.Logger;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.fail;
import static com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.*;
import static org.junit.Assert.*;

public class UtilsTest {
@BeforeClass
public static void beforeClass() {
Logger.setLoggerImplTypeIfNotSetYet("stderr");
}

@Test
public void test_get_unboxing_boolean_fromMap() {
Map<String, Object> map = new HashMap<String, Object>();
Expand All @@ -23,4 +31,23 @@ public void test_get_unboxing_boolean_fromMap() {
private static boolean getUnboxingBoolean(Map<String, Object> map, String key) {
return (Boolean) map.get(key);
}

@Test
public void test_className_package() {
assertEquals("", getPackageName("Hello"));
assertEquals("com.foo", getPackageName("com.foo.Hello"));

assertTrue(isClassAtPackage("java.util.TimerTask", "java.util"));
assertFalse(isClassAtPackage("java.util.TimerTask", "java.utils"));
assertFalse(isClassAtPackage("java.util.TimerTask", "java"));
assertFalse(isClassAtPackage("java.util.TimerTask", "java.util.zip"));

assertTrue(isClassUnderPackage("java.util.TimerTask", "java.util"));
assertFalse(isClassUnderPackage("java.util.TimerTask", "java.utils"));
assertTrue(isClassUnderPackage("java.util.TimerTask", "java"));
assertFalse(isClassUnderPackage("java.util.TimerTask", "javax"));

assertTrue(isClassAtPackageJavaUtil("java.util.PriorityQueue"));
assertFalse(isClassAtPackageJavaUtil("java.util.zip.ZipInputStream"));
}
}

0 comments on commit c55acbd

Please sign in to comment.