I am trying to run my jar file by executing java -jar myJarFile.jar arg1 but it throws ClassNotFoundException ! for the classfiles which are referred in my class files. FYI, these class files are present in some external jars which i have placed on my classpath by setting the env CLASSPATH variable pointing to the directory where all the external jars are placed. And my MANIFEST.MF would look like
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 20.14-b01 (Sun Microsystems Inc.)
Main-Class: com.abc.test.FileGenerator
BuildDate: 01/10/2014 12:52:36
Class-Path: C:\libraries\commons-beanutils-1.8.3.jar C:\libraries\commons-collections.jar
C:\libraries\commons-discovery-0.2.jar C:\libraries\commons-lang-2.5.jar
C:\libraries\commons-logging-1.1.1.jar C:\libraries\commons-logging-1.0.4.jar
My main class is available in my jar and I am running from where my jar is getting created by ant script like dist folder. I even changed the absolute path to relative path.. It is still throwing the same error. Here is my jar structure -
myFile.jar
|- com
| |
| abc
| |
| test
| |-package1
| |-package2
| |-FileGenerator.class
|
|-META-INF | |- MANIFEST.MF
Kindly help me on this.
Thanks in advance!
You need to set the paths to all your jar files in the CLASSPATH, putting only a directory will cause jvm to look for .class files of which the packages start from that directory not .jar files.
So set your classpath something like this (windows):
set CLASSPATH=%CLASSPATH%;C:\path\to\libs\somelib1.jar;path2\to\libs\somelib2.jar
and so on.
You have then to run your program like this:
java your.main.Klass arg1
Alternatively you could add a Calss-path entry in your manifest and put all your dependencies in it:
Class-Path: libs/somelib1.jar libs/somelib3.jar
Then you can run it using the -jar option
java -jar myJarFile.jar arg1
Using -jar tells the JVM to ignore any other classpath settings (include CLASSPATH and -cp). You have to give a classpath in your manifest file at that point.
Please add the classpaths of your external jar in your manifest file like
Class-Path: abc.jar def.jar folder/ghi.jar
and then run your command java -jar myJarFile.jar arg1
Related
I have below project structure:
->bin
->lib
->resources
->src
->DemoFramework
->FirstDemo.java
In lib folder, I have an external jar that I need in my application. Its name is ext.jar. In resources, I have Manifest.txt file, whose content is given below.
Manifest-Version: 1.0
Class-Path: . lib/ext.jar
Main-Class: DemoFramework.FirstDemo
I am using below command to generate jar:
javac -cp ".;./lib/ext.jar" src/DemoFramework/*.java -d bin
Basically I am putting all class files into bin folder so that in final jar file, source code is not visible.
Then I am issuing below command:
jar cmf resources/Manifest.txt project.jar bin lib
The jar file is successfully created but when I run it, it says:
no main manifest attribute, in project.jar
I am confused about this error, no idea why it is happening.
Can you guys help me to sort it out?
Thanks.
I'm trying to create a jar file and run it using java -cp main.jar com.test.Foo.Main but I keep getting:
Error: Could not find or load main class com.test.Foo.Main
Caused by: java.lang.ClassNotFoundException: com.test.Foo.Main
This is my file structure. So I'm thinking the line in my Main.java should be package com.test.Foo correct?
I'm compiling my Main.java with javac Main.java which outputs a Main.class file. Afterward, I create a jar file using jar cfm main.jar META-INF/MANIFEST.MF Main.class and finally while I'm in the same directory as the jar file <root>/src/com/test/Foo/ I run java -cp main.jar com.test.Foo.Main and that's when I run into the above error. Any idea how I can run this file like this (and yes I need it to run with this command specifically)?
Main.java
package com.test.Foo;
public class Main {
public static void main (String args[]) {
System.out.println("I am com.test.Foo.Main");
}
}
META-INF/MANIFEST.MF
Manifest-Version: 1.0
Main-Class: com.test.Foo.Main
I tried using some of the options given in this popular SO question and nothing helped.
The picture you're showing in your question is your project structure not your jar structure.
When you create a jar file, the structure for that jar file might be
different with your source code folder structure.
Every IDE (such as eclipse, netbeans, IntelliJ) has a mechanism for creating JAR files. In your case when you open the created jar file (using zip apps like winrar) you should see something like this :
com
|
test
|
Foo
|
Main
META-INF
|
MANIFEST.MF
This should be the ordering of your files and folders, otherwise Java can not find your main class from MANIFEST.MF
Now to solve this problem:
Open your jar file using a zip application like winrar
check the folder structure residing inside your jar file as I draw
Fix it right away within the winrar or try to correct your project structure to produce the structure I mentioned.
The class is called com.test.Foo.Main you need to specify the full name in the command:
java -cp main.jar com.test.Foo.Main
or you can use the simpler
java -jar main.jar
Check your META-INF/MANIFEST.MF for the attribute of Manifest-Version: 1.0
This attribute must be there.
Edit:
You need to move to the source root src/ and issue below command to create a valid jar.
javac com/test/Foo/*.java
and, create the jar using,
jar cmf com/test/Foo/MANIFEST.MF main.jar com/test/Foo/*.class
The thing is, package structure should match with the folder structure apparently.
I have a jar whose content looks as shown below,
Below is my manifest file
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.3
Created-By: 1.7.0_06-b24 (Oracle Corporation)
Main-Class: org.sai.com.DerbyDemo
Class-Path: derby.jar derbyclient.jar derbynet.jar derbytools.jar
When i try to run the jar, it has thrown a ClassNotFoundExcception meaning it isn't referencing the jars inside the outer jar.
In the Class-Path attribute, how can I reference jars (derby.jar, etc) inside the actual jar?
You will need a custom class loader for this, have a look at One Jar.
One-JAR lets you package a Java application together with its dependency Jars into a single executable Jar file.
It has an ant task which can simplify the building of it as well.
REFERENCE (from background)
Most developers reasonably assume that putting a dependency Jar file into their own Jar file, and adding a Class-Path attribute to the META-INF/MANIFEST will do the trick:
jarname.jar
| /META-INF
| | MANIFEST.MF
| | Main-Class: com.mydomain.mypackage.Main
| | Class-Path: commons-logging.jar
| /com/mydomain/mypackage
| | Main.class
| commons-logging.jar
Unfortunately this is does not work. The Java Launcher$AppClassLoader does not know how to load classes from a Jar inside a Jar with this kind of Class-Path. Trying to use jar:file:jarname.jar!/commons-logging.jar also leads down a dead-end. This approach will only work if you install (i.e. scatter) the supporting Jar files into the directory where the jarname.jar file is installed.
You can't. From the official tutorial:
By using the Class-Path header in the manifest, you can avoid having
to specify a long -classpath flag when invoking Java to run the your
application.
Note: The Class-Path header points to classes or JAR files on the
local network, not JAR files within the JAR file or classes accessible
over internet protocols. To load classes in JAR files within a JAR
file into the class path, you must write custom code to load those
classes. For example, if MyJar.jar contains another JAR file called
MyUtils.jar, you cannot use the Class-Path header in MyJar.jar's
manifest to load classes in MyUtils.jar into the class path.
In Eclipse you have option to export executable jar.
You have an option to package all project related jars into generated jar and in this way eclipse add custom class loader which will refer to you integrated jars within new jar.
Default implementations of the classloader cannot load from a jar-within-a-jar: in order to do so, the entire 'sub-jar' would have to be loaded into memory, which defeats the random-access benefits of the jar format (reference pending - I'll make an edit once I find the documentation supporting this).
I recommend using a program such as JarSplice to bundle everything for you into one clean executable jar.
Edit: Couldn't find the source reference, but here's an un-resolved RFE off the Sun website describing this exact 'problem': http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4648386
Also, you could 'test' that your program works by placing the library jar files in a \lib sub-directory of your classes directory, then running from the command line. In other words, with the following directory structure:
classes/org/sai/com/DerbyDemo.class
classes/org/sai/com/OtherClassFiles.class
classes/lib/derby.jar
classes/lib/derbyclient.jar
From the command line, navigate to the above-mentioned 'classes' directory, and type:
java -cp .:lib/* org.sai.com.DerbyDemo
if you do not want to create a custom class loader. You can read the jar file stream. And transfer it to a File object. Then you can get the url of the File. Send it to the URLClassLoader, you can load the jar file as you want.
sample:
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("example"+ ".jar");
final File tempFile = File.createTempFile("temp", ".jar");
tempFile.deleteOnExit(); // you can delete the temp file or not
try (FileOutputStream out = new FileOutputStream(tempFile)) {
IOUtils.copy(resourceAsStream, out);
}
IOUtils.closeQuietly(resourceAsStream);
URL url = tempFile.toURI().toURL();
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url});
urlClassLoader.loadClass()
...
Add the jar files to your library(if using netbeans) and modify your manifest's file classpath as follows:
Class-Path: lib/derby.jar lib/derbyclient.jar lib/derbynet.jar lib/derbytools.jar
a similar answer exists here
in eclipse, right click project, select RunAs -> Run Configuration and save your run configuration, this will be used when you next export as Runnable JARs
I am struggling to get my Java program to run on AIX. I used Eclipse on Windows to create a runnable Jar file, jRams.jar below. I kept on getting a class not found error, until finally I put all the external libraries in the same directory.
$ ls
JAXB2_20081030.jar
JAXB2_20110601.jar
activation.jar
asjava.jar
commons-beanutils-1.8.3.jar
commons-beanutils-bean-collections-1.8.3.jar
commons-beanutils-core-1.8.3.jar
commons-codec-1.5.jar
commons-collections-3.2.1.jar
commons-configuration-1.6.jar
commons-digester-2.1.jar
commons-jxpath-1.3.jar
commons-lang-2.6.jar
commons-logging-1.1.1.jar
commons-logging-adapters-1.1.1.jar
commons-logging-api-1.1.1.jar
jRams.jar
jaxb-api.jar
jaxb-impl.jar
jaxb-xjc.jar
jaxb1-impl.jar
jremote.jar
jsr173_1.0_api.jar
log4j-1.2.16.jar
netty-3.2.4.Final.jar
$
Still, I get the class not found error.
$ java -jar jRams.jar
The java class is not found: com.jbase.jremote.JRemoteException
jremote.jar definitely contains JRemoteException. Why isn't this working?
UPDATE
Thank you for your straight-to-the-point answers. I now understand the nature of a java application and a manifest file far better.
Turns out my ftp client was transferring in ASCII mode and not Binary, so the jar files were corrupt. I have learned a great deal, nonetheless.
When using the -jar option, you need to specify which jar-files should be on your class path in the manifest file. Just having the required jar files in the same directory won't do it.
Add a line in your manifest that says:
Class-Path: JAXB2_20081030.jar:JAXB2_20110601.jar:....:netty-3.2.4.Final.jar
or skip the -jar option and launch using
java -cp JAXB2_20081030.jar:....:netty-3.2.4.Final.jar:jRams.jar pkg.JRamsMain
and it should work fine.
(Note that on *nix systems, as opposed to Windows machines, the jar files in the class paths should be separated using : instead of ;.)
Further reading:
The Java Tutorials: Adding Classes to the JAR File's Classpath
You need to add all those JARs to the runtime CLASSPATH by adding the -classpath parameter. AIX requires you to separate the JARs using :
You will have to specify the full path(if libraries not in the same directory as jRams) or just the names of the jar file in a manifest file (If all dependency jars are in the same folder). Alternative specify the path to all the dependent jars using -cp argument.
Example (This assume every dependency is in the same directory you are executing java command from):
java -cp commons-collections-3.2.1.jar; jaxb-impl.jar; etc.. ;jRams.jar package_to_class.MyMainClass.java
Where package_to_class is example: com.myproj.example.
EDITED.
Follow these steps to add "Class-Path" to existing jar file -
Create "newmanifest" file with following entry
Class-Path: additional/jars
Update existing jar file e.g. "classes.jar"
jar --update --manifest=newmanifest --file classes.jar
Inflate jar file
jar -xvf classes.jar
created: META-INF/
inflated: META-INF/MANIFEST.MF
Verify "Class-Path" is added to MANIFEST.MF
cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
main-class: CLASSNAME
Created-By: 15.0.2 (Oracle Corporation)
Class-Path: additional/jars
I have created jar file which includes my .class , manifest file and dependency jar files like
jar cfmv custadvicejar.jar mymanifest.txt Gchreportsautomation Bean Utils
jxl.jar ojdbc14.jar
where
custadvicejar.jar - is my jar file name
mymanifest.txt contains
Main-Class: Gchreportsautomation.GCH_Home_Loan_Data_Cust_Advice_DAO
"Gchreportsautomation" is the package name contains "GCH_Home_Loan_Data_Cust_Advice_DAO.class" [This class is my starting point of my application]
Gchreportsautomation/ GCH_Home_Loan_Data_Cust_Advice_DAO.class
"Bean" is the package name contains "GCH_Home_Loan_Data_Cust_Advice_Bean.class"
Bean/ GCH_Home_Loan_Data_Cust_Advice_Bean.class
"Utils" is the package name contains "Utils.class"
Utils/ Utils.class
and
jxl.jar and ojdbc14.jar are jar files required for my application which i kept
in parent directory of the .class files like
D:\Excalcreation
/Gchreportsautomation/ GCH_Home_Loan_Data_Cust_Advice_DAO.class
/Bean/ GCH_Home_Loan_Data_Cust_Advice_Bean.class
/Utils/ Utils.class
/jxl.jar
/ojdbc.jar
while running the application i got error like
Caused by: java.lang.ClassNotFoundException: jxl.format.CellFormat
i know this is because of class-path error. how to rectify it.
If i click my jar file ,the application has to run. please provide solution.
If you don't mind having the other jar files around, your manifest can specify which other jars should be in the classpath when the jar is invoked. See:
http://java.sun.com/docs/books/tutorial/deployment/jar/downman.html
This might be easier than including the files from the jars in your jar.
If you add a Class-Path: line in your jar that specifies the location of the jars (relative to the the runnable jar, I believe), then you should be set.
You cannot include jars in jars without pulling some ClassLoader tricks to access them. What you can do though is unjar the internal jars and put the contained files into your main jar. There are tools to help you with that. See also: Classpath including JAR within a JAR
To do that manually, do this:
jar -xf jxl.jar
jar -xf ojdbc14.jar
jxl-dirs=`jar -tf jxl.jar | sed -e 's/\/.*//' | sort | uniq | grep -v META-INF`
ojdbc14-dirs=`jar -tf ojdbc14.jar | sed -e 's/\/.*//' | sort | uniq | grep -v META-INF`
jar cfmv custadvicejar.jar mymanifest.txt Gchreportsautomation Bean Utils $jxl-dirs $ojdbc14-dirs
where $jxl-dirs are the top-level directories you got by running the first jar -xf jxl and $ojdbc14-dirs are the top-level directories you got by running jar -xf ojdbc14.jar leaving out META-INF. (This will not work, though, if any one of these top-level directories contains spaces.)