I have some minor issue with class loading. I have a jar say abc.jar and under that jar there is another jar called libs/cde.jar. I had written a a class in that jar that used the cde.jar. I packaged the abc.jar correct and inspected that the dependent jar was correctly packaged under /libs/cde.jar.
However, when I try load the jar (abc.jar) and execute the class which depend on cde.jar, it cannot find that dependent cde.jar. Any pointer as to how I can do it? I cannot use other jar loaders like OneJar, etc. I have to do it with pure java class loading if possible. I tried putting it in the classpath by using "file:////C:/abc.jar!/libs/cde.jar" without any success
Thanks
Masti
Java can't, by default, deal with embedded Jars (ie Jars within Jars)
If you really want this type of behavior, you should take a look at OneJar
Otherwise you will need to leave dependent Jars externally and specify there dependency via the parent Jar's Class-Path attribute in its Manifest file
Related
I inherited all these classes that have no package, and the only way I can make this work is to put all these in the root directory where I run my class program. The issue is that this pollutes the directory and it's not a clean installation. Since these classes were already compiled, I cannot change the package. Is there a way to put these classes in a directory and have Java find them in the classpath?
Since you have them only as bytecode, you are using them more or less like a libray. So why not generate a jar file out of them?
jar cf jar-file-name input-files-or-dirs-with-wildcard
Then you can put this jar-file wherever you want, you just need to add it to your classpath and your root-directory is no longer polluted.
Let's assume I have two jar files on classpath when building my project - myJarFile.jar and myJarFileOld.jar. They contain the same packages and the same classes, but the myJarFileOld.jar contains old implementation, which causes that the compilation fails. I'm not asking for solution of this error, I know that I should remove myJarFileOld.jar to make compilation work. However I'd like to know, what mechanism decides which class from which jar file is used during compilation, when both jar files are present?
When a class needs to be loaded, all jar files in the classpath, in order, are scanned. As soon as the class is found, it's loaded.
Not fully sure, but I believe the order of classpath appearance is deciding. If it's found in first jar, then it's not search in another. However I'm pretty sure that class loader will load both jars at the beginning, and you will get some errors about duplicate code. However I'm not sure this, this is probably related to runtime environment.
you have this feature in Eclipse where you can specify the ordering of the jars that you want to be executed from the project classpath.Go to
Project->Select Properties->Select Build Path from left pane-> go to Order and Export Tab->Select Top or Bottom button-> click ok.
The next time you build your project the jar from the classpath will be picked in the order that you have specified.
I have a jar containing the main class of a project. This depends on several other jars that reside in a lib directory. One class of such a dependend jar loads a ressource "/Data/foo/bar/file.txt". But loading this file as ressource leads to null.
Here is the directory structure:
./main.jar
./lib/lib1.jar
./lib/lib2.jar
./lib/lib3.jar
./lib/runtimedata/Data/foo/bar/file.txt
This is the classpath of the manifest.mf of the main.jar:
lib/lib1.jar lib/lib2.jar lib/lib3.jar lib/runtimedata
I start the application via
java -jar main.jar
The lib2.jar contains a class that tries to load the file with
ThatClass.class.getResource("/Data/foo/bar/file.txt");
But that happens to be null. Why? lib/runtimedata is in the classpath.
I even tried to put the Data directory into lib/lib/runtimedata, in case the path is relative to the jar file containing the loading class. But that doesn't help.
What am I doing wrong here?
EDIT:
Running the application with
java -cp main.jar:lib/*.jar:lib/runtimedata my.package.Main
works correctly.
EDIT 2:
I cannot change that lib that does the resource loading. I am only using that lib. The only things I can change is the main.jar the classpath and the command line.
When you start the path with a "/", it's considered as absolute. Try ThatClass.class.getResource("/runtime/Data/foo/bar/file.txt");
Otherwise, if you cant't change the code, put the file on /Data/foo/bar/file.txt
In a development environment, this can sometimes happen when resources have not been processed during the build. Using Gradle and building your main JAR or main test JAR will depend on the compileJava tasks in your libs, but will not trigger their resources to be processed. You can see if this is happening by looking in your build dir to see if resources for your libs have been copied over. If they haven't been copied the resource loader won't find them at runtime.
If this is the problem, a full build will fix the issue and published JARs should always have their resources. But, it's nice to be able to trigger e.g. the test task for an individual module and know that it will always pull in everything it needs. If you have a library with essential resources that must always be present, you can force them to be processed in partial builds by adding this to the build.gradle of the library:
compileJava.dependsOn(processResources)
Consider a Java program, launched from a main method, that needs something from tools.jar. In this case, some utility code for connecting to JMX services. Do we have any choice but to wrap it in a shell script that uses -cp to manage the class path? We'd much rather use a MANIFEST.MF classpath.
from http://java.sun.com/developer/Books/javaprogramming/JAR/basics/manifest.html
the URLs in the Class-Path header are given relative to the URL of the JAR file of the applet or application.
I do not believe you have a choice about using a shell wrapper to get the tools.jar on your classpath. unless you write some custom classloader internally to allow you to find external jars.
If incorporating classes from the dependency jar is an option, I'd go with creation of a "Runnable JAR file". Basically you extract the classes from it and put them with your own classes in the JAR. That eliminates the need for a wrapping script.
To do that in Eclipse, select your project, File -> Export -> Java -> Runnable JAR file; that option will require that you have executed the main class at least once to know what profile to run when you actually run produced JAR.
I am trying to use ant to build an application, run the application's main() method, run junit tests, and package everything in a jar file (source+build+libraries+build.xml). The classes include a runner class with a main() method entry point.
The objective however is to inlcude all libraries used, like junit.jar, and the ant build.xml itself.
I was wondering if there is a way for the executable jar file, to run selected targets of the ant build file itslef, instead of just the main() method. Obviously I wouldn't need to run the compile targets again, but only the main() method (the java element in my run target) and the junit target. Is that possible?
Many thanks in advance for the insight!
"Executable jar" is not what you think it is. It allows you pack all your classes together (you can add source to it as well though I see little point in that) and declare a main class using Main-Class attribute in the jar manifest. Details are here.
You can then launch that jar using "java -jar my.jar" command line which would invoke main() method of the class you've specified. You can also specify classpath via Class-Path attribute in the manifest file that can point to other jars needed by your application. That DOES NOT MEAN those jars are archived within your jar; in fact if you were to do that, JVM won't be able to load classes from those jars unless you were to take special precautions and write a custom classloader.