Dynamically loading a JAR on a maven based project - java

I am trying to fix this exception: Cannot load 64-bit SWT libraries on 32-bit JVM
My project is maven based and I declared both dependencies (SWT 32 bit and SWT 64 bit) in the pom.xml file.
I am trying to dynamically load the correct JAR based on the Java architecture data model (sun.arch.data.model property) using the following function:
private static synchronized void loadLibrary(File jar) {
try {
URLClassLoader loader = (URLClassLoader) ClassLoader.getSystemClassLoader();
URL url = jar.toURI().toURL();
for (URL it : Arrays.asList(loader.getURLs())) {
if (it.equals(url)) {
return;
}
}
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(loader, new Object[]{url});
} catch (Exception e) {
System.out.println("error");
}
}
The problem is that I don't know how to specify the path to the JAR. I see the JAR is downloaded in the .m2 folder but I guess that I can't specify that path. My guess is that I should specify the path to the Java cache were JNLP will download the JARs. Am I correct?

I would create separate 32-bit and 64-bit versions of your artifact. This can be achieved by wrapping the swt dependencies into profiles (you could call them 32bit and 64bit) and then activate the suitable profile. You can then produce two artifacts of different name or version (or classifier).

I solved the problem by doing this: I have downloaded the 32 and 64 bit jars and put them in the resource folder of my project (/swt/swt_x86.jar and /swt/swt_x86_64.jar). Then, in the places where I needed the jar I used the function mentioned in the subject to load it based on the Java architecture.

Related

IntelliJ, JInput and the java.library.path

I'm working on a java project that uses both Jogl and JInput, and I working in IntelliJ. I'm having some issues with the application not being able to find various DLLs. I know the recommended way is to extract the DLLs to a folder and then point the java.library.path at that folder. Is there a way to include those libraries in project configuration somehow? I'm pulling those files from jCenter, and I'd rather just point the jar files and let JNA do its work.
I use this method below to set the path dynamically just before the DLL is needed by some object. It is called as follows:
setDllLibraryPath("C:/yourPathToDLLs")
Method to set library path
public static void setDllLibraryPath(String resourceStr) {
try {
System.setProperty("java.library.path", resourceStr);
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);//next time path is accessed, the new path will be imported
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}

Load library jars with javassist

I am trying to analyze the code of a java project.
I have the project to be analyzed in a jar that I add to javassist path using insertClassPath function. Everything works fine if I try to access a class form the project.
The problem is that I need to access also the classes from the libraries the project uses.
I tried to add the library to the class path just like i did with the project jar, but I get a NotFoundException so i guess I am not giving the right path.
The code looks like this:
String jarFileName = "C:/Users/diana/Desktop/Test/ckjm.jar";
ClassPool pool = ClassPool.getDefault();
try{
pool.insertClassPath(jarFileName);
pool.insertClassPath("C:/Users/diana/Desktop/Test/ckjm/lib/bcel-5.2.jar");
} catch (NotFoundException e) {
System.out.println("error loading jar!!");
}
I used the harcoded string just for testing purpose. The jar is in the lib folder or the project that was archived to a jar.
I am not sure how can i add a jar that is contained in another jar.
Note: if i keep the library as a separate jar (and give the path like: "C:/Users/diana/Desktop/Test/bcel-5.2.jar") it woks fine
Any help would be appreciated
If your target JAR is inside another JAR, you can use a LoaderClassPath created using a URLClassLoader which is defined using a JarURLConnection URL path of the JAR.
So assume you have a target JAR, inner.jar, embedded inside another JAR, C:/Users/diana/outer.jar.
Let's assume it is in a subdirectory called lib.
The URL of the outer JAR would be file:/C:/Users/diana/outer.jar.
The URL of the inner JAR would be jar:file:/C:/Users/diana/outer.jar!/lib/inner.jar.
You code to load this classpath would be:
URL cpUrl = new URL("jar:file:/C:/Users/diana/outer.jar!/lib/inner.jar");
URLClassLoader cpUrlLoader = new URLClassLoader(new URL[]{cpUrl});
pool.insertClassPath(new LoaderClassPath(cpUrlLoader));

Eclipse: Setting an environment variable that references a folder contained in a plugin

I have some Java code that wraps an existing native application and performs the following:
Takes some input from the user
Executes a native application providing as parameters the input taken in step 1
Performs some more operations on the output files produced in step 2
The native application in step 2 requires some dynamic libraries. So, under Run Configurations -> Environment I have set the following variables to reference the libraries.
DYLD_LIBRARY_PATH = ${project_loc}/path/to/libs
DYLD_FALLBACK_LIBRARY_PATH = ${project_loc}/path/to/libs
And so far it all works. Now I have packaged my code and the existing native application as an Eclipse plugin. Whenever I try to run the code inside the plugin I get the following error:
dyld: Library not loaded: libsrcml.dylib
Referenced from: workspace/Project/src/nativeApp
Reason: image not found
To my understanding, this happens because the environment variables I had set previously reference {$project_loc}, which is the location where my Eclipse project was stored. Now, my code is no longer contained in that project, but it is contained inside a plugin, so the path for the variables no longer works. Question is, how can I set a path that references a folder inside my plugin? Alternatively, is it possible to, somehow, load those variables dynamically inside my Java code?
The path variables are used to specify a fixed location in the file system.
To identify a resource in a plugin, I would use its URL
Case 1: Platform.getBundle("").getEntry("")
Bundle bundle = Platform.getBundle("your.bundle.id");
URL url = bundle.getEntry("yourDir/yourFile.txt");
File f = new File(FileLocator.resolve(url).toURI());
Case 2 : Platform URL to your resource:
url = new URL("platform:/plugin/your.bundle.id/yourDir/yourFile.txt");
File f = new File(FileLocator.resolve(url).toURI());
Thanks to Vogella for this tip.
However, for libraries in your plug-in it is a little bit different, as System.loadLibrary("libname") must be able to resolve your lib.
If you ship and use native libraries in your plug-in, please package your plugin as a directory, and not as a compressed jar file.
So edit your plug-in's MANIFEST.MF and set your Eclipse-BundleShape: dir
Eclipse-BundleShape: dir
Then, your plug-in will be packaged as a folder, and then it is your responsibility to make your Native libraries interacting. Usually this depends on how the native libraries are linking each other, and on how your Java-to-native framework is setting the search paths.
My simple solution, is putting all the native libraries to the root folder of the Eclipse executable, which is the Java execution directory, so that I can get that path using the "user.dir" environment variable as follows:
System.getProperty("user.dir");
Then, when all the natives are in the same folder, they can reference each other without problems.
Please, also check these resources:
this StackOverflow answer
this eclipse forum answer

How to read file with different canonical paths

I am making an java application which reads a file from a particular location. The location of the file is in the folder retrived from
getCanonicalPath().
The problem i am facing is that when i am running my application in Eclipse the canonical path is different from the one which Dr Java sees. So, what should i do before delivering my application to the client to make sure that it sees the file no matter which ide/command prompt is used to run the application. Obviously it would not be a good idea to copy the same file across all possible folders to cover different possibilities of getCanonicalPath.
Thanks
One of the solution is to have this file in your classpath and load it from your classpath, with a code like
URL url = getClass().getClassLoader().getResource(path);
if(url != null) {
try {
return new File(url.toURI().getPath());
} catch (URISyntaxException e) {
return null;
}
}
This is standard if this file is a configuration file. Usually in a standard java project layout you put this in the folder src/main/resources.
If this is more of a data file, you should put in a configuration file its path, and have different configurations, one for your station and one for production on the client machine. Of course in this case the configuration file is in the class path ;).
A common solution is to place the file in a directory which is in the class path. If you use getResource or getResourceAsInputStream you can find the file regardless of where it is provided its in the class path. if you use maven you can be sure how the classpath is setup regardless of the IDE used.
You should always load file ClassLoader using API like Test.class.getClassLoader().getResource(name),Test.class.getClassLoader().getResourceAsStream(name) More Information available here

Setting CLASSPATH during runtime

How do I set a CLASSPATH variable during runtime while using IKVM?
I've been trying to do it by using:
java.lang.System.setProperty("java.class.path", "whatever");
The class I'm calling requires a configuration file in the classpath to work - and I keep getting errors that seem to indicate that it hasn't gotten its settings.
Is the way I'm trying to add variable incorrect?
If you really can't set the classpath beforehand yourself using the java's -cp or -classpath argument (why not by the way? that's the normal approach), then you can try to use URLClassLoader instead. Here's a kickoff example:
URL url = new URL(whateverPath);
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
ClassLoader urlCL = URLClassLoader.newInstance(new URL[] { url }, contextCL);
Thread.currentThread().setContextClassLoader(urlCL);
// ...
You only need to be lucky if the class you're calling is actually loading its resources through Thread.currentThread().getContextClassLoader().getResource() and thus not through
SomeClass.class.getClassLoader().getResource().
I was trying to do the same thing. I had some jar files compiled to a .Net dll but some of those (3rd party) jar files were trying to load their configuration files from the java classpath.
I solved the problem by specifying the -classloader option for the ikvmc tool. Example:
ikvmc -out:mydotnetapp.dll -classloader:ikvm.runtime.ClassPathAssemblyClassLoader c:/myjavaapp/lib/*.jar
This worked for me!
Source for the solution: http://old.nabble.com/Not-able-to-load-files-from-ClassPath-td31141788.html

Categories

Resources