Try to load accessClass without synchronization

In EsotericSoftware/kryo#422 it's reported that the sychronization
in `ConstructorAccess.get` on the loader is causing significant
thread contention.
This change tries to prevent this, via double checked locking.
Because it's the same pattern it's also done for `FieldAccess`
and `MethodAccess` as well.
This commit is contained in:
Martin Grotzke 2016-05-08 22:44:25 +02:00
parent 88ec7037ea
commit c5563b1205
3 changed files with 232 additions and 220 deletions

View File

@ -51,10 +51,13 @@ public abstract class ConstructorAccess<T> {
Class accessClass;
AccessClassLoader loader = AccessClassLoader.get(type);
synchronized (loader) {
try {
accessClass = loader.loadClass(accessClassName);
} catch (ClassNotFoundException ignored) {
synchronized (loader) {
try {
accessClass = loader.loadClass(accessClassName);
} catch (ClassNotFoundException ignored2) {
String accessClassNameInternal = accessClassName.replace('.', '/');
String classNameInternal = className.replace('.', '/');
String enclosingClassNameInternal;
@ -100,6 +103,7 @@ public abstract class ConstructorAccess<T> {
accessClass = loader.defineClass(accessClassName, cw.toByteArray());
}
}
}
ConstructorAccess<T> access;
try {
access = (ConstructorAccess<T>)accessClass.newInstance();

View File

@ -121,10 +121,13 @@ public abstract class FieldAccess {
Class accessClass = null;
AccessClassLoader loader = AccessClassLoader.get(type);
synchronized (loader) {
try {
accessClass = loader.loadClass(accessClassName);
} catch (ClassNotFoundException ignored) {
synchronized (loader) {
try {
accessClass = loader.loadClass(accessClassName);
} catch (ClassNotFoundException ignored2) {
String accessClassNameInternal = accessClassName.replace('.', '/');
String classNameInternal = className.replace('.', '/');
@ -155,6 +158,7 @@ public abstract class FieldAccess {
accessClass = loader.defineClass(accessClassName, cw.toByteArray());
}
}
}
try {
FieldAccess access = (FieldAccess)accessClass.newInstance();
access.fieldNames = fieldNames;

View File

@ -107,10 +107,13 @@ public abstract class MethodAccess {
Class accessClass;
AccessClassLoader loader = AccessClassLoader.get(type);
synchronized (loader) {
try {
accessClass = loader.loadClass(accessClassName);
} catch (ClassNotFoundException ignored) {
synchronized (loader) {
try {
accessClass = loader.loadClass(accessClassName);
} catch (ClassNotFoundException ignored2) {
String accessClassNameInternal = accessClassName.replace('.', '/');
String classNameInternal = className.replace('.', '/');
@ -272,6 +275,7 @@ public abstract class MethodAccess {
accessClass = loader.defineClass(accessClassName, data);
}
}
}
try {
MethodAccess access = (MethodAccess)accessClass.newInstance();
access.methodNames = methodNames;