I have a project name: examplePrj.
This projects contains 3 jar (which includes in the build path of examplePrj)
the 3 jars are: A.jar, B.jar, C.jar
Let say that A.jar and B.jar contains tbd.jar.
And we said that examplePrj contains A.jar and B.jar
Does tbd.jar will be included twise ?
Is there any influence on the performance ?
Same as Q1, but in addition the project examplePrj contains the tbd.jar (total 3 includes)
?
First thing to note here is that classes inside the JARs are loaded by the classloader.
Now considering that tbd.jar has same classes inside it, Oracle will load these classes only once. The order in which you specify multiple class path entries is important. The Java interpreter will look for classes in the directories in the order they appear in the class path variable.
Related
It worth to mention that I am using maven as my build management tool. I have a jar (let's call it dep.jar) which will be included into the final project (final.jar) as dependency.
dep.jar has a class with main method.
I need to have several entry points (classes with main methods) within my final.jar's top level directory so I can use entry point depending on my need. Including one from dep.jar.
I considered:
Changing META-INF/MANIFEST.MF file within jar. As Oracle stated that is not possible to reference main classes inside jar's dependencies (BOOT-INF/lib directory) -> https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html;
Uber jar - not an option, I am dependent on jar directory structure inside Java code base
Using special class loader like this one http://www.jdotsoft.com/JarClassLoader.php. But it implies changing final.jar's main method which I cannot do due to project restrictions.
Using maven-dependency-plugin but it can unpack inner jar (dep.jar) and copy classes to maven working directory target which during packaging phase will be packed to BOOT-INF/classes directory. Again, I cannot reference main classes from there. If I unpack and copy them somewhere different than target - copied classes will not appear in my final.jar
Is there any other plugin or option how to add classes from final.jar dependant jar dep.jar during JAR build to final.jar's top level?
EDIT:
final.jar project looks like this:
final.jar
|_______BOOT-INF
|_______lib
| |_______dep.jar (contains main class I want to invoke)
|_______classes
|__________dir (directory I want to copy on demand with help of CLI)
I found a solution here Spring Boot - How to specify an alternate start-class? (Multiple Entry Points). Ended up using -Dloader.main property when launching jar.
Command line looks like these: java -jar -Dloader.main=<main_class> ./final.jar
I'm having troubles compiling a mixture of clojure and java files into a single package. The files have dependencies between each other and if they were all just java files the java compiler could handle all of this. Just to make this concrete I want to create a package called pkg with 4 files, A.java, b.clj, c.clj, and D.java. A.java contains main and creates an object declared in b.clj, b.clj calls functions in c.clj and uses objects of class D. How do I write the project file?
If I use
:prep-tasks ["javac" "compile"]
in the project file then I get a complaint while compiling A.java that something in pkg.b or pkg.c is undefined. If I use
:prep-tasks ["compile" "javac"]
I get a complaint that class pkg.D does not exist. If I try
:prep-tasks [["javac" "pkg/D.java"] "compile" "javac"]
it can't find pkg/D.java, even though I set java-source-paths correctly.
One way to handle this would be to create 3 packages, one that contains A.java, one that contains b.clj and c.clj, and one that contains D.java. Then build a jar for D.java, a jar for b and c, that uses D.jar, and a jar for A that uses bc.jar and D.jar. Ugly, though.
You cannot have circular dependencies between the java and clojure sources in a single lein project. As you correctly point out, you could split the project in more than one package to avoid the circular dependency, but you don't need 3 packages but just 2, as lein supports Clojure -> Java dependencies. So you could have a project with b, c and D and another one with just A.
Another option would be just to write A in Clojure so you avoid the burden of multiple projects.
I plan on becoming a certified Java programmer and am studying from the Sierra-Bates book. I had a question about classpaths. Do classpaths need to find only the supporting classes of the class I'm running/compiling, or the supporting classes and the class itself? Also, when I'm getting classes in packages from classpaths, is it legal to just put the adress of the file(the path to it), instead of putting it's root package. Thanks.
1 - a classpath has to give access to each class that needs to run in your program. That would include the main class and any classes it calls and those they call. If there is some code in one of those classes that is never called, in many cases, you don't need to have the classes referenced by the uncalled code.
2 - you have to put the root of the packages in the classpath. So a class "com.bob.myprog.Main" would need to have the class path point to the folder where the "com" package/folder lies. It will need to contain a "bob" folder and "bob" will need to contain a "myprog" folder with "Main.class" in it.
Classpath has to contain both the supporting classes and the class itself.
However, sometimes you can run a single file without specifying classpath (and it will work).
As specified in http://docs.oracle.com/javase/tutorial/essential/environment/paths.html :
The default value of the class path is ".", meaning that only the
current directory is searched. Specifying either the CLASSPATH
variable or the -cp command line switch overrides this value.
Therefore, if you have a class MyClass compiled in the current directory, the following will work:
java MyClass
while pointing classpath to another directory will lead to an error (classpath no longer contains MyClass):
java -cp lib MyClass
When you have a class in a package, it is not enough to put the address to the class file in the classpath. According to SCJP Sun Certified Programmer for Java 5 Study Guide:
In order to find a class in a package, you have to have a directory in
your classpath that has the package's leftmost entry (the package's
"root") as a subdirectory.
A have jar B in build path,
B have jar C in build path,
Can I use classes in C in A ?
Thanks in advance
If you have A, B and C in your class path you can use any of these classes from any other class. All you need is a reference or a reference to a reference etc.
I think you may need to distinguish between building these jars and the subsequent usage.
e.g. you can build jar B referencing jar C, but the two would need to be deployed together. If you don't then in your build for jar A, you reference jar B, but it wouldn't work without jar C.
Your build could alternatively take the code for B, and package it together with the contents of jar C. Then you could use B and C together in A.
This dependency management can become quite complex (as you can see). Packaging code together such that you don't have to provide multiple jars makes life easy (you only reference one jar), but it makes upgrades a pain (you can't upgrade, say, one common lib). Tools like Maven provide options for dealing with this (do I need this jar for compilation only, do I package it with my program, is it used for testing only etc.)
having jar b and jar c in build path is not enough.
You can use any of these options to achieve what you want:
add a new line in jar b manifest containing
Class-Path: c.jar
add a new line to jar a manifest containing
Class-Path: b.jar
java -cp a.jar;b.jar;c.jar yourfullclassname
I would like to build a Jar whose main class package is not at the root of the jar.
In the application, I've just written a Main class
com.gmail.bernabe.laurent.test.HelloWorld
I could simply make a Runnable jar from the Eclipse IDE, but I would like to go a step further
=> Having the final jar organized like this
Root
=> META-INF
=> Lib
=====> com
==========> gmail
...
Instead of :
Root
=> META-INF
==> com
======> gmail
...
Is it possible to configure the Manifest file so that the Jar runs properly ?
Thanks in advance
Why do I want to do this ?
I want to build a JOGL-based jar organized as follow
=> JOGL (subdirectories are JOGL just needed files)
=> CORE (subdirectorie is the core application package)
=> LAUNCHER (subdirectory is the custom classloader package)
=> META-INF
Yes and no.
No, because you should not do that: imagine someone supporting your code. Or even yourself, two years later, returning to the project: you saw hundreds of jars organised as defined by JarClassLoader, you worked in tens of "usual" projects... Now, well, now you see a JAR file. Will you expect it to have a tricky custom loading scheme? I doubt so.
Yes, because you can add one more main class, use it to set up a classloader, and after that load classes from any layout. You will need to keep manifest and the startup class at the "proper" places, though.
The tutorial on class loading can be found at http://java.sun.com/developer/onlineTraining/Security/Fundamentals/magercises/ClassLoader/help.html