Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LoadNativeLibrary doesn't handle java.lang.reflect.InvocationTargetException #12

Closed
xerial opened this issue Sep 6, 2012 · 0 comments
Closed
Labels
bug

Comments

@xerial
Copy link
Owner

@xerial xerial commented Sep 6, 2012

Remove the native libraries from the Snappy.jar file (to simulate not being able to load the native libraries for some reason)
Compile and run the attached test program.

What is the expected output? What do you see instead?
Expected the test code to catch the exception, instead java snappy throws:
java.lang.reflect.InvocationTargetException

java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.xerial.snappy.SnappyLoader.loadNativeLibrary(SnappyLoader.java:317)
at org.xerial.snappy.SnappyLoader.load(SnappyLoader.java:219)
at org.xerial.snappy.Snappy.<clinit>(Snappy.java:44)
at testSnappy.<init>(testSnappy.java:12)
at testSnappy.main(testSnappy.java:6)
Caused by: java.lang.UnsatisfiedLinkError: no snappyjava in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1758)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1045)
at org.xerial.snappy.SnappyNativeLoader.loadLibrary(SnappyNativeLoader.java:52)
... 9 more
Exception in thread "main" org.xerial.snappy.SnappyError: [FAILED_TO_LOAD_NATIVE_LIBRARY] null
at org.xerial.snappy.SnappyLoader.load(SnappyLoader.java:229)
at org.xerial.snappy.Snappy.<clinit>(Snappy.java:44)
at testSnappy.<init>(testSnappy.java:12)
at testSnappy.main(testSnappy.java:6)

What version of the product are you using? On what operating system?
snappy-java-1.0.4.1 Debian Squeeze for Raspberry Pi

Please provide any additional information below.
I'm fairly sure this is thrown by loadMethod.invoke(null, "snappyjava"); in loadNativeLibrary (SnappyLoader.java) around line 317

The fault manifested itself tracking issue 4400 in the apache cassandra project

https://issues.apache.org/jira/browse/CASSANDRA-4400?focusedCommentId=13406480#comment-13406480

Migrated from http://code.google.com/p/snappy-java/issues/detail?id=46


earlier comments

kimchy said, at 2012-07-22T20:30:26.000Z:

It would be great if the print to System.err will be removed in the next version, and let the calling code to handle it.

bradford.powell said, at 2012-08-15T18:20:53.000Z:

Comment 1 points at a use case that calling code may want to be informed of problems with initialization and respond (which may be by not using snappy, using an alternative method, logging/informing the user...). Specifically, an example is the picard project (picard.sourceforge.net) where snappy-java is used (via reflection) if available. If not, then the fallback is to not use compression.

In order to determine at first use of their snappy wrapper (net.sf.samtools.util.SnappyLoader) whether the library is available and can be loaded, thy had used LoadSnappy.load() (which is no longer available in 1.0.4, and the similar method in org.xerial.snappy.SnappyLoader is not public).

Initialization of org.xerial.snappy.Snappy could occur at a defined time using reflection by calling Class.forName("org.xerial.snappy.Snappy"), but any exceptions generated are swallowed because loading of the native library occurs in the Snappy static initializer (and static blocks cannot throw checked exceptions).

I see two potential ways to address this use case:

  1. Allow some public static method to ensure that the native library is loaded (and throw and exception if loading is unsuccessful).
  2. Throw an ExceptionInInitializerError if an Exception occurs in the static block of org.xerial.snappy.Snappy. This would allow the Error to be caught and handled if Class.forName is used, but I'm not sure that the effect for programs using the library without reflection would be ideal.

I attached a patch for option #2. Are there other ideas/singleton tricks that could be used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.