Skip to content

Commit

Permalink
Synchronize the lookup-and-define-class logic in blackbird
Browse files Browse the repository at this point in the history
If blackbird attempts to access/define a new class concurrently,
it can hit a race condition between attempting to access it and
defining it when that fails.  If it does fail, enter a synchronized
block and try again before defining the access class.

Should fix FasterXML#169
  • Loading branch information
josephlbarnett committed May 4, 2022
1 parent 4b5be14 commit 8a2e02b
Showing 1 changed file with 23 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,24 +109,29 @@ private static Class<?> accessClassIn(MethodHandles.Lookup lookup) throws IOExce
try {
return Class.forName(pkg.getName() + "." + CLASS_NAME, true, lookup.lookupClass().getClassLoader());
} catch (ClassNotFoundException ign) { }
String fqcn = pkg.getName()
.replace('.', '/')
+ "/" + CLASS_NAME;
ByteArrayOutputStream classBytes = new ByteArrayOutputStream(HEADER.length + FOOTER.length + fqcn.length() + 16);
DataOutputStream dataOut = new DataOutputStream(classBytes);
for (int b : HEADER) {
dataOut.writeByte(b);
}
dataOut.writeUTF(fqcn);
for (int b : FOOTER) {
dataOut.writeByte(b);
}
try {
return (Class<?>) DEFINE_CLASS.invokeExact(lookup, classBytes.toByteArray());
} catch (RuntimeException | Error | IOException | ReflectiveOperationException e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e);
synchronized(CrossLoaderAccess.class) {
try {
return Class.forName(pkg.getName() + "." + CLASS_NAME, true, lookup.lookupClass().getClassLoader());
} catch (ClassNotFoundException ign) { }
String fqcn = pkg.getName()
.replace('.', '/')
+ "/" + CLASS_NAME;
ByteArrayOutputStream classBytes = new ByteArrayOutputStream(HEADER.length + FOOTER.length + fqcn.length() + 16);
DataOutputStream dataOut = new DataOutputStream(classBytes);
for (int b : HEADER) {
dataOut.writeByte(b);
}
dataOut.writeUTF(fqcn);
for (int b : FOOTER) {
dataOut.writeByte(b);
}
try {
return (Class<?>) DEFINE_CLASS.invokeExact(lookup, classBytes.toByteArray());
} catch (RuntimeException | Error | IOException | ReflectiveOperationException e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
}

0 comments on commit 8a2e02b

Please sign in to comment.