Compiling from command line doesn't use libraries - java

I'm working on a project where I need to compile .java files 'automaticly'(So not using Eclipse)
And now I have some trouble with the libraries that are required by the sources that I compile.
The problem is that the compiled code extends a class which is inside a library.
I've added classpaths, and made sure the libraries where actually in the correct directory.
But it doesn't seem to be able to run.
I get an error which says that the class can not be found or loaded.
I modified the test source so that it doesn't extend. And then it does work.
How do I make the compiled class be able to actually use the classes from libraries in the class path?
I use this to compile:
javac -d /bin -cp kit.jar src/com/indieveloper/kittest/*.java
The class files compile with no error, and also in the correct package hierarchy
This is the manifest:
Manifest-Version: 1.0
Class-Path: .;lib/kit.jar
Created-By: Me
Main-Class: com.indieveloper.kittest.Main
The folder lib with the jar is in the same folder where the final packed .jar also ends up
Which I build using this code:
jar cvfm test.jar manifest.txt -C bin/ .
The inside of the final jar seems okay to me:
META-INF/
META-INF/MANIFEST.MF
com/
com/indieveloper/
com/indieveloper/kittest/
com/indieveloper/kittest/Main.class
The manifest is still correct(Nothing changed the manifest during 'jarring')
I also tried putting the lib folder with the jar inside the final jar, but that was a hopeless attempt..
The exact error:
java -jar test.jar
Error: Could not find or load main class com.indieveloper.kittest.Main
Does anyone know I can do to make it work?

Related

External Jars in VS code

I have a program written in java using Eclipse. For some reason that I won't write here, I decided to move to VS Code. If I run my code in debug mode, all works, but, when I want to export as jar file some errors comes out.
Some information:
- The program is composed by several classes.
- I use 3 external jars included via Eclipse.
- If I run the code with the extension 'Java extension pack - microsoft' all works. Compiling via terminal with
javac MyApp.java
it doesn't compile. (It doesn't find some classes belonging to external jars)
- If I use
jar -cvfm MyApp.jar manifest.txt *.class
where *.class are created by compiling via 'Java extension pack' the error is 'Unable to find or load the main class'
- I'm using a MacBook Pro and the last version of VS Code
What do I do wrong? Which more information you need to help me?
Let's say your project has app package. Under that a App.java class resides which has the main method. Now after building the class files let's assume the class file folder structure is
bin
|app
|App.class
Now go to the bin folder and copy the manifest.txt file in bin folder. manifest.txt file must contain Main-Class . here app.App is the name of the Main-Class.
Main-Class: app.App
Note manifest.txt file must be ended with a new line or carriage return . After Main-Class: app.App put a new line at least.Now run this command from the bin folder
jar cfmv App.jar manifest.txt app/
then test the Jar with
java -jar App.jar

jar throwing NoClassDefFoundError

I've got a project that is structured liked so:
root/
-- lib/
---- commons-cli-1.2.jar
-- src/
---- my/package/name/*.java
-- bin/
---- my/package/name/*.class
-- .classpath
-- .project
-- manifest.mf
The *.class files in bin/ are made by Eclipse each build. My .classpath has the lib/ included and compiles just fine; it also runs as a "Java Application" just fine with my current stubs.
The issue comes about when I try to create a JAR and include the lib/ dependencies. From the command line I've been issuing:
jar cvfm prog.jar manifest.mf -C bin/ .
The program builds, and then when I try to run java -jar prog.jar, I get:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/cli/Option... (there is more, but I cant copy from the other machine)
My manifest.mf looks like:
Manifest-Version: 1.0
Main-Class: my.package.Main
Class-Path: ./lib/commons-cli-1.2.jar
Seems to me that the Class-Path isn't being included and the JAR cannot find the classes contained in the commons-cli-1.2.jar. I've isolated this to JAR creation, since I can run the compiled classes with no issue.
What am I doing wrong when creating the JAR and including the lib/*.jar?
I have had issues with specifying classpath in the manifest file before. If I were you, I would skip referencing the required libraries in the manifest file and instead include them directly inside your jar. Eclipse allows you to easily do this link
You probably assume that the build process should pull the commons JAR into the new that holds your classes. Wrong assumption.
The default Java approach is that you only include your classes in your jar. But instruct your users that they need to have the commons jar in their class path as well!

Is it possible to have a jar Manifest to use all jars in a folder

I'm trying to set a jar manifest so it loads all the libraries (jars) within a folder next to the jar.
The manifest looks like this:
Manifest-Version: 1.0
Class-Path: libs/
Main-Class: path.to.my.class.Main
The layout is as follows:
- MyJar.jar
- libs/
-----lib1.jar
-----lib2.jar
And I'm trying to run like this:
java -jar MyJar.jar
And I get NoClassDefinition errors about classes in the jar within the folder.
In case someone is curious, this folder might contain optional jars that are processed during class loading. That' swhy I can't use the hardcoded or autogenerated ones.
Any idea?
Update
Rephrased the question as this is not currently possible from the manifest itself. The answer was the only really viable without the need of extracting the jars, although it also works.
So as a summary the answer is no, this can't be done from manifest file alone if you have unespecified dependencies.
You should define your Manifest classpath as
Class-Path: libs/lib1.jar libs/lib2.jar
See Oracle documentation for more details https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
Try extracting these jars. It looks like you cannot add all jars from directory but you can add all classes. You lose obviously all configuration in manifest, however, if you are interested in jars' code content only, it might work.
I tested that with these simple classes
import pkg.B;
public class A {
public static void main(String[] args) {
System.out.println(B.class.getName());
}
}
package pkg;
public class B {}
now I try to separate the classes. I have jarred them into
$ jar tf libA.jar
META-INF/
META-INF/MANIFEST.MF
A.class
$ jar tf libB.jar
META-INF/
META-INF/MANIFEST.MF
pkg/B.class
no Class-Path in any manifest. I can run A with java -cp libB.jar:libA.jar A. Now I create another jar with Class-Path set to lib/
$ cat manifest
Class-Path: lib/
$ jar cfm empty.jar manifest
my directory tree look like
$ ls -R
.:
A.java empty.jar lib lib.jar manifest pkg
./lib:
libA.jar libB.jar
./pkg:
B.java
Now I try jar
$ java -jar empty.jar
Error: Could not find or load main class A
Hopeless, right? Then I extracted libA.jar and libB.jar into lib (same as [this guy][2]). Now all is fine
$ java -jar empty.jar
pkg.B
java does not know the jar files in the libs directory.
If you are using java 1.6+, You can run program as
java -cp lib/* -jar MyJar.jar

How exactly do I compile my Java into a JAR file?

So I'm trying to compile my game for my Object-Oriented Programming class into a jar file so it can be ran with java -jar javacoffeeadventure.jar.
My folder structure for a folder with java files removed looks like this:
audiomanager/
commandinterpreter/
gamemanager/
io/
logic/
META-INF/
player/
resources/
rooms/
main.class
Everything is packaged under javacoffeeadventure. For example, the main file is javacoffeeadventure.main. The META-INF folder contains one MANIFEST.MF file that I tried to edit and make the jar invoke main.class's main() method:
Manifest-Version: 1.0
Created-By: 1.8.0_60 (Oracle Corporation)
Main-Class: javacoffeeadventure.main
I know I use jar to compile into a jar file, but how would I use that command to create a jar file that is able to begin with javacoffeeadventure.main? Is my manifest wrong?
as a slight by-the-way, jar puns are funny to me if you guys have any. :)
In my experience, the following has worked, but if you utilize it, you may need to adapt your directory structure.
First, your folder structure needs to be of the form 'containing_folder.com.example.package', where your classes are in the 'package' folder. You need to then place your manifest.mf file in the uppermost directory ('folder'). The manifest file should be as follows:
Manifest-Version: 1.0
Main-Class: com/example/package/javacoffeeadventure
including a carriage return after the second line.
From the initial folder compile with the following command:
jar cmvf manifest.mf javacoffeeadventure.jar com/example/package/*.class
making sure that beforehand you've compiled the classes in your package (use *.java)
Hope this helps.

How to run a java file with a lot of jars dependencies in ubuntu

I have a java class which has almost 12 jar file dependencies and i am using ubuntu 12.10 . I need to know how to run this java application because every time i run it , it gives me errors as "symbols not found". I have all jar files in a folder called libs. and i have tried these commands but none of these gives me some succesful result.I have flights.java class in test directory and libs directory is inside test directory.Currently i am in test directory
javac -cp "/home/ubuntu/test/libs/*.jar" flights.java
javac -cp '/home/ubuntu/test/libs/*.jar' flights.java
if you have single class in your app called flights.java and all of your required jar are located at /home/ubuntu/test/libs/ then use this
javac -cp '.:/home/ubuntu/test/libs/*.jar' flights.java
and to run
java -cp '.:/home/ubuntu/test/libs/*.jar' flights
better to just pack dependency and app in to a single jar and make it launchable and runnable jar
12 jars is not a very large number. Why not just append all the jars on the classpath?
Alternatively, you can create another jar and specify all the jars in Class-Path variable in that jar's MANIFEST.MF and then add this single jar to your classpath.
EDIT:
Here is how I would do it. Create a MANIFEST.MF file with content similar to this:
Manifest-Version: 1.0
Archiver-Version: whatever
Created-By: whatever
Built-By: author-name
Build-Jdk: 1.6.0_34
Class-Path: jar1.jar jar2.jar jar3.jar
replace jar1.jar with the actual file names of the jar.
Then you can create a jar with command : jar cvf test.jar -m ./MANIFEST.MF .
Now when you are using it on classpath use it like java -jar xyz.jar class-name

Categories