I need a way to load library inside a jar file without extracting it. Is there a way I can use a method like getClass().getResourceAsStream("xxx")
structure will be as follows:
myjar.jar
- lib/
- <somelib>.<libext>
- <package>
- Foo.class
Where the Foo.class will be the class that loads and connect to the native library and method should also work if the lib folder was inside the <package>
No, there is no way to load library from inside of a jar file without extracting it first, you need to extract the library at least into tmp folder in order to be able to load it using eg:
System.load("path/to/libAbc.so")
It is not currently possible in java to load the library from memory or zip file. The method that loads the library is native void ClassLoader.NativeLibrary.load(String name), also the name of the library is used internally by the java.lang.ClassLoader to keep the track of loaded libraries, so currently you can't use anything different than a real file to be loaded as native library because it wouldn't fit the current mechanism.
Since the loading of the native library is done with the help of native code, the answer depends if there is a way to load the native library in a C code: dlopen from memory?
Theoretically it can be done, but bacause it is platform specific and have many aspects that needs to be considered and resolved it isn't implemented in Java and it isn't a standard and/or easy thing in C either.
Currently in java, there is no way to do it, this could change if someone will create such a native library that will do that, but for now I don't know any such library.
Also sci-java native lib loader handles this (although it extracts it behind the scenes).
You may want to try it: https://mvnrepository.com/artifact/org.scijava/native-lib-loader
You can't do it without putting it somewhere (at least some temporary location).
You can take a look here:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo031
This recipe gives you a template that will take your native library from jar, extract it, and load inside your Java code.
Have fun with JNI!
Related
In order to create a valid .class file, every method has to have a full internal name and type descriptors associated with it. When procedurally creating these, is there some sort of lookup table one can use (outside of Java, where a ClassLoader can be used) to get these type descriptors from a method name? For example, how would one go from Scanner.hasNextByte to boolean java.util.Scanner.hasNextByte(int) / boolean java.util.Scanner.hasNextByte() (or even from java.util.Scanner.hasNextByte to boolean java.util.Scanner.hasNextByte(int) / boolean java.util.Scanner.hasNextByte())? The above example has overloading in it, which is another problem a human- but mostly computer-readable declarations file would hopefully address.
I've found many sources of human-readable documentation like https://docs.oracle.com/javase/8/docs/api/index.html containing uses of each method, hyperlinks to other places, etc. but never a simple text file or collection of files containing just declarations in any format. If there's no such file(s) don't worry about it, I can try and scrape some annoying HTML files, but if there is it would save a lot of time. Thanks!
The short answer is No.
There isn't a "header file" containing the class and method signatures for the Java class libraries. The Java tool chain has no need for such a thing. Nor do 3rd-party Java compilers, or compilers for other languages that rely on the Java SE class libraries.
AFAIK, there isn't a 3rd-party tool that builds such a file or an equivalent database or in-memory data structures.
You could create one though.
You could chose an existing Java parsing library, and use it to build parse trees for all of the source files in the class library, and emit the information that you need.
You could potentially create a custom Javadoc "doclet" plugin to emit the information.
Having said that, I don't understand why you would need such a mapping. Surely, your IDE does this already ... and exposes the information via some internal API. And if this is not for an IDE plugin, what it is for?
You commented:
I'm making a compiler for a JVM-based programming language ....
Ah ... so your compiler should do what other compilers do. Get the information from the ".class" file. You can either load the class using a standard or custom class loader, or you can use a library like asm or bcel or javassist ... which can read a ".class" file without loading it.
(I haven't checked, but I think the standard javac compiler uses an internal API to do this.)
Note that your proposed approaches won't work for interfacing with 3rd-party Java libraries where the source code is not available and/or the javadoc is not scrapable.
What about building it from the source files for the standard library?
The Oracle Java 8 API web pages you referenced was created by Javadoc processing of source files for the Java standard library.
If you use an IDE with a debugger, there is a good chance you already have much of the standard library source code downloaded. After all, if you set a break point, and then follow the program step-by-step with "Step into", you can trace the execution of the program into standard library methods. The source files would be part of the JDK.
However, some parts of the standard library source might not be available, due to licensing restrictions.
I can access Java class and methods when executing xquery with Saxon when they are declared correctly (through namespace pointing to package and class) but I wonder if there is a way to create a kind of "dynamic" class path at each run to load external jar file and search classes in it instead of in the current project/program classpath (as I cannot add all possible class in it).
So for instance I have something like :
declare namespace dpr="java:com.*****.atm.dpr.common.util.DPRConfigurationLoader";
declare variable $rules as node()* := doc(dpr:getApplicationProperty('Common','RulesFileLocation'))//category;
I can replace the path the real class with an emulated version but it means I must create each possible class on my side (not really a good way as it means a "patch" for each new java call...).
So if I provide a jar containing the classes I need is there a way to load it so that the namespace point to it ?
I know I can load .class file if they are on classpath, but 3 jar files entirely ?
Thanks.
Technically, Saxon doesn't require external classes to be on the classpath - it requires them to be accessible using the appropriate ClassLoader. If you understand ClassLoaders and are prepared to write your own or configure third-party offerings, then you can load classes from anywhere. All the hooks are there in Saxon if you want to do such things; but there's nothing packaged with the product.
Some of the thing you could try include:
With Configuration.setDynamicLoader() you can change the way Saxon does dynamic loading of external classes, including the classes used for Java extension functions.
With Configuration.getDynamicLoader().setClassLoader() you could provide a different ClassLoader for loading classes, for example a URLClassLoader.
With ProfessionalConfiguration.setExtensionBinder("java", XXX) you could register a customized JavaExtensionLibrary, typically as a subclass of the standard one, allowing you to change the way URIs are mapped to Java classes and the way methods are selected (for example)
This is all very low-level system programming and is not for the faint-hearted.
I need to redefine a single class file in a spring-boot application from an external library io.external.library until they update their code. I have this working by creating a single file with the same package name and class name in my own project.
src/main/java/io/external/library/TheirFile.java
I am a bit worried that this just happens to work and in different conditions the original file might be loaded into memory.
I have seen that there may be ways to achieve this in Gradle by unzipping and repackaging the jar file. This seems to be a bit of an overkill to me though considering this is a temp solution until the third party updates their code.
What is the simplest or best practice way to achieve this?
It is a spring-boot application and my build system is Gradle.
I've written a bunch of android JNI code that I want to make into a library for a customer. Obviously, I don't want the customer to be able to see my JNI code. Is there a way I can include just the so file in a library project for them?
I've tried just using System.loadLibrary(<library>); but I get an Unsatisfied Link Error every time.
One thing that's worked, is I've just compiled my project and deleted all the c files. I'm still able to use the .so file, but if I do a make clean, it deletes my so file and there's no way to recover it without the source.
In short, what I want is to be able to compile an so file on my own, and give it to my customer with some java code that interfaces with it. I don't care if they see the java 'wrapper' source but I don't want them to be able to see the JNI code. I also want them to be able to treat this library as they would any other (ie make cleans don't wreck it).
Thanks!
Is there a way I can include just the so file in a library project for them?
Package an AAR containing the libraries, and host the AAR as an artifact for your customers. See my CWAC-AndDown library for an example. The AAR will contain your .so files for whatever architectures that you are supporting, plus a JAR of the compiled Java code that provides your Java API to the native code.
I also want them to be able to treat this library as they would any other (ie make cleans don't wreck it).
Well, by definition, make clean requires source. It also requires a makefile, which presumably you will not distributing, since that's useless without the source.
Suppose that I want to prevent trivial disassembly of jar/class files.
A JVM is started from a C++ application that can descramble the jar/class files that are stored within its own executable. Is there a way of somehow streaming the contents of such files to a JVM without saving them on disk?
I'm looking for a solution on both windows and unix platforms.
You can create a ClassLoader which gets its class data from anywhere. You could even have it call native methods to obtain byte code for a class. Have a look at URLClassLoader which is widely used, it can obtain it's classes from files on disk or the network or any supported URL.
Think part what you're after is supplied by the JarInputStream class, Docs
You'd need some custom class-loading behavior as well. May need to create a Classloader implementation that loads your classes as well if you go that route. It might be simpler to use the URLClassloader as well depending on your circumstances.