Skip to content
Permalink
Browse files

Fixed concurrency issue in custom classloader used for template classes

As reported in issue #241, the problem is only critical (random but
complete crash of the JVM) when upgrading to JDK11.
  • Loading branch information...
luccioman committed Oct 11, 2018
1 parent 0eb52f8 commit 7a62fc0e668f855e13babffbc529a0dc891143d2
Showing with 24 additions and 16 deletions.
  1. +24 −16 source/net/yacy/server/serverClassLoader.java
@@ -70,7 +70,7 @@ public serverClassLoader(final ClassLoader parent) {

/**
* A special loadClass using file as argument to find and load a class
* This methode is directly called by the application and not part of the
* This method is directly called by the application and not part of the
* normal loadClass chain (= never called by JVM)
*
* @param classfile
@@ -84,22 +84,30 @@ public serverClassLoader(final ClassLoader parent) {
if (p < 0) throw new ClassNotFoundException("wrong class name: " + classfile.getName());
final String classname = classfile.getName().substring(0, p);

// load the file from the file system
byte[] b;
try {
//System.out.println("*** DEBUG CLASSLOADER: " + classfile + "; file " + (classfile.exists() ? "exists": "does not exist"));
b = FileUtils.read(classfile);
// make a class out of the stream
c = this.defineClass(null, b, 0, b.length);
resolveClass(c);
} catch (final LinkageError ee) {
synchronized (this) {
/* Important : we must first synchronize any concurrent access AND then check if the class was not already loaded.
* Otherwise, trying to define again the same class (with the defineClass function) may lead to a JVM crash on some platforms,
* notably when running on Java 11 (on earlier JVMs, a LinkageError was only triggered and gracefully catched in that case) */
c = findLoadedClass(classname);
if (c != null) return c;
throw new ClassNotFoundException("linkageError, " + ee.getMessage() + ":" + classfile.toString());
} catch (final IOException ee) {
throw new ClassNotFoundException(ee.getMessage() + ":" + classfile.toString());
}
return c;
if (c != null) {
return c;
}

// load the file from the file system
byte[] b;
try {
b = FileUtils.read(classfile);
// make a class out of the stream
c = this.defineClass(null, b, 0, b.length);
resolveClass(c);
} catch (final LinkageError ee) {
/* This error could occur when two threads try to define concurrently the same class. Should not occur here */
throw new ClassNotFoundException("linkageError, " + ee.getMessage() + ":" + classfile.toString());
} catch (final IOException ee) {
throw new ClassNotFoundException(ee.getMessage() + ":" + classfile.toString());
}
return c;
}
}

}

0 comments on commit 7a62fc0

Please sign in to comment.
You can’t perform that action at this time.