I am having an executable JAR. Ofcouser I have JDK installed at my end I am giving following command to run my exe JAR from command prompt.
1 Using JRE :-
C:\Users\userName\Desktop\Utility\latest>"C:\Program Files\Java\jre1.8.0_161\bin\java.exe" -jar Utility.jar
2 Using JDK
C:\Users\userName\Desktop\Utility\latest>"C:\Program Files\Java\jdk1.8.0_161\bin\javaw.exe" -jar Utility.jar
Both are working on my desktop but if I tries #1 to run the executable JAR on different machine which has only JRE Version (1.8 onwards) it is not getting opened up.
I tried following links but some links are sayin to download few installers but all I do not want to get that. Is there any way. Or issue with my executable JAR ?
How can I make my executable JAR not need JDK to run
Run a JAR file using a specific JRE
Manifest-Version: 1.0
Rsrc-Class-Path: ./ commons-collections4-4.3.jar poi-3.17.jar poi-ooxm
l-3.17.jar xmlbeans-3.0.1.jar curvesapi-1.06.jar poi-ooxml-schemas-3.
17.jar poi-examples-3.17.jar poi-excelant-3.17.jar poi-scratchpad-3.1
7.jar commons-codec-1.10.jar commons-collections4-4.1.jar commons-log
ging-1.2.jar curvesapi-1.04.jar junit-4.12.jar log4j-1.2.17.jar xmlbe
ans-2.6.0.jar ooxml-schemas-1.3.jar
Class-Path: ./ commons-collections4-4.3.jar poi-3.17.jar poi-ooxml-3.17.jar
xmlbeans-3.0.1.jar curvesapi-1.06.jar poi-ooxml-schemas-3.17.jar poi-examples-3.17.
jar poi-excelant-3.17.jar poi-scratchpad-3.17.jar commons-codec-1.10.jar
commons-collections4-4.1.jar commons-logging-1.2.jar curvesapi-1.04.jar
junit-4.12.jar log4j-1.2.17.jar xmlbeans-2.6.0.jar ooxml-schemas-1.3.jar
Rsrc-Main-Class: DataProcessor.DataProcessor.App
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoade
It sounds like the issue your are having is more than not having the JDK or knowing where the JRE on the target system is located, it's that you also didn't include the dependencies that your code has.
The jar file you have includes details in the manifest file that tells the JVM the classpath and the main class to load. If you look at the Rsrc-Class-Path, it is add the jars from the current directory. This is fine if you are sending the entire folder structure that includes all the jars in the expected location. But it doesn't work with just the jar.
In order to make a single jar that would run without any additional jars, you need to repackage the jars. There are two common ways to do this
UberJar - where the class of your project is combined with the classes extracted form all of your dependencies into a single jar
JarInJar - where your jar and all the dependecy jars are put into a jar and a custom classloader is used to load the classes from the jars inside the jar.
I'm not sure what build tool you're using, but for Maven the Shade Plugin will create an UberJar.
I personally recommend using the JarInJar option for this reason. The Spring Boot Maven Plugin is what I believe to the easiest
Related
The structure of my first app is simple:
libs
opencsv-3.8.jar
yamlbeans-1.0.jar
out
artifacts
...
production
...
src
META-INF
MANIFEST.MF
pl.krzysiu
App.java
CsvReplacer.java
Everything is fine during the compile and running the program. After building artifact jar file in the default out\artifacts directory, I get
java.lang.NoClassDefFoundError: net/sourceforge/yamlbeans/YamlException
when I try to run it by java -jar CsvReplacer.jar command
The libraries are included inside the jar file (they are there after unpacking it) - they are added to Libraries section in Project Structure (separately - one file per one lib), the whole libs dir is included in the Dependencies tab of Modules section (with export checkbox checked) and the libs dir is added in Output Layout of Artifacts section similarily.
The manifest file contains:
Manifest-Version: 1.0
Class-Path: libs\yamlbeans-1.0.jar libs\opencsv-3.8.jar
Main-Class: pl.krzysiu.App
Why the libs aren't visible for the App? If I copy this dir manually to the CsvReplacer.jar file's location - everything works fine.
The structure inside CsvReplacer.jar file looks like:
libs
opencsv-3.8.jar
yamlbeans-1.0.jar
META-INF
MANIFEST.MF
pl
krzysiu
App.java
CsvReplacer.java
IDE: Intellij IDEA 2016.3
The standard Java classloaders cannot find a JAR file embedded inside another JAR file.
You have two choices when making an executable JAR with dependencies.
Create a so-called uberJAR file by merging the contents of the dependent JARs into your main JAR.
References:
IntelliJ IDEA export Runnable program as Uber Jar
https://blog.jetbrains.com/idea/2010/08/quickly-create-jar-artifact/
Give your JAR a "Class-Path" manifest attribute to tell it where the (external!) dependent JARs are located.
You can't give a -cp and a -jar option together. But another alternative would be to get rid of the -jar option and use a -cp argument to specify the classpath.
Alternatively, you could implement a custom classloader that can load from a jar inside a jar, or use something like one-jar or Spring Boot.
I am trying to build my application jar (non executable jar) with all it's dependenices jar files also to unpack.
Simply to explain my issue, in eclipse, to export runnable/executable jar, there is an option
"Extract required libraries into generated Jar"
Please help me the same option for non-runnable jar also.
Thanks
No there isn't.
Just as background: Packaging dependencies within a JAR file (sometimes called a fat jar or app jar) is not a native Java mechanism but is grafted on using custom ClassLoaders or start scripts packaged in the JAR.
If you create a runnable JAR file with Eclipse it uses a wrapper to run your application which can read the packaged libraries. You can see this if you open the exported JAR file and look at it's Manifest:
Manifest-Version: 1.0
Rsrc-Class-Path: ./ [removed]
Class-Path: .
Rsrc-Main-Class: com.example.Test
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
The JarRsrcLoader sits between your applications Main-Class and the Java Runtime and can then load the packaged dependencies before executing your code. In a library there is no such hook that Eclipse can hook into since the loading is done by someone using your library and you can't control the loading process.
There are mechanisms to combine JAR files into a single one by unpacking the dependencies and then repackaging them into your JAR. Look here for example: How to combine two Jar files
Note though that by repackaging a 3rd party JAR you might run into issues with signed classes or conflicting Metadata.
If you want to publish a library and/or manage dependencies properly I recommend looking into build systems like Maven (http://maven.apache.org/) or Gradle (http://www.gradle.org/). I personally much prefer Gradle.
Edit: This project seems promising: https://github.com/puniverse/capsule
Use Capsule. It does everything you want including set JVM configuration right in the manifest.
With capsule you have the option of packing all of your JARs and native libs right into the capsule JAR, or you can specify your Maven dependencies in the Manifest, and let them be downloaded the first time the capsule is launched.
I am in the final step of my application release and so creating jar, called App.jar. I have other jars on which App.jar is dependent, so I rather included it within App.jar. When trying to run, it works if App.jar is put into the folder of the main project. However, when put outside it (for example on the dekstop), it does not work completely, meaning that some GUi components are not displaying. My question is:
Besides other jars on which my App.jar is dependent, can it be dependent on some other files or under some other conditions?
EDIT:
I am working in Eclipse, to build jar I just exported it and chose the option "packaged required libraries into generated JAR", which put all the jars I need to run into App.jar. My MANIFEST.MF then looks like this:
Manifest-Version: 1.0
Rsrc-Class-Path: ./ JTattoo.jar plugin.jar docking-frames-common-1.1.1
-SNAPSHOT.jar jl1.0.jar swt-3.7M5-win32-win32-x86.jar worldwind.jar a
ccess-bridge.jar sunpkcs11.jar looks-2.0.1.jar tools.jar OfficeLnFs_2
.7.jar jce.jar jna_WindowUtils.jar dom4j-2.0.0-ALPHA-2.jar junit-4.5.
jar rt.jar mysql-connector-java-5.1.21-bin.jar sunmscapi.jar glasslib
.jar resources.jar jxl.jar dnsns.jar sunec.jar jogl.jar mp3spi1.9.4.j
ar docking-frames-core-1.1.1-SNAPSHOT.jar DJNativeSwing.jar tritonus_
share.jar dom4j-2.0.0-ALPHA-2-sources.jar zipfs.jar MozillaInterfaces
-1.8.1.3.jar jfr.jar DJNativeSwing-SWT.jar gluegen-rt.jar jaxen-1.1.1
.jar gdal.jar localedata.jar jna-3.2.4.jar charsets.jar sunjce_provid
er.jar jsse.jar jaccess.jar
Class-Path: .
Rsrc-Main-Class: org.cnstar.wiki.app.GreatPlaces
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
SplashScreen-Image: images/splash_screen.png
You should set the classpath properly to include all the jars required.
Yes there can be more jars dependency due to transitive dependency. Your App.jar may be dependent on a jar, which may be dependent on another jar. Using Maven you can be away from all such worries as it automatically downloads all the dependencies.
It works fine when compiling project, but after exporting it to a runnable jar and launching, it can't find external files and throws an error. What should I do?
Add external libraries to the manifest.mf:
Class-Path: . MyApp_lib/extlib.jar MyApp_lib/extlib2.jar ...
You could attempt building a fat jar that includes all the jars. It contains a custom class loader to load the jars referenced externally by your project.
Try using http://fjep.sourceforge.net/ plugin to build a fat jar.
You can export a java project containing jars using the File -> Export -> Other -> One Jar Exporter.
The jar thus exported works fine.
You have to keep all required jars in the classpath to run your jar. Run your jar like :
java -cp extlib/* -jar yourjar.jar OR java -cp lib1.jar:lib2.jar:.. -jar yourjar.jar
Make sure that while building the jar, you include all the used libraries(include everything from class path). This issue will happen when you refer a external jar.
You can include a classpath variable in the jar's manifest file.
JAR file classpath
I have a Java project in Eclipse with class MainClass having main method in package :
com.nik.mypackage.
The project also references two external libraries, which I copied in the lib folder in Eclipse and then added to build path using ADD JAR function. The libraries being one.jar and two.jar
This library is in lib folder in eclipse and added to the build path.
I want to create a executable JAR of the application using ant script. So that user can access my application using command:
c:>java -jar MyProject-20111126.jar
I know about the Eclipse plugin which directly exports a java application as runnable JAR. But I want to learn ant and the build process so manually want to create the build.xm.
You have two options from your build.xml. You can either unjar the library jars and then bundle their contents with the code compiled for your application. Or, you can put the library jars on the filesystem and supply a ClassPath entry in the manifest file of the MyProject-2011126.jar file.
If you set the classpath in the manifest remember that the path you supply is relative to the MyProject-2011126.jar.
one alternative:
Instead of having only a jar, you build mutiple jars (your jar + libs) +batch file.
So, your built package can be like this structure:
-/package/bin/app.bat
/package/lib/my.jar
/package/lib/one.jar
/package/lib/two.jar
In app.bat you just have the same as your code
java -jar MyProject-20111126.jar
PS: if you want to start learning built tools, ANT may be a bit tool old. I suggest http://maven.apache.org/
Please try one-jar. It helps to redistribute everything packaged as single jar and comes with ant-task . See Easiest way to merge a release into one JAR file.