-
Notifications
You must be signed in to change notification settings - Fork 719
Open
Description
I've identified a thread-safety issue in the class cache management where concurrent execution of compress() and removeCached() may cause NullPointerException.

- classes Hashtable is accessed by:
- removeCached() performs classes.remove()
- compress() iterates via classes.elements()
-
No synchronization between these operations
-
Race condition may occur when:
- Thread A starts iteration in compress()
- Thread B removes an element via removeCached()
- Thread A tries to call compress() on removed element → NPE
Reproduction:
public class Main {
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
int size = 300;
CountDownLatch countDownLatch = new CountDownLatch(size);
for (int i = 0; i < size; i++) {
int finalI = i;
new Thread(() -> {
try {
ClassFile classFile = new ClassFile(false, "test" + finalI, Object.class.getName());
CtClass cc = pool.makeClass(classFile);
System.out.println(cc.getSimpleName());
Thread.sleep(5);
cc.detach();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}finally {
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
System.out.println("done");
}
}
The issue can be easily reproduced during debugging in IntelliJ IDEA when stepping through the nextElement() call.

Metadata
Metadata
Assignees
Labels
No labels