Support running Netty in bootstrap class loader
Motivation: Fix NullPointerExceptions that occur when running netty-tcnative inside the bootstrap class loader. Modifications: - Replace loader.getResource(...) with ClassLoader.getSystemResource(...) when loader is null. - Replace loader.loadClass(...) with Class.forName(..., false, loader) which works when loader is both null and non-null. Result: Support running native libs in bootstrap class loader
This commit is contained in:
parent
911b2acc50
commit
58e74e9fee
@ -136,13 +136,22 @@ public final class NativeLibraryLoader {
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
File tmpFile = null;
|
||||
URL url = loader.getResource(path);
|
||||
URL url;
|
||||
if (loader == null) {
|
||||
url = ClassLoader.getSystemResource(path);
|
||||
} else {
|
||||
url = loader.getResource(path);
|
||||
}
|
||||
try {
|
||||
if (url == null) {
|
||||
if (PlatformDependent.isOsx()) {
|
||||
String fileName = path.endsWith(".jnilib") ? NATIVE_RESOURCE_HOME + "lib" + name + ".dynlib" :
|
||||
NATIVE_RESOURCE_HOME + "lib" + name + ".jnilib";
|
||||
url = loader.getResource(fileName);
|
||||
if (loader == null) {
|
||||
url = ClassLoader.getSystemResource(fileName);
|
||||
} else {
|
||||
url = loader.getResource(fileName);
|
||||
}
|
||||
if (url == null) {
|
||||
FileNotFoundException fnf = new FileNotFoundException(fileName);
|
||||
ThrowableUtil.addSuppressedAndClear(fnf, suppressed);
|
||||
@ -280,8 +289,12 @@ public final class NativeLibraryLoader {
|
||||
private static Class<?> tryToLoadClass(final ClassLoader loader, final Class<?> helper)
|
||||
throws ClassNotFoundException {
|
||||
try {
|
||||
return loader.loadClass(helper.getName());
|
||||
return Class.forName(helper.getName(), false, loader);
|
||||
} catch (ClassNotFoundException e1) {
|
||||
if (loader == null) {
|
||||
// cannot defineClass inside bootstrap class loader
|
||||
throw e1;
|
||||
}
|
||||
try {
|
||||
// The helper class is NOT found in target ClassLoader, we have to define the helper class.
|
||||
final byte[] classBinary = classToByteArray(helper);
|
||||
|
@ -17,6 +17,7 @@ package io.netty.util.internal;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -25,6 +26,8 @@ import static org.junit.Assert.fail;
|
||||
|
||||
public class NativeLibraryLoaderTest {
|
||||
|
||||
private static final Method getSupressedMethod = getGetSuppressed();
|
||||
|
||||
@Test
|
||||
public void testFileNotFound() {
|
||||
try {
|
||||
@ -32,6 +35,47 @@ public class NativeLibraryLoaderTest {
|
||||
fail();
|
||||
} catch (UnsatisfiedLinkError error) {
|
||||
assertTrue(error.getCause() instanceof FileNotFoundException);
|
||||
if (getSupressedMethod != null) {
|
||||
verifySuppressedException(error, UnsatisfiedLinkError.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileNotFoundWithNullClassLoader() {
|
||||
try {
|
||||
NativeLibraryLoader.load(UUID.randomUUID().toString(), null);
|
||||
fail();
|
||||
} catch (UnsatisfiedLinkError error) {
|
||||
assertTrue(error.getCause() instanceof FileNotFoundException);
|
||||
if (getSupressedMethod != null) {
|
||||
verifySuppressedException(error, ClassNotFoundException.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifySuppressedException(UnsatisfiedLinkError error,
|
||||
Class<?> expectedSuppressedExceptionClass) {
|
||||
try {
|
||||
Throwable[] suppressed = (Throwable[]) getSupressedMethod.invoke(error.getCause());
|
||||
assertTrue(suppressed.length == 1);
|
||||
assertTrue(suppressed[0] instanceof UnsatisfiedLinkError);
|
||||
suppressed = (Throwable[]) getSupressedMethod.invoke(suppressed[0]);
|
||||
assertTrue(suppressed.length == 1);
|
||||
assertTrue(expectedSuppressedExceptionClass.isInstance(suppressed[0]));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getGetSuppressed() {
|
||||
if (PlatformDependent.javaVersion() < 7) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Throwable.class.getDeclaredMethod("getSuppressed");
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user