From 8d49dddbba500562182c0ea836bda56888f565ff Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 1 Aug 2011 18:22:48 +0900 Subject: [PATCH] use static call instead of call by reflection --- .../java/org/xerial/snappy/SnappyLoader.java | 111 ++++++++++-------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/src/main/java/org/xerial/snappy/SnappyLoader.java b/src/main/java/org/xerial/snappy/SnappyLoader.java index 82941a4..4215b31 100755 --- a/src/main/java/org/xerial/snappy/SnappyLoader.java +++ b/src/main/java/org/xerial/snappy/SnappyLoader.java @@ -170,65 +170,82 @@ public class SnappyLoader 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 + File nativeLib = findNativeLibrary(); + if (nativeLib != null) { + System.load(nativeLib.getAbsolutePath()); + } + else { + // Load preinstalled snappyjava (in the path -Djava.library.path) + System.loadLibrary("snappyjava"); + } + + try { + api = (SnappyNativeAPI) Class.forName("org.xerial.snappy.SnappyNative").newInstance(); + isLoaded = true; + } + catch (Exception e) { + e.printStackTrace(System.err); + throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, e.getMessage()); + } + + } } - // Prepare SnappyNativeLoader or LocalSnappyNativeLoader - Class< ? > nativeLoader = prepareNativeLoader(); - // Load the code - loadNativeLibrary(nativeLoader); return api; } private static Class< ? > prepareNativeLoader() { - boolean useNativeCodeInjection = !Boolean.parseBoolean(System.getProperty(KEY_SNAPPY_DISABLE_NATIVE_INJECTION, - "false")); try { - if (!useNativeCodeInjection) { - // Use the local loader - return LocalSnappyNativeLoader.class; + // Use parent class loader to load SnappyNative, since Tomcat, which uses different class loaders for each webapps, cannot load JNI interface twice + + final String nativeLoaderClassName = "org.xerial.snappy.SnappyNativeLoader"; + ClassLoader rootClassLoader = getRootClassLoader(); + // Load a byte code + byte[] byteCode = getByteCode("/org/xerial/snappy/SnappyNativeLoader.bytecode"); + // In addition, we need to load the other dependent classes (e.g., SnappyNative and SnappyException) using the system class loader + final String[] classesToPreload = new String[] { "org.xerial.snappy.SnappyNativeAPI", + "org.xerial.snappy.SnappyNative", "org.xerial.snappy.SnappyErrorCode" }; + List preloadClassByteCode = new ArrayList(classesToPreload.length); + for (String each : classesToPreload) { + preloadClassByteCode.add(getByteCode(String.format("/%s.class", each.replaceAll("\\.", "/")))); } - else { - // Use parent class loader to load SnappyNative, since Tomcat, which uses different class loaders for each webapps, cannot load JNI interface twice - final String nativeLoaderClassName = "org.xerial.snappy.SnappyNativeLoader"; - ClassLoader rootClassLoader = getRootClassLoader(); - // Load a byte code - byte[] byteCode = getByteCode("/org/xerial/snappy/SnappyNativeLoader.bytecode"); - // In addition, we need to load the other dependent classes (e.g., SnappyNative and SnappyException) using the system class loader - final String[] classesToPreload = new String[] { "org.xerial.snappy.SnappyNativeAPI", - "org.xerial.snappy.SnappyNative", "org.xerial.snappy.SnappyErrorCode" }; - List preloadClassByteCode = new ArrayList(classesToPreload.length); - for (String each : classesToPreload) { - preloadClassByteCode.add(getByteCode(String.format("/%s.class", each.replaceAll("\\.", "/")))); + // Create SnappyNative class from a byte code + Class< ? > classLoader = Class.forName("java.lang.ClassLoader"); + Method defineClass = classLoader.getDeclaredMethod("defineClass", new Class[] { String.class, byte[].class, + int.class, int.class }); + + //ProtectionDomain pd = System.class.getProtectionDomain(); + + // ClassLoader.defineClass is a protected method, so we have to make it accessible + defineClass.setAccessible(true); + try { + // Create a new class using a ClassLoader#defineClass + defineClass.invoke(rootClassLoader, nativeLoaderClassName, byteCode, 0, byteCode.length); + + for (int i = 0; i < classesToPreload.length; ++i) { + byte[] b = preloadClassByteCode.get(i); + defineClass.invoke(rootClassLoader, classesToPreload[i], b, 0, b.length); } - - // Create SnappyNative class from a byte code - Class< ? > classLoader = Class.forName("java.lang.ClassLoader"); - Method defineClass = classLoader.getDeclaredMethod("defineClass", new Class[] { String.class, - byte[].class, int.class, int.class }); - - //ProtectionDomain pd = System.class.getProtectionDomain(); - - // ClassLoader.defineClass is a protected method, so we have to make it accessible - defineClass.setAccessible(true); - try { - // Create a new class using a ClassLoader#defineClass - defineClass.invoke(rootClassLoader, nativeLoaderClassName, byteCode, 0, byteCode.length); - - for (int i = 0; i < classesToPreload.length; ++i) { - byte[] b = preloadClassByteCode.get(i); - defineClass.invoke(rootClassLoader, classesToPreload[i], b, 0, b.length); - } - } - finally { - // Reset the accessibility to defineClass method - defineClass.setAccessible(false); - } - - // Load the SnappyNativeLoader class - return rootClassLoader.loadClass(nativeLoaderClassName); } + finally { + // Reset the accessibility to defineClass method + defineClass.setAccessible(false); + } + + // Load the SnappyNativeLoader class + return rootClassLoader.loadClass(nativeLoaderClassName); + } catch (Exception e) { e.printStackTrace(System.err);