|
33 | 33 | import java.util.ArrayList; |
34 | 34 | import java.util.List; |
35 | 35 | import java.util.Map; |
| 36 | +import java.util.WeakHashMap; |
36 | 37 | import java.util.concurrent.ConcurrentHashMap; |
37 | 38 | import lombok.experimental.UtilityClass; |
38 | 39 | import org.objectweb.asm.ClassWriter; |
|
62 | 63 | final class ClassInstrumentationUtil { |
63 | 64 |
|
64 | 65 | private static final Map<ClassLoader, InstrumentedClassLoader> classLoaderCache = |
65 | | - new ConcurrentHashMap<>(); |
| 66 | + new WeakHashMap<>(); |
66 | 67 |
|
67 | 68 | /** |
68 | 69 | * Creates and returns an instance of a dynamically instrumented class that extends the specified |
@@ -122,7 +123,13 @@ public <T extends Component> Class<? extends T> instrumentClass(Class<T> parent) |
122 | 123 | Constructor<?> defaultConstructor = parent.getDeclaredConstructor(); |
123 | 124 | if (!Modifier.isPublic(defaultConstructor.getModifiers()) |
124 | 125 | && !Modifier.isProtected(defaultConstructor.getModifiers())) { |
125 | | - defaultConstructor.setAccessible(true); |
| 126 | + try { |
| 127 | + defaultConstructor.setAccessible(true); |
| 128 | + } catch (Exception e) { |
| 129 | + throw new IllegalArgumentException( |
| 130 | + "Parent class must have an accessible no-argument constructor: " + parent.getName(), |
| 131 | + e); |
| 132 | + } |
126 | 133 | } |
127 | 134 | } catch (NoSuchMethodException e) { |
128 | 135 | throw new IllegalArgumentException( |
@@ -178,12 +185,17 @@ private static boolean hasJsonValueParameters(Method method) { |
178 | 185 |
|
179 | 186 | private <T extends Component> Class<? extends T> createInstrumentedClass(Class<T> parent, |
180 | 187 | String className) throws Exception { |
181 | | - ClassLoader parentClassLoader = parent.getClassLoader(); |
182 | 188 | InstrumentedClassLoader classLoader = |
183 | | - classLoaderCache.computeIfAbsent(parentClassLoader, InstrumentedClassLoader::new); |
| 189 | + getOrCreateInstrumentedClassLoader(parent.getClassLoader()); |
184 | 190 | return classLoader.defineInstrumentedClass(className, parent).asSubclass(parent); |
185 | 191 | } |
186 | 192 |
|
| 193 | + private InstrumentedClassLoader getOrCreateInstrumentedClassLoader(ClassLoader parent) { |
| 194 | + synchronized (classLoaderCache) { |
| 195 | + return classLoaderCache.computeIfAbsent(parent, InstrumentedClassLoader::new); |
| 196 | + } |
| 197 | + } |
| 198 | + |
187 | 199 | private static final class InstrumentedClassLoader extends ClassLoader { |
188 | 200 |
|
189 | 201 | private final Map<Class<?>, Class<?>> instrumentedClassCache = new ConcurrentHashMap<>(); |
@@ -289,7 +301,11 @@ private void generateMethodOverride(ClassWriter cw, Method method, String intern |
289 | 301 | } |
290 | 302 |
|
291 | 303 | // Return converted result or void |
292 | | - mv.visitInsn(Opcodes.ARETURN); |
| 304 | + if (method.getReturnType() == Void.TYPE) { |
| 305 | + mv.visitInsn(Opcodes.RETURN); |
| 306 | + } else { |
| 307 | + mv.visitInsn(Opcodes.ARETURN); |
| 308 | + } |
293 | 309 |
|
294 | 310 | mv.visitMaxs(0, 0); |
295 | 311 | mv.visitEnd(); |
|
0 commit comments