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

effects of classloader injection and multiple wars in servlet container #24

Closed
bokken opened this issue Mar 19, 2013 · 8 comments
Closed

Comments

@bokken
Copy link
Contributor

bokken commented Mar 19, 2013

What happens if multiple wars in the same tomcat instance contain snappy-java? It would appear that would require that each contain the same version of snappy-java (at least the jni interface must be the same).

Would a better solution to the library problems in a jee environment be to modify the name of the library for each class loader? So in the process of SnappyLoader.loadNativeLibrary method, copy the os/arch specific library to a temp file with a modified name (i.e. libsnappyjava1234.so). Then for that class loader make a static call to System.load(snappyjava1234). The same library may end up being loaded multiple times in the same container, but there will never be any issue with different versions.

@xerial
Copy link
Owner

xerial commented Mar 28, 2013

Native code injection checks whether snappy-java is already loaded by another webapp, so the problem you mentioned would not happen.

@xerial
Copy link
Owner

xerial commented Mar 28, 2013

Current snappy-java appends version number to the extracted native library, and SnappyNativeLoader.java injected to the root class loader can load different versions of snappy-java.

I can say that your proposed solution is partly implemented. But I havent't fully tested this scenario.

@bokken bokken closed this as completed Mar 28, 2013
@bokken bokken reopened this Mar 28, 2013
@bokken
Copy link
Contributor Author

bokken commented Mar 28, 2013

Appending the version to the extracted library may cover my primary concern. Do you change the name of the class which are you are loading via bytecode for each version as well?

I guess I just question the value of the finding the parent classloader and injecting the bytecode. It would allow multiple wars/ears in the same jee runtime to share the same library (if using same version). But it also introduces some complexity in that while wars can be stopped/undeployed it does not appear (at least that I can see) that the injected class(es) can ever be cleaned up. If the library were given a completely unique name when it is copied out to be loaded, then there would be no need for injecting byte code into a parent classloader. Then individual wars being stopped/started/undeployed can clean up after themselves and not impact other wars in the same runtime.

@xerial
Copy link
Owner

xerial commented Mar 28, 2013

The name of injected classes aren't changed.

As you mentioned, unloading injected codes would be difficult. But the current approach solves many other problems, including UnsatisfiedLinkError observed when snappy-java is used in multiple web containers or in different class loaders. Eclipse and various testing frameworks use custom class loaders. Without the native code injection, we cannot use these development tools with snappy-java.

Even if you assign unique names to native libraries, it might be necessary to change the function names defined in the libraries to avoid name collisions.

Changing function names in the c++ library needs re-compilation, and I don't know how to do it without adding complexities to the building process.

@xerial
Copy link
Owner

xerial commented Mar 28, 2013

Java classes and c++ codes must use corresponding function names, so both of them need to be changed to make your solution work.

Is there any example that shows using different library file names can avoid function name collision?

@xerial
Copy link
Owner

xerial commented Mar 28, 2013

I added a small test to confirm whether changing lib file names works:
https://github.com/xerial/snappy-java/blob/feature/jni-multiload/src/test/java/org/xerial/snappy/JNIMultiLoadTest.java

It succeeded in loading different versions of native libraries in separate class loaders. Great!
If I load the same native lib in different class loaders, it throws UnsatisfiedLinkError.

I haven't noticed to such a simple solution.
Is there any documentation or article for this technique?

xerial added a commit that referenced this issue Mar 28, 2013
@bokken
Copy link
Contributor Author

bokken commented Mar 28, 2013

What I believe should work is having SnappyNative actually have a static block that determines the appropriate native library to load, copies it to a unique location in the file system, then calls System.loadLibrary with that absolute path.

@xerial
Copy link
Owner

xerial commented Mar 29, 2013

Thanks for the suggestion, and it makes simple the native lib loading part.

Merged in to #27

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

No branches or pull requests

2 participants