aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormichalkurka <michalk@h2o.ai>2021-03-17 13:12:21 -0400
committermichalkurka <michalk@h2o.ai>2021-03-17 13:12:21 -0400
commit64e15350cfdb7aa42a627e374d5c5de880fc9bed (patch)
tree666269b0d918325c006db9a0bf71531f97f16372
parent0d468da4e95daeef7413c99a81b71d72eb8e7cad (diff)
downloadjavassist-64e15350cfdb7aa42a627e374d5c5de880fc9bed.tar.gz
javassist-64e15350cfdb7aa42a627e374d5c5de880fc9bed.zip
Fix a race condition in CtClassType#getClassFile3
javassist fails to find a class when concurrently running process compresses the class (converts classfile to raw bytes) the idea of the fix is to make sure to only update rawClassfile and classfile under lock in getClassFile3, all other places that modify classfile are already synchronized when reading the object state, we need to read under lock both classfile and rawClassFile otherwise we might get an inconsistent state
-rw-r--r--src/main/javassist/CtClassType.java25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/main/javassist/CtClassType.java b/src/main/javassist/CtClassType.java
index ae196c4a..959ec302 100644
--- a/src/main/javassist/CtClassType.java
+++ b/src/main/javassist/CtClassType.java
@@ -179,6 +179,7 @@ class CtClassType extends CtClass {
}
public ClassFile getClassFile3(boolean doCompress) {
+ // quick path - no locking
ClassFile cfile = classfile;
if (cfile != null)
return cfile;
@@ -186,17 +187,29 @@ class CtClassType extends CtClass {
if (doCompress)
classPool.compress();
- if (rawClassfile != null) {
+ byte[] rcfile;
+ synchronized (this) {
+ // repeat under lock to make sure we get a consistent result (classfile might have been set by another thread)
+ cfile = classfile;
+ if (cfile != null)
+ return cfile;
+
+ rcfile = rawClassfile;
+ }
+
+ if (rcfile != null) {
+ final ClassFile cf;
try {
- ClassFile cf = new ClassFile(new DataInputStream(
- new ByteArrayInputStream(rawClassfile)));
- rawClassfile = null;
- getCount = GET_THRESHOLD;
- return setClassFile(cf);
+ cf = new ClassFile(new DataInputStream(new ByteArrayInputStream(rcfile)));
}
catch (IOException e) {
throw new RuntimeException(e.toString(), e);
}
+ getCount = GET_THRESHOLD;
+ synchronized (this) {
+ rawClassfile = null;
+ return setClassFile(cf);
+ }
}
InputStream fin = null;