mirror of
https://github.com/xerial/snappy-java.git
synced 2025-04-08 19:35:08 +02:00
removed overlapped part. Use ProtectionDomain when injecting classes
This commit is contained in:
parent
075b94af00
commit
1aba243237
@ -31,11 +31,13 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.DigestInputStream;
|
import java.security.DigestInputStream;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
@ -111,6 +113,19 @@ public class SnappyLoader
|
|||||||
return isLoaded;
|
return isLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasInjectedNativeLoader() {
|
||||||
|
try {
|
||||||
|
final String nativeLoaderClassName = "org.xerial.snappy.SnappyNativeLoader";
|
||||||
|
Class< ? > c = Class.forName(nativeLoaderClassName);
|
||||||
|
// If this native loader class is already defined, it means that another class loader already loaded the native library of snappy
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e) {
|
||||||
|
// do loading
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load SnappyNative and its JNI native implementation in the root class
|
* Load SnappyNative and its JNI native implementation in the root class
|
||||||
* loader. This is necessary to avoid the JNI multi-loading issue when the
|
* loader. This is necessary to avoid the JNI multi-loading issue when the
|
||||||
@ -145,7 +160,7 @@ public class SnappyLoader
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static synchronized SnappyNativeAPI load() {
|
static SnappyNativeAPI load() {
|
||||||
|
|
||||||
if (api != null)
|
if (api != null)
|
||||||
return api;
|
return api;
|
||||||
@ -154,54 +169,41 @@ public class SnappyLoader
|
|||||||
"false"));
|
"false"));
|
||||||
//System.out.println("use native code injection: " + useNativeCodeInjection);
|
//System.out.println("use native code injection: " + useNativeCodeInjection);
|
||||||
|
|
||||||
if (useNativeCodeInjection) {
|
try {
|
||||||
try {
|
if (useNativeCodeInjection) {
|
||||||
final String nativeLoaderClassName = "org.xerial.snappy.SnappyNativeLoader";
|
if (!hasInjectedNativeLoader()) {
|
||||||
Class< ? > c = Class.forName(nativeLoaderClassName);
|
// Prepare SnappyNativeLoader or LocalSnappyNativeLoader
|
||||||
// If this native loader class is already defined, it means that another class loader already loaded the native library of snappy
|
Class< ? > nativeLoader = injectSnappyNativeLoader();
|
||||||
api = (SnappyNativeAPI) Class.forName("org.xerial.snappy.SnappyNative").newInstance();
|
// Load the JNI code
|
||||||
isLoaded = true;
|
loadNativeLibrary(nativeLoader);
|
||||||
return api;
|
}
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException e) {
|
else {
|
||||||
// do loading
|
if (!isLoaded) {
|
||||||
}
|
// load locally
|
||||||
catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare SnappyNativeLoader or LocalSnappyNativeLoader
|
|
||||||
Class< ? > nativeLoader = prepareNativeLoader();
|
|
||||||
// Load the code
|
|
||||||
loadNativeLibrary(nativeLoader);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!isLoaded) {
|
|
||||||
// load locally
|
|
||||||
try {
|
|
||||||
File nativeLib = findNativeLibrary();
|
File nativeLib = findNativeLibrary();
|
||||||
if (nativeLib != null) {
|
if (nativeLib != null) {
|
||||||
System.load(nativeLib.getAbsolutePath());
|
System.load(nativeLib.getAbsolutePath());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Load preinstalled snappyjava (in the path -Djava.library.path)
|
// Load pre-installed libsnappyjava (in the path -Djava.library.path)
|
||||||
System.loadLibrary("snappyjava");
|
System.loadLibrary("snappyjava");
|
||||||
}
|
}
|
||||||
isLoaded = true;
|
|
||||||
api = (SnappyNativeAPI) Class.forName("org.xerial.snappy.SnappyNative").newInstance();
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
e.printStackTrace(System.err);
|
|
||||||
throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isLoaded = true;
|
||||||
|
api = (SnappyNativeAPI) Class.forName("org.xerial.snappy.SnappyNative").newInstance();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return api;
|
return api;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Class< ? > prepareNativeLoader() {
|
private static Class< ? > injectSnappyNativeLoader() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use parent class loader to load SnappyNative, since Tomcat, which uses different class loaders for each webapps, cannot load JNI interface twice
|
// Use parent class loader to load SnappyNative, since Tomcat, which uses different class loaders for each webapps, cannot load JNI interface twice
|
||||||
@ -221,19 +223,19 @@ public class SnappyLoader
|
|||||||
// Create SnappyNative class from a byte code
|
// Create SnappyNative class from a byte code
|
||||||
Class< ? > classLoader = Class.forName("java.lang.ClassLoader");
|
Class< ? > classLoader = Class.forName("java.lang.ClassLoader");
|
||||||
Method defineClass = classLoader.getDeclaredMethod("defineClass", new Class[] { String.class, byte[].class,
|
Method defineClass = classLoader.getDeclaredMethod("defineClass", new Class[] { String.class, byte[].class,
|
||||||
int.class, int.class });
|
int.class, int.class, ProtectionDomain.class });
|
||||||
|
|
||||||
//ProtectionDomain pd = System.class.getProtectionDomain();
|
ProtectionDomain pd = System.class.getProtectionDomain();
|
||||||
|
|
||||||
// ClassLoader.defineClass is a protected method, so we have to make it accessible
|
// ClassLoader.defineClass is a protected method, so we have to make it accessible
|
||||||
defineClass.setAccessible(true);
|
defineClass.setAccessible(true);
|
||||||
try {
|
try {
|
||||||
// Create a new class using a ClassLoader#defineClass
|
// Create a new class using a ClassLoader#defineClass
|
||||||
defineClass.invoke(rootClassLoader, nativeLoaderClassName, byteCode, 0, byteCode.length);
|
defineClass.invoke(rootClassLoader, nativeLoaderClassName, byteCode, 0, byteCode.length, pd);
|
||||||
|
|
||||||
for (int i = 0; i < classesToPreload.length; ++i) {
|
for (int i = 0; i < classesToPreload.length; ++i) {
|
||||||
byte[] b = preloadClassByteCode.get(i);
|
byte[] b = preloadClassByteCode.get(i);
|
||||||
defineClass.invoke(rootClassLoader, classesToPreload[i], b, 0, b.length);
|
defineClass.invoke(rootClassLoader, classesToPreload[i], b, 0, b.length, pd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@ -252,30 +254,22 @@ public class SnappyLoader
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadNativeLibrary(Class< ? > loaderClass) {
|
private static void loadNativeLibrary(Class< ? > loaderClass) throws SecurityException, NoSuchMethodException,
|
||||||
|
IllegalArgumentException, IllegalAccessException, InvocationTargetException {
|
||||||
if (loaderClass == null)
|
if (loaderClass == null)
|
||||||
throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, "missing snappy native loader class");
|
throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, "missing snappy native loader class");
|
||||||
|
|
||||||
try {
|
File nativeLib = findNativeLibrary();
|
||||||
File nativeLib = findNativeLibrary();
|
if (nativeLib != null) {
|
||||||
if (nativeLib != null) {
|
// Load extracted or specified snappyjava native library.
|
||||||
// Load extracted or specified snappyjava native library.
|
Method loadMethod = loaderClass.getDeclaredMethod("load", new Class[] { String.class });
|
||||||
Method loadMethod = loaderClass.getDeclaredMethod("load", new Class[] { String.class });
|
loadMethod.invoke(null, nativeLib.getAbsolutePath());
|
||||||
loadMethod.invoke(null, nativeLib.getAbsolutePath());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Load preinstalled snappyjava (in the path -Djava.library.path)
|
|
||||||
Method loadMethod = loaderClass.getDeclaredMethod("loadLibrary", new Class[] { String.class });
|
|
||||||
loadMethod.invoke(null, "snappyjava");
|
|
||||||
}
|
|
||||||
isLoaded = true;
|
|
||||||
api = (SnappyNativeAPI) Class.forName("org.xerial.snappy.SnappyNative").newInstance();
|
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
else {
|
||||||
e.printStackTrace(System.err);
|
// Load preinstalled snappyjava (in the path -Djava.library.path)
|
||||||
throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, e.getMessage());
|
Method loadMethod = loaderClass.getDeclaredMethod("loadLibrary", new Class[] { String.class });
|
||||||
|
loadMethod.invoke(null, "snappyjava");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String KEY_SNAPPY_LIB_PATH = "org.xerial.snappy.lib.path";
|
public static final String KEY_SNAPPY_LIB_PATH = "org.xerial.snappy.lib.path";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user