Add a trick to delegate native library loading to the parent class loader

This commit is contained in:
Taro L. Saito 2011-06-23 22:09:09 +09:00
parent 4301cfd9bd
commit dc0e8a3150
10 changed files with 279 additions and 116 deletions

View File

@ -232,5 +232,12 @@
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.14.0-GA</version>
<type>jar</type>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -24,6 +24,7 @@
//--------------------------------------
package org.xerial.snappy;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
@ -49,9 +50,9 @@ public class Snappy
* @param input
* the input data
* @return the compressed byte array
* @throws SnappyException
* @throws IOException
*/
public static byte[] compress(byte[] input) throws SnappyException {
public static byte[] compress(byte[] input) throws IOException {
return rawCompress(input, input.length);
}
@ -65,11 +66,11 @@ public class Snappy
* @param output
* @param outputOffset
* @return byte size of the compressed data
* @throws SnappyException
* @throws IOException
* when failed to access the input/output buffer
*/
public static int compress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset)
throws SnappyException {
throws IOException {
return rawCompress(input, inputOffset, inputLength, output, outputOffset);
}
@ -87,7 +88,7 @@ public class Snappy
* @throws SnappyError
* when the input is not a direct buffer
*/
public static int compress(ByteBuffer uncompressed, ByteBuffer compressed) throws SnappyException {
public static int compress(ByteBuffer uncompressed, ByteBuffer compressed) throws IOException {
if (!uncompressed.isDirect())
throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer");
@ -131,7 +132,7 @@ public class Snappy
return rawCompress(input, input.length * 2); // short uses 2 bytes
}
public static byte[] compress(String s) throws SnappyException {
public static byte[] compress(String s) throws IOException {
try {
return compress(s, "UTF-8");
}
@ -140,7 +141,7 @@ public class Snappy
}
}
public static byte[] compress(String s, String encoding) throws UnsupportedEncodingException, SnappyException {
public static byte[] compress(String s, String encoding) throws UnsupportedEncodingException, IOException {
byte[] data = s.getBytes(encoding);
return compress(data);
}
@ -160,7 +161,7 @@ public class Snappy
* uncompressed data. Takes time proportional to the input length, but is
* usually at least a factor of four faster than actual decompression.
*/
public static boolean isValidCompressedBuffer(byte[] input, int offset, int length) throws SnappyException {
public static boolean isValidCompressedBuffer(byte[] input, int offset, int length) throws IOException {
if (input == null)
throw new NullPointerException("input is null");
return SnappyNative.isValidCompressedBuffer(input, offset, length);
@ -172,7 +173,7 @@ public class Snappy
* uncompressed data. Takes time proportional to the input length, but is
* usually at least a factor of four faster than actual decompression.
*/
public static boolean isValidCompressedBuffer(byte[] input) throws SnappyException {
public static boolean isValidCompressedBuffer(byte[] input) throws IOException {
return isValidCompressedBuffer(input, 0, input.length);
}
@ -182,7 +183,7 @@ public class Snappy
* Takes time proportional to the input length, but is usually at least a
* factor of four faster than actual decompression.
*/
public static boolean isValidCompressedBuffer(ByteBuffer compressed) throws SnappyException {
public static boolean isValidCompressedBuffer(ByteBuffer compressed) throws IOException {
return SnappyNative.isValidCompressedBuffer(compressed, compressed.position(), compressed.remaining());
}
@ -230,10 +231,10 @@ public class Snappy
* @param outputOffset
* byte offset at the output array
* @return byte size of the compressed data
* @throws SnappyException
* @throws IOException
*/
public static int rawCompress(Object input, int inputOffset, int inputLength, byte[] output, int outputOffset)
throws SnappyException {
throws IOException {
if (input == null || output == null)
throw new NullPointerException("input or output is null");
@ -262,10 +263,10 @@ public class Snappy
* @param outputOffset
* byte offset
* @return the byte size of the uncompressed data
* @throws SnappyException
* @throws IOException
*/
public static int rawUncompress(byte[] input, int inputOffset, int inputLength, Object output, int outputOffset)
throws SnappyException {
throws IOException {
if (input == null || output == null)
throw new NullPointerException("input or output is null");
return SnappyNative.rawUncompress(input, inputOffset, inputLength, output, outputOffset);
@ -276,9 +277,9 @@ public class Snappy
*
* @param input
* @return the uncompressed byte array
* @throws SnappyException
* @throws IOException
*/
public static byte[] uncompress(byte[] input) throws SnappyException {
public static byte[] uncompress(byte[] input) throws IOException {
byte[] result = new byte[Snappy.uncompressedLength(input)];
int byteSize = Snappy.uncompress(input, 0, input.length, result, 0);
return result;
@ -300,10 +301,10 @@ public class Snappy
* @param output
* @param outputOffset
* @return the byte size of the uncompressed data
* @throws SnappyException
* @throws IOException
*/
public static int uncompress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset)
throws SnappyException {
throws IOException {
return rawUncompress(input, inputOffset, inputLength, output, outputOffset);
}
@ -323,12 +324,12 @@ public class Snappy
* output of the the uncompressed data. It uses buffer[pot()..]
* @return uncompressed data size
*
* @throws SnappyException
* @throws IOException
* when failed to uncompress the given input
* @throws SnappyError
* when the input is not a direct buffer
*/
public static int uncompress(ByteBuffer compressed, ByteBuffer uncompressed) throws SnappyException {
public static int uncompress(ByteBuffer compressed, ByteBuffer uncompressed) throws IOException {
if (!compressed.isDirect())
throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer");
@ -347,18 +348,18 @@ public class Snappy
return decompressedSize;
}
public static char[] uncompressCharArray(byte[] input) throws SnappyException {
public static char[] uncompressCharArray(byte[] input) throws IOException {
return uncompressCharArray(input, 0, input.length);
}
public static char[] uncompressCharArray(byte[] input, int offset, int length) throws SnappyException {
public static char[] uncompressCharArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
char[] result = new char[uncompressedLength / 2];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
public static double[] uncompressDoubleArray(byte[] input) throws SnappyException {
public static double[] uncompressDoubleArray(byte[] input) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, 0, input.length);
double[] result = new double[uncompressedLength / 8];
int byteSize = SnappyNative.rawUncompress(input, 0, input.length, result, 0);
@ -371,11 +372,11 @@ public class Snappy
*
* @param input
* @return umcompressed byte size of the the given input data
* @throws SnappyException
* @throws IOException
* when failed to uncompress the given input. The error code is
* {@link SnappyErrorCode#PARSING_ERROR}
*/
public static int uncompressedLength(byte[] input) throws SnappyException {
public static int uncompressedLength(byte[] input) throws IOException {
return SnappyNative.uncompressedLength(input, 0, input.length);
}
@ -387,11 +388,11 @@ public class Snappy
* @param offset
* @param length
* @return umcompressed byte size of the the given input data
* @throws SnappyException
* @throws IOException
* when failed to uncompress the given input. The error code is
* {@link SnappyErrorCode#PARSING_ERROR}
*/
public static int uncompressedLength(byte[] input, int offset, int length) throws SnappyException {
public static int uncompressedLength(byte[] input, int offset, int length) throws IOException {
if (input == null)
throw new NullPointerException("input is null");
@ -409,8 +410,7 @@ public class Snappy
}
}
public static CompressedDataLength getUncompressedLength(byte[] input, int offset, int limit)
throws SnappyException {
public static CompressedDataLength getUncompressedLength(byte[] input, int offset, int limit) throws IOException {
if (input == null)
throw new NullPointerException("input is null");
@ -463,64 +463,64 @@ public class Snappy
* @param compressed
* input data [pos() ... limit())
* @return uncompressed byte length of the given input
* @throws SnappyException
* @throws IOException
* when failed to uncompress the given input. The error code is
* {@link SnappyErrorCode#PARSING_ERROR}
* @throws SnappyError
* when the input is not a direct buffer
*/
public static int uncompressedLength(ByteBuffer compressed) throws SnappyException {
public static int uncompressedLength(ByteBuffer compressed) throws IOException {
if (!compressed.isDirect())
throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer");
return SnappyNative.uncompressedLength(compressed, compressed.position(), compressed.remaining());
}
public static float[] uncompressFloatArray(byte[] input) throws SnappyException {
public static float[] uncompressFloatArray(byte[] input) throws IOException {
return uncompressFloatArray(input, 0, input.length);
}
public static float[] uncompressFloatArray(byte[] input, int offset, int length) throws SnappyException {
public static float[] uncompressFloatArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
float[] result = new float[uncompressedLength / 4];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
public static int[] uncompressIntArray(byte[] input) throws SnappyException {
public static int[] uncompressIntArray(byte[] input) throws IOException {
return uncompressIntArray(input, 0, input.length);
}
public static int[] uncompressIntArray(byte[] input, int offset, int length) throws SnappyException {
public static int[] uncompressIntArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
int[] result = new int[uncompressedLength / 4];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
public static long[] uncompressLongArray(byte[] input) throws SnappyException {
public static long[] uncompressLongArray(byte[] input) throws IOException {
return uncompressLongArray(input, 0, input.length);
}
public static long[] uncompressLongArray(byte[] input, int offset, int length) throws SnappyException {
public static long[] uncompressLongArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
long[] result = new long[uncompressedLength / 8];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
public static short[] uncompressShortArray(byte[] input) throws SnappyException {
public static short[] uncompressShortArray(byte[] input) throws IOException {
return uncompressShortArray(input, 0, input.length);
}
public static short[] uncompressShortArray(byte[] input, int offset, int length) throws SnappyException {
public static short[] uncompressShortArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
short[] result = new short[uncompressedLength / 2];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
public static String uncompressString(byte[] input) throws SnappyException {
public static String uncompressString(byte[] input) throws IOException {
try {
return uncompressString(input, "UTF-8");
}
@ -529,7 +529,7 @@ public class Snappy
}
}
public static String uncompressString(byte[] input, int offset, int length) throws SnappyException {
public static String uncompressString(byte[] input, int offset, int length) throws IOException {
try {
return uncompressString(input, offset, length, "UTF-8");
}
@ -538,14 +538,14 @@ public class Snappy
}
}
public static String uncompressString(byte[] input, int offset, int length, String encoding)
throws SnappyException, UnsupportedEncodingException {
public static String uncompressString(byte[] input, int offset, int length, String encoding) throws IOException,
UnsupportedEncodingException {
byte[] uncompressed = new byte[uncompressedLength(input, offset, length)];
int compressedSize = uncompress(input, offset, length, uncompressed, 0);
return new String(uncompressed, encoding);
}
public static String uncompressString(byte[] input, String encoding) throws SnappyException,
public static String uncompressString(byte[] input, String encoding) throws IOException,
UnsupportedEncodingException {
byte[] uncompressed = uncompress(input);
return new String(uncompressed, encoding);

View File

@ -45,4 +45,12 @@ public enum SnappyErrorCode {
private SnappyErrorCode(int id) {
this.id = id;
}
public static String getErrorMessage(int id) {
for (SnappyErrorCode code : SnappyErrorCode.values()) {
if (code.id == id)
return code.name();
}
return UNKNOWN.name();
}
}

View File

@ -95,16 +95,11 @@ public class SnappyInputStream extends InputStream
finishedReading = true;
// Uncompress
try {
int uncompressedLength = Snappy.uncompressedLength(compressed, 0, cursor);
uncompressed = new byte[uncompressedLength];
Snappy.uncompress(compressed, 0, cursor, uncompressed, 0);
this.uncompressedCursor = 0;
this.uncompressedLimit = uncompressedLength;
}
catch (SnappyException e) {
throw new IOException(e.getMessage());
}
int uncompressedLength = Snappy.uncompressedLength(compressed, 0, cursor);
uncompressed = new byte[uncompressedLength];
Snappy.uncompress(compressed, 0, cursor, uncompressed, 0);
this.uncompressedCursor = 0;
this.uncompressedLimit = uncompressedLength;
}
@ -160,7 +155,7 @@ public class SnappyInputStream extends InputStream
}
uncompressedLimit = actualUncompressedLength;
}
catch (SnappyException e) {
catch (IOException e) {
throw new IOException("failed to uncompress the chunk: " + e.getMessage());
}

View File

@ -35,6 +35,9 @@ import java.net.URL;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
@ -77,13 +80,97 @@ import java.util.Properties;
*/
public class SnappyLoader
{
private static boolean isLoaded = false;
private static boolean isInitialized = false;
private static boolean isLoaded = false;
private static ClassLoader getSystemClassLoader() {
ClassLoader cl = SnappyLoader.class.getClassLoader();
while (cl.getParent() != null) {
cl = cl.getParent();
}
return cl;
}
private static byte[] getByteCode(String resourcePath) throws IOException {
InputStream in = SnappyLoader.class.getResourceAsStream(resourcePath);
assert (in != null);
byte[] buf = new byte[1024];
ByteArrayOutputStream byteCodeBuf = new ByteArrayOutputStream();
for (int readLength; (readLength = in.read(buf)) != -1;) {
byteCodeBuf.write(buf, 0, readLength);
}
in.close();
return byteCodeBuf.toByteArray();
}
public static void load() {
if (!isInitialized) {
final String nativeLoaderClassName = "org.xerial.snappy.SnappyNativeLoader";
final String[] preloadClass = new String[] { "org.xerial.snappy.SnappyNative",
"org.xerial.snappy.SnappyErrorCode" };
try {
Class.forName(nativeLoaderClassName);
// If this native loader class is already defined, it means that another class loader already loaded the native library of snappy
isInitialized = true;
return;
}
catch (ClassNotFoundException e) {
try {
// Load a byte code
byte[] byteCode = getByteCode("/org/xerial/snappy/SnappyNativeLoader.bytecode");
// In addition, load the SnappyNative and SnappyException class in the system class loader
List<byte[]> preloadClassByteCode = new ArrayList<byte[]>(preloadClass.length);
for (String each : preloadClass) {
preloadClassByteCode.add(getByteCode(String.format("/%s.class", each.replaceAll("\\.", "/"))));
}
// Create a new class to the system class loader
Class< ? > classLoader = Class.forName("java.lang.ClassLoader");
java.lang.reflect.Method defineClass = classLoader.getDeclaredMethod("defineClass", new Class[] {
String.class, byte[].class, int.class, int.class, ProtectionDomain.class });
ClassLoader systemClassLoader = getSystemClassLoader();
defineClass.setAccessible(true);
try {
// Load SnappyNativeLoader
defineClass.invoke(systemClassLoader, nativeLoaderClassName, byteCode, 0, byteCode.length,
System.class.getProtectionDomain());
for (int i = 0; i < preloadClass.length; ++i) {
byte[] b = preloadClassByteCode.get(i);
defineClass.invoke(systemClassLoader, preloadClass[i], b, 0, b.length,
System.class.getProtectionDomain());
}
}
finally {
defineClass.setAccessible(false);
}
// Load the loader class
Class< ? > loaderClass = systemClassLoader.loadClass(nativeLoaderClassName);
if (loaderClass != null) {
java.lang.reflect.Method loadMethod = loaderClass.getDeclaredMethod("load",
new Class[] { String.class });
File nativeLib = findNativeLibrary();
loadMethod.invoke(null, nativeLib.getAbsolutePath());
for (String each : preloadClass) {
systemClassLoader.loadClass(each);
}
isInitialized = true;
}
}
catch (Exception e2) {
e.printStackTrace();
}
}
public static boolean load() {
if (!isLoaded) {
loadSnappyNativeLibrary();
}
return isLoaded;
}
public static final String KEY_SNAPPY_LIB_PATH = "org.xerial.snappy.lib.path";
@ -101,7 +188,6 @@ public class SnappyLoader
*/
static String md5sum(InputStream input) throws IOException {
BufferedInputStream in = new BufferedInputStream(input);
try {
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
DigestInputStream digestInputStream = new DigestInputStream(in, digest);
@ -128,8 +214,7 @@ public class SnappyLoader
* @param targetFolder
* @return
*/
private static boolean extractAndLoadLibraryFile(String libFolderForCurrentOS, String libraryFileName,
String targetFolder) {
private static File extractLibraryFile(String libFolderForCurrentOS, String libraryFileName, String targetFolder) {
String nativeLibraryFilePath = libFolderForCurrentOS + "/" + libraryFileName;
final String prefix = "snappy-" + getVersion() + "-";
String extractedLibFileName = prefix + libraryFileName;
@ -142,7 +227,7 @@ public class SnappyLoader
String md5sum2 = md5sum(new FileInputStream(extractedLibFile));
if (md5sum1.equals(md5sum2)) {
return loadNativeLibrary(targetFolder, extractedLibFileName);
return new File(targetFolder, extractedLibFileName);
}
else {
// remove old native library file
@ -154,10 +239,10 @@ public class SnappyLoader
}
}
// extract a native library file into the target directory
// Extract a native library file into the target directory
InputStream reader = SnappyLoader.class.getResourceAsStream(nativeLibraryFilePath);
FileOutputStream writer = new FileOutputStream(extractedLibFile);
byte[] buffer = new byte[1024];
byte[] buffer = new byte[8192];
int bytesRead = 0;
while ((bytesRead = reader.read(buffer)) != -1) {
writer.write(buffer, 0, bytesRead);
@ -175,52 +260,46 @@ public class SnappyLoader
catch (Throwable e) {}
}
return loadNativeLibrary(targetFolder, extractedLibFileName);
return new File(targetFolder, extractedLibFileName);
}
catch (IOException e) {
System.err.println(e.getMessage());
return false;
e.printStackTrace(System.err);
return null;
}
}
private static synchronized boolean loadNativeLibrary(String path, String name) {
File libPath = new File(path, name);
private static synchronized boolean loadNativeLibrary(File libPath) {
if (libPath.exists()) {
try {
System.load(new File(path, name).getAbsolutePath());
System.load(libPath.getAbsolutePath());
return true;
}
catch (UnsatisfiedLinkError e) {
throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, e);
}
}
else
return false;
}
private static void loadSnappyNativeLibrary() {
if (isLoaded)
return;
static File findNativeLibrary() {
// Try to load the library from org.xerial.snappy.lib.path library path */
String snappyNativeLibraryPath = System.getProperty(KEY_SNAPPY_LIB_PATH);
String snappyNativeLibraryName = System.getProperty(KEY_SNAPPY_LIB_NAME);
if (System.getProperty(KEY_SNAPPY_DISABLE_BUNDLED_LIBS, "false").equals("false")) {
// Try to load the library from org.xerial.snappy.lib.path library path */
String snappyNativeLibraryPath = System.getProperty(KEY_SNAPPY_LIB_PATH);
String snappyNativeLibraryName = System.getProperty(KEY_SNAPPY_LIB_NAME);
// Resolve the library file name with a suffix (e.g., dll, .so, etc.)
if (snappyNativeLibraryName == null)
snappyNativeLibraryName = System.mapLibraryName("snappyjava");
if (snappyNativeLibraryPath != null) {
if (loadNativeLibrary(snappyNativeLibraryPath, snappyNativeLibraryName)) {
isLoaded = true;
return;
}
File nativeLib = new File(snappyNativeLibraryPath, snappyNativeLibraryName);
if (nativeLib.exists())
return nativeLib;
}
}
{
// Load an OS-dependent native library inside a jar file
snappyNativeLibraryPath = "/org/xerial/snappy/native/" + OSInfo.getNativeLibFolderPathForCurrentOS();
@ -230,10 +309,22 @@ public class SnappyLoader
System.getProperty("java.io.tmpdir"))).getAbsolutePath();
// Extract and load a native library inside the jar file
if (extractAndLoadLibraryFile(snappyNativeLibraryPath, snappyNativeLibraryName, tempFolder)) {
isLoaded = true;
return;
}
return extractLibraryFile(snappyNativeLibraryPath, snappyNativeLibraryName, tempFolder);
}
}
return null;
}
private static void loadSnappyNativeLibrary() {
if (isLoaded)
return;
File nativeLibrary = findNativeLibrary();
if (nativeLibrary != null) {
if (loadNativeLibrary(nativeLibrary)) {
isLoaded = true;
return;
}
}

View File

@ -24,6 +24,7 @@
//--------------------------------------
package org.xerial.snappy;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
@ -35,37 +36,38 @@ import java.nio.ByteBuffer;
public class SnappyNative
{
native static String nativeLibraryVersion();
public native static String nativeLibraryVersion();
// ------------------------------------------------------------------------
// Generic compression/decompression routines.
// ------------------------------------------------------------------------
native static int rawCompress(ByteBuffer input, int inputOffset, int inputLength, ByteBuffer compressed,
int outputOffset) throws SnappyException;
public native static int rawCompress(ByteBuffer input, int inputOffset, int inputLength, ByteBuffer compressed,
int outputOffset) throws IOException;
native static int rawCompress(Object input, int inputOffset, int inputByteLength, Object output, int outputOffset);
public native static int rawCompress(Object input, int inputOffset, int inputByteLength, Object output,
int outputOffset);
native static int rawUncompress(ByteBuffer compressed, int inputOffset, int inputLength, ByteBuffer uncompressed,
int outputOffset) throws SnappyException;
public native static int rawUncompress(ByteBuffer compressed, int inputOffset, int inputLength,
ByteBuffer uncompressed, int outputOffset) throws IOException;
native static int rawUncompress(Object input, int inputOffset, int inputLength, Object output, int outputOffset)
throws SnappyException;
public native static int rawUncompress(Object input, int inputOffset, int inputLength, Object output,
int outputOffset) throws IOException;
// Returns the maximal size of the compressed representation of
// input data that is "source_bytes" bytes in length;
native static int maxCompressedLength(int source_bytes);
public native static int maxCompressedLength(int source_bytes);
// This operation takes O(1) time.
native static int uncompressedLength(ByteBuffer compressed, int offset, int len) throws SnappyException;
public native static int uncompressedLength(ByteBuffer compressed, int offset, int len) throws IOException;
native static int uncompressedLength(Object input, int offset, int len) throws SnappyException;
public native static int uncompressedLength(Object input, int offset, int len) throws IOException;
native static boolean isValidCompressedBuffer(ByteBuffer compressed, int offset, int len) throws SnappyException;
public native static boolean isValidCompressedBuffer(ByteBuffer compressed, int offset, int len) throws IOException;
native static boolean isValidCompressedBuffer(Object input, int offset, int len) throws SnappyException;
public native static boolean isValidCompressedBuffer(Object input, int offset, int len) throws IOException;
protected static void throw_error(int errorCode) throws SnappyException {
throw new SnappyException(errorCode);
protected static void throw_error(int errorCode) throws IOException {
throw new IOException(SnappyErrorCode.getErrorMessage(errorCode));
}
}

Binary file not shown.

View File

@ -121,15 +121,10 @@ public class SnappyOutputStream extends OutputStream
return; // no need to dump
// Compress and dump the buffer content
try {
int compressedSize = Snappy.compress(uncompressed, 0, cursor, compressed, 0);
writeInt(out, compressedSize);
out.write(compressed, 0, compressedSize);
cursor = 0;
}
catch (SnappyException e) {
throw new IOException(e.getMessage());
}
int compressedSize = Snappy.compress(uncompressed, 0, cursor, compressed, 0);
writeInt(out, compressedSize);
out.write(compressed, 0, compressedSize);
cursor = 0;
}
@Override

View File

@ -24,8 +24,19 @@
//--------------------------------------
package org.xerial.snappy;
import static org.junit.Assert.*;
import java.io.File;
import java.security.ProtectionDomain;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtNewMethod;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.junit.Ignore;
import org.junit.Test;
import org.xerial.util.log.Logger;
@ -33,6 +44,7 @@ public class SnappyLoaderTest
{
private static Logger _logger = Logger.getLogger(SnappyLoaderTest.class);
@Ignore
@Test
public void loadFromSytemClassLoader() throws Exception {
@ -41,8 +53,53 @@ public class SnappyLoaderTest
ClassRealm L1 = cw.newRealm("l1", parent);
ClassRealm L2 = cw.newRealm("l2", parent);
File nativeLib = SnappyLoader.findNativeLibrary();
assertNotNull(nativeLib);
ClassPool pool = ClassPool.getDefault();
CtClass cl = pool.makeClass("org.xerial.snappy.SnappyNativeLoader");
cl.addField(CtField.make("static boolean isLoaded = false;", cl));
String body = "public static void load(String lib) {if(!isLoaded) { try { System.load(lib); isLoaded=true; } catch(Exception e) { e.printStackTrace(); } }}";
cl.addMethod(CtNewMethod.make(body, cl));
ProtectionDomain systemPD = System.class.getProtectionDomain();
byte[] bytecode = cl.toBytecode();
// FileOutputStream f = new FileOutputStream("src/main/java/org/xerial/snappy/SnappyNativeLoader.bytecode");
// f.write(bytecode);
// f.close();
//Class< ? > loaderClass = cl.toClass(parent, System.class.getProtectionDomain());
//_logger.info(cl.getName());
//Class< ? > loaderClass = cl.toClass();
Class< ? > classLoader = Class.forName("java.lang.ClassLoader");
java.lang.reflect.Method defineClass = classLoader.getDeclaredMethod("defineClass", new Class[] { String.class,
byte[].class, int.class, int.class, ProtectionDomain.class });
defineClass.setAccessible(true);
defineClass.invoke(parent, cl.getName(), bytecode, 0, bytecode.length, System.class.getProtectionDomain());
Class< ? > forName = parent.loadClass("org.xerial.snappy.SnappyNativeLoader");
_logger.info(forName.toString());
//Class< ? > snappyClass = L1.loadClass("org.xerial.snappy.Snappy"); // not found
//_logger.info(snappyClass.getName());
}
@Test
public void load() throws Exception {
//SnappyLoader.load();
// Class< ? > c1 = Class.forName("org.xerial.snappy.SnappyNative");
// Class< ? > c2 = Class.forName("org.xerial.snappy.Snappy");
// ClassLoader cl1 = c1.getClassLoader();
// ClassLoader cl2 = c2.getClassLoader();
// Method m = c1.getDeclaredMethod("nativeLibraryVersion");
// m.setAccessible(true);
// String version = (String) m.invoke(null);
// _logger.info(version);
//_logger.info(SnappyNative.nativeLibraryVersion());
_logger.info(Snappy.getNativeLibraryVersion());
}
}

View File

@ -26,6 +26,7 @@ package org.xerial.snappy;
import static org.junit.Assert.*;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.junit.Assert;
@ -294,9 +295,16 @@ public class SnappyTest
byte[] uncompressed = Snappy.uncompress(b);
fail("cannot reach here since the input is invalid data");
}
catch (SnappyException e) {
assertEquals(SnappyErrorCode.FAILED_TO_UNCOMPRESS, e.errorCode);
catch (IOException e) {
//assertEquals(SnappyErrorCode.FAILED_TO_UNCOMPRESS, e.errorCode);
}
// catch (Exception e) {
// Class< ? > c = e.getClass();
// ClassLoader cl = c.getClassLoader();
//
// ClassLoader cl2 = SnappyException.class.getClassLoader();
// _logger.error(e);
// }
}