Skip to content

Commit

Permalink
[3.3] Optimized Wrapper#getWrapper and some unit tests (#15164)
Browse files Browse the repository at this point in the history
* Optimized getWrapper of bytecode Wrapper

* Destroyed all framework model before each test of ReplierDispatcherTest

* Un-exported service config of ServiceConfigTest and ReferenceConfigTest

* Shutdown executor after each test of EagerThreadPoolExecutorTest

* Shutdown executor after each test of AbortPolicyWithReportTest

* Destroyed all framework model before each test of NettyClientTest

* Destroyed all framework model before each test of ApolloDynamicConfigurationTest

* Using available port to avoid address already in use issue at AnnotationIsolationTest
  • Loading branch information
zrlw authored Mar 3, 2025
1 parent 403e127 commit dfc6f3c
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 193 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,17 @@ public Object invokeMethod(Object instance, String mn, Class<?>[] types, Object[
* @return Wrapper instance(not null).
*/
public static Wrapper getWrapper(Class<?> c) {
while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class.
{
c = c.getSuperclass();
}

if (c == Object.class) {
return OBJECT_WRAPPER;
}
return ConcurrentHashMapUtils.computeIfAbsent(WRAPPER_MAP, c, (clazz) -> {
while (ClassGenerator.isDynamicClass(clazz)) // can not wrapper on dynamic class.
{
clazz = clazz.getSuperclass();
}

return ConcurrentHashMapUtils.computeIfAbsent(WRAPPER_MAP, c, Wrapper::makeWrapper);
if (clazz == Object.class) {
return OBJECT_WRAPPER;
}
return makeWrapper(clazz);
});
}

private static Wrapper makeWrapper(Class<?> c) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ protected void jstack(FileOutputStream jStackStream) {

await().until(() -> AbortPolicyWithReport.guard.availablePermits() == 1);
Assertions.assertNotNull(fileOutputStream.get());
executorService.shutdown();
}

@Test
Expand Down Expand Up @@ -128,6 +129,7 @@ protected void jstack(FileOutputStream jStackStream) {
Assertions.assertEquals(
runTimes, finishedCount.get() + failureCount.get(), "all the test thread should be run completely");
Assertions.assertEquals(1, jStackCount.get(), "'jstack' should be called only once in 10 minutes");
threadPoolExecutor.shutdown();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ void testEagerThreadPool() throws Exception {
Thread.sleep(5000);
// cores theads are all alive.
Assertions.assertEquals(executor.getPoolSize(), cores, "more than cores threads alive!");

executor.shutdown();
}

@Test
Expand Down Expand Up @@ -163,6 +165,8 @@ void testEagerThreadPoolFast() {
await().until(() -> executor.getActiveCount() == 0);

await().until(() -> executor.getPoolSize() == cores);

executor.shutdown();
}

@Test
Expand Down Expand Up @@ -218,6 +222,8 @@ void testEagerThreadPool_rejectExecution1() {
await().until(() -> executor.getActiveCount() == 0);

executor.execute(runnable);

executor.shutdown();
}

@Test
Expand Down Expand Up @@ -273,5 +279,7 @@ public boolean retryOffer(Runnable o, long timeout, TimeUnit unit) throws Interr
executor.execute(runnable);
semaphore.release(5);
await().until(() -> executor.getActiveCount() == 0);

executor.shutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1001,73 +1001,77 @@ void testDifferentClassLoader() throws Exception {

DemoService demoService = new DemoServiceImpl();
ServiceConfig<DemoService> serviceConfig = new ServiceConfig<>();
serviceConfig.setInterface(DemoService.class);
serviceConfig.setRegistry(new RegistryConfig(zkUrl1));
serviceConfig.setScopeModel(moduleModel);
serviceConfig.setRef(demoService);
serviceConfig.export();

String basePath = DemoService.class
.getProtectionDomain()
.getCodeSource()
.getLocation()
.getFile();
basePath = URLDecoder.decode(basePath, "UTF-8");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
TestClassLoader classLoader1 = new TestClassLoader(classLoader, basePath);
TestClassLoader classLoader2 = new TestClassLoader(classLoader, basePath);

Class<?> class1 = classLoader1.loadClass(DemoService.class.getName(), false);
Class<?> class2 = classLoader2.loadClass(DemoService.class.getName(), false);

Assertions.assertNotEquals(class1, class2);

ReferenceConfig<DemoService> referenceConfig1 = new ReferenceConfig<>();
referenceConfig1.setInterface(class1);
referenceConfig1.setRegistry(new RegistryConfig(zkUrl1));
referenceConfig1.setScopeModel(moduleModel);
referenceConfig1.setScope("remote");
Object demoService1 = referenceConfig1.get();

for (Class<?> anInterface : demoService1.getClass().getInterfaces()) {
Assertions.assertNotEquals(DemoService.class, anInterface);
}
Assertions.assertTrue(Arrays.stream(demoService1.getClass().getInterfaces())
.anyMatch((clazz) -> clazz.getClassLoader().equals(classLoader1)));
try {
serviceConfig.setInterface(DemoService.class);
serviceConfig.setRegistry(new RegistryConfig(zkUrl1));
serviceConfig.setScopeModel(moduleModel);
serviceConfig.setRef(demoService);
serviceConfig.export();

String basePath = DemoService.class
.getProtectionDomain()
.getCodeSource()
.getLocation()
.getFile();
basePath = URLDecoder.decode(basePath, "UTF-8");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
TestClassLoader classLoader1 = new TestClassLoader(classLoader, basePath);
TestClassLoader classLoader2 = new TestClassLoader(classLoader, basePath);

Class<?> class1 = classLoader1.loadClass(DemoService.class.getName(), false);
Class<?> class2 = classLoader2.loadClass(DemoService.class.getName(), false);

Assertions.assertNotEquals(class1, class2);

ReferenceConfig<DemoService> referenceConfig1 = new ReferenceConfig<>();
referenceConfig1.setInterface(class1);
referenceConfig1.setRegistry(new RegistryConfig(zkUrl1));
referenceConfig1.setScopeModel(moduleModel);
referenceConfig1.setScope("remote");
Object demoService1 = referenceConfig1.get();

for (Class<?> anInterface : demoService1.getClass().getInterfaces()) {
Assertions.assertNotEquals(DemoService.class, anInterface);
}
Assertions.assertTrue(Arrays.stream(demoService1.getClass().getInterfaces())
.anyMatch((clazz) -> clazz.getClassLoader().equals(classLoader1)));

java.lang.reflect.Method callBean1 = demoService1.getClass().getDeclaredMethod("callInnerClass");
callBean1.setAccessible(true);
Object result1 = callBean1.invoke(demoService1);
java.lang.reflect.Method callBean1 = demoService1.getClass().getDeclaredMethod("callInnerClass");
callBean1.setAccessible(true);
Object result1 = callBean1.invoke(demoService1);

Assertions.assertNotEquals(result1.getClass(), DemoService.InnerClass.class);
Assertions.assertEquals(classLoader1, result1.getClass().getClassLoader());
Assertions.assertNotEquals(result1.getClass(), DemoService.InnerClass.class);
Assertions.assertEquals(classLoader1, result1.getClass().getClassLoader());

ReferenceConfig<DemoService> referenceConfig2 = new ReferenceConfig<>();
referenceConfig2.setInterface(class2);
referenceConfig2.setRegistry(new RegistryConfig(zkUrl1));
referenceConfig2.setScopeModel(moduleModel);
referenceConfig2.setScope("remote");
Object demoService2 = referenceConfig2.get();
ReferenceConfig<DemoService> referenceConfig2 = new ReferenceConfig<>();
referenceConfig2.setInterface(class2);
referenceConfig2.setRegistry(new RegistryConfig(zkUrl1));
referenceConfig2.setScopeModel(moduleModel);
referenceConfig2.setScope("remote");
Object demoService2 = referenceConfig2.get();

for (Class<?> anInterface : demoService2.getClass().getInterfaces()) {
Assertions.assertNotEquals(DemoService.class, anInterface);
for (Class<?> anInterface : demoService2.getClass().getInterfaces()) {
Assertions.assertNotEquals(DemoService.class, anInterface);
}
Assertions.assertTrue(Arrays.stream(demoService2.getClass().getInterfaces())
.anyMatch((clazz) -> clazz.getClassLoader().equals(classLoader2)));

java.lang.reflect.Method callBean2 = demoService2.getClass().getDeclaredMethod("callInnerClass");
callBean2.setAccessible(true);
Object result2 = callBean2.invoke(demoService2);

Assertions.assertNotEquals(callBean1, callBean2);
Assertions.assertNotEquals(result2.getClass(), DemoService.InnerClass.class);
Assertions.assertEquals(classLoader2, result2.getClass().getClassLoader());
Assertions.assertNotEquals(result1.getClass(), result2.getClass());

applicationModel.destroy();
DubboBootstrap.getInstance().destroy();
Thread.currentThread().setContextClassLoader(classLoader);
Thread.currentThread().getContextClassLoader().loadClass(DemoService.class.getName());
} finally {
serviceConfig.unexport();
}
Assertions.assertTrue(Arrays.stream(demoService2.getClass().getInterfaces())
.anyMatch((clazz) -> clazz.getClassLoader().equals(classLoader2)));

java.lang.reflect.Method callBean2 = demoService2.getClass().getDeclaredMethod("callInnerClass");
callBean2.setAccessible(true);
Object result2 = callBean2.invoke(demoService2);

Assertions.assertNotEquals(callBean1, callBean2);
Assertions.assertNotEquals(result2.getClass(), DemoService.InnerClass.class);
Assertions.assertEquals(classLoader2, result2.getClass().getClassLoader());
Assertions.assertNotEquals(result1.getClass(), result2.getClass());

applicationModel.destroy();
DubboBootstrap.getInstance().destroy();
Thread.currentThread().setContextClassLoader(classLoader);
Thread.currentThread().getContextClassLoader().loadClass(DemoService.class.getName());
}

@Test
Expand Down Expand Up @@ -1103,47 +1107,52 @@ public void testDifferentClassLoaderRequest() throws Exception {
clazz1impl.getDeclaredConstructor(AtomicReference.class, AtomicReference.class);

ServiceConfig serviceConfig = new ServiceConfig<>();
serviceConfig.setInterfaceClassLoader(classLoader1);
serviceConfig.setInterface(clazz1);
serviceConfig.setRegistry(new RegistryConfig(zkUrl1));
serviceConfig.setScopeModel(moduleModel);
serviceConfig.setRef(declaredConstructor.newInstance(innerRequestReference, innerResultReference));
serviceConfig.export();

Class<?> clazz2 = classLoader2.loadClass(MultiClassLoaderService.class.getName(), false);
Class<?> requestClazzOrigin = classLoader2.loadClass(MultiClassLoaderServiceRequest.class.getName(), false);
Class<?> requestClazzCustom2 = compileCustomRequest(classLoader2);
Class<?> resultClazzCustom3 = compileCustomResult(classLoader3);
classLoader2.loadedClass.put(requestClazzCustom2.getName(), requestClazzCustom2);
classLoader3.loadedClass.put(resultClazzCustom3.getName(), resultClazzCustom3);

ReferenceConfig<DemoService> referenceConfig1 = new ReferenceConfig<>();
referenceConfig1.setInterface(clazz2);
referenceConfig1.setInterfaceClassLoader(classLoader3);
referenceConfig1.setRegistry(new RegistryConfig(zkUrl1));
referenceConfig1.setScopeModel(moduleModel);
referenceConfig1.setScope("remote");
referenceConfig1.setTimeout(30000);
Object object1 = referenceConfig1.get();

java.lang.reflect.Method callBean1 = object1.getClass().getDeclaredMethod("call", requestClazzOrigin);
callBean1.setAccessible(true);
Object result1 = callBean1.invoke(
object1, requestClazzCustom2.getDeclaredConstructor().newInstance());

Assertions.assertEquals(resultClazzCustom3, result1.getClass());
Assertions.assertNotEquals(classLoader2, result1.getClass().getClassLoader());
Assertions.assertEquals(
classLoader1, innerRequestReference.get().getClass().getClassLoader());

Thread.currentThread().setContextClassLoader(classLoader1);
callBean1.invoke(object1, requestClazzCustom2.getDeclaredConstructor().newInstance());
Assertions.assertEquals(classLoader1, Thread.currentThread().getContextClassLoader());

applicationModel.destroy();
DubboBootstrap.getInstance().destroy();
Thread.currentThread().setContextClassLoader(classLoader);
Thread.currentThread().getContextClassLoader().loadClass(DemoService.class.getName());
try {
serviceConfig.setInterfaceClassLoader(classLoader1);
serviceConfig.setInterface(clazz1);
serviceConfig.setRegistry(new RegistryConfig(zkUrl1));
serviceConfig.setScopeModel(moduleModel);
serviceConfig.setRef(declaredConstructor.newInstance(innerRequestReference, innerResultReference));
serviceConfig.export();

Class<?> clazz2 = classLoader2.loadClass(MultiClassLoaderService.class.getName(), false);
Class<?> requestClazzOrigin = classLoader2.loadClass(MultiClassLoaderServiceRequest.class.getName(), false);
Class<?> requestClazzCustom2 = compileCustomRequest(classLoader2);
Class<?> resultClazzCustom3 = compileCustomResult(classLoader3);
classLoader2.loadedClass.put(requestClazzCustom2.getName(), requestClazzCustom2);
classLoader3.loadedClass.put(resultClazzCustom3.getName(), resultClazzCustom3);

ReferenceConfig<DemoService> referenceConfig1 = new ReferenceConfig<>();
referenceConfig1.setInterface(clazz2);
referenceConfig1.setInterfaceClassLoader(classLoader3);
referenceConfig1.setRegistry(new RegistryConfig(zkUrl1));
referenceConfig1.setScopeModel(moduleModel);
referenceConfig1.setScope("remote");
referenceConfig1.setTimeout(30000);
Object object1 = referenceConfig1.get();

java.lang.reflect.Method callBean1 = object1.getClass().getDeclaredMethod("call", requestClazzOrigin);
callBean1.setAccessible(true);
Object result1 = callBean1.invoke(
object1, requestClazzCustom2.getDeclaredConstructor().newInstance());

Assertions.assertEquals(resultClazzCustom3, result1.getClass());
Assertions.assertNotEquals(classLoader2, result1.getClass().getClassLoader());
Assertions.assertEquals(
classLoader1, innerRequestReference.get().getClass().getClassLoader());

Thread.currentThread().setContextClassLoader(classLoader1);
callBean1.invoke(
object1, requestClazzCustom2.getDeclaredConstructor().newInstance());
Assertions.assertEquals(classLoader1, Thread.currentThread().getContextClassLoader());

applicationModel.destroy();
DubboBootstrap.getInstance().destroy();
Thread.currentThread().setContextClassLoader(classLoader);
Thread.currentThread().getContextClassLoader().loadClass(DemoService.class.getName());
} finally {
serviceConfig.unexport();
}
}

@Test
Expand All @@ -1157,26 +1166,30 @@ void testClassLoader() {
Thread.currentThread().setContextClassLoader(classLoader);

ServiceConfig<DemoService> serviceConfig = new ServiceConfig<>(applicationModel.newModule());
serviceConfig.setInterface(DemoService.class);
serviceConfig.setProtocol(new ProtocolConfig("dubbo", -1));
serviceConfig.setRegistry(new RegistryConfig("N/A"));
serviceConfig.setRef(new DemoServiceImpl());
serviceConfig.export();

ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>(applicationModel.newModule());
referenceConfig.setInterface(DemoService.class);
referenceConfig.setRegistry(new RegistryConfig("N/A"));
DemoService demoService = referenceConfig.get();

demoService.sayName("Dubbo");
Assertions.assertEquals(classLoader, Thread.currentThread().getContextClassLoader());

Thread.currentThread().setContextClassLoader(null);
demoService.sayName("Dubbo");
Assertions.assertNull(Thread.currentThread().getContextClassLoader());

Thread.currentThread().setContextClassLoader(originClassLoader);
frameworkModel.destroy();
try {
serviceConfig.setInterface(DemoService.class);
serviceConfig.setProtocol(new ProtocolConfig("dubbo", -1));
serviceConfig.setRegistry(new RegistryConfig("N/A"));
serviceConfig.setRef(new DemoServiceImpl());
serviceConfig.export();

ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>(applicationModel.newModule());
referenceConfig.setInterface(DemoService.class);
referenceConfig.setRegistry(new RegistryConfig("N/A"));
DemoService demoService = referenceConfig.get();

demoService.sayName("Dubbo");
Assertions.assertEquals(classLoader, Thread.currentThread().getContextClassLoader());

Thread.currentThread().setContextClassLoader(null);
demoService.sayName("Dubbo");
Assertions.assertNull(Thread.currentThread().getContextClassLoader());

Thread.currentThread().setContextClassLoader(originClassLoader);
frameworkModel.destroy();
} finally {
serviceConfig.unexport();
}
}

private Class<?> compileCustomRequest(ClassLoader classLoader) throws NotFoundException, CannotCompileException {
Expand Down
Loading

0 comments on commit dfc6f3c

Please sign in to comment.