Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I would like to distribute my Java program as a JAR file. My program requires the Oracle JDBC driver, which is also delivered as an JAR file. But the java -jar command accepts only one JAR file. Therefore I have to merge the two JAR files. This can be done quite easily but am I allowed to do that? Am I allowed to distribute my program as a JAR file containing the contents of the Oracle JDBC JAR file?
But the java -jar command accepts only one JAR file.
That's not correct. Your JAR file can contain a Manifest with a Class-Path: entry which can name the Oracle .jar file.
Yes you can package Oracle JDBC drivers into your jar file, as long as you are not modifying the jar file or any of the file there in. In some of the libraries it is required to include the license files also as part of your distribution - you need to read the license details of the respective jar files. Generic Oracle distribution license terms can be found here http://www.oracle.com/technetwork/licenses/distribution-license-152002.html
Regarding the java -jar part of your question please refer following explanation:
To launch the executable jar file we use the command java -jar executable.jar
JVM would look into the manifest of jar file and execute the main method of main class - that you specify in jar file. Any dependency of the application can be satisfied by classpath settings - we dont need to specify all the dependency jar files while launching the application.
There are different ways of classpath settings:
Set the system classpath (on Windows set CLASSPATH=app1.jar;app2.jar;driver.jar; and on Unix/Linux export CLASSPATH=app1.jar:app2.jar:app3.jar ). This method is useful when you have control over system variables and it is controlled environment, this method is not preferred for distributing applications to client
Mention the classpath while launching the application. This can be done by using -classpath option of java comman - for example java -classpath app1.jar;app2.jar;driver.jar -jar executable.jar this method is useful for quick testing and if the number of jar files to be referred are less
Specifying the mainfest classpath. This is the best option for packaged application. We can specify the dependencies in the manifest classpath, like this Class-Path: app1.jar app2.jar driver.jar
Note: please use proper delimiters in classpath entries, for example on windows ; is the delimiter for classpath entry, on unix : is the delimiter and in manifest class path you have use space as delimiter. Also where ever app1.jar/app2.jar/driver.jar is mentioned you have to use absolute or relative path of jar files
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I don't want to make the code messy Is there a way to set a classpath to exexute my java program, because my jar files are from different directories they are like 30 jar files
Various strategies are available.
runnable jars
A 'runnable jar' can be run with java -jar thejar.jar, and depending on your OS and how you installed java on it, just doubleclicking the jar in the user interface works too (and does the same thing as java -jar thejar.jar.
This 'maps' to java -cp someclasspath myapp.pkg.Main as follows:
The thejar.jar is scanned for the file META-INF/MANIFEST.MF. This is a text file containing key/value pairs separated by a colon.
java.exe looks for an entry named Main-Class and takes the value of that as myapp.pkg.Main. It then looks for an entry named Class-Path and parses the value for that to use as classpath. This classpath string is space-separated, and all paths are relative to the same path the jar you run is in.
Thus, if you have, say:
/usr/local/myapp/myapp.jar
/usr/local/myapp/deps/guava.jar
/usr/local/myapp/deps/jooq.jar
and the myapp.jar file contains the class file /my/app/Main.class, then this needs to be in the manifest:
Main-Class: my.app.Main
Class-Path: deps/guava.jar deps/jooq.jar
and then you can just java -jar myapp.jar, from anywhere (you don't need to be in the /usr/local/myapp directory. Note that -jar automatically uses this mechanism for the classpath. $CLASSPATH and the -cp option are completely ignored.
So, how do you get that file in there? Well, build systems tend to have ways to let them automatically build up the list of 30-some jar files, but your question doesn't explain how your build works, so you'd have to peruse the documentation of maven or gradle or whatnot. Alternatively, script it together with some bashisms if you've handrolled your build (not recommended).
The * include
Another option is to use the * include option. java.exe itself can pick up every jar file in a given directory (not recursively, though - it won't pick up jars in subdirectories). The problem is, on every OS except windows, it is the job of the shell to unpack * into a list of files, so your shell will do that. Which you don't want it to do, because it unpacks using spaces, and the -cp command line option doesn't work that way. Thus, on ALL OSes except windows, you must put the classpath in single quotes in order to suppress the shell's feature that it will detect that * and unpack it.
Thus, with the same setup as above, you can also run:
java -cp 'myapp.jar:deps/*' my.app.Main
and that also works, though you'd have to [A] be running some posix based OS and [B] have to be in the /usr/local/myapp directory. On windows, I think java -cp myapp.jar;deps/* my.app.Main will work.
Note that it has to be just *. Not *.jar.
Use your build tooling
Most build tooling has a 'run' command that includes the proper (runtime) dependencies automatically. This includes IDEs.
Shading
Also called 'fatjars' or 'uberjars' or 'striped jars', this is the notion of taking all class files in all the jars needed at runtime and packing them into one gigantic jar file.
This is a dumb idea for many reasons:
It's slow as molasses; your average serious project has hundreds of dependencies, so that one gigantic jar is half a GB in size. Just writing that out to disk takes time, let alone transferring it around to your deployment and test servers. You want the time and effort it takes to make a change in your code and see your test results to be as low as it reasonable, and the fatjar concept fundamentally clashes with this notion.
signed jars do not work well with this model.
It makes updating deps harder.
You could in theory consider the notion of 'I make a single fat jar and now I can just zip that up and mail it around to folks', and thus conclude that fat jars are nice, but this is no good either:
gmail and other services will flat out strip that jar right out of your email because it's generally used to convey malicious code. Mailing jars around isn't a good deployment model
The current only official supported style of distributing java apps is NOT by just shipping jar files around; there are no JREs anymore (JRE8 was the last official release. Some third parties still make them. Doesn't make it any more officially supported though). You're supposed to ship an installer which takes care of setting up a treeshaken JRE and keeping it up to date. Various tools make this possible such as jmod and jlink. These aren't used much, but that's probably mostly because the vast majority of java apps run on servers and aren't themselves client apps meant to run directly on end user hardware. See for example minecraft or eclipse: Java-written desktop apps. Neither 'ships as a jar file' and certainly not as fat jars.
"Just shade it / make a fatjar" is extremely common advice. You are now armed with sufficiently knowledge to know it is bad advice.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
How can I create a .jar file which includes both class files and some additional resources(namely images) without the use of an IDE.
You can use maven or ant to reach this goal.
In order to create a jar of your project you need to the following command:
jar cf jar-file input-file(s)
first make sure that running in command prompt or terminal jar is not going to tell you "command not found".
The options and arguments used in this command are:
The c option indicates that you want to create a JAR file.
The f option indicates that you want the output to go to a file
rather than to stdout.
jar-file is the name that you want the resulting JAR file to have.
The input-file(s) argument is a space-separated list of one or more
files that you want to include in your JAR file. The input-file(s)
argument can contain the wildcard * symbol. If any of the
"input-files" are directories, the contents of those directories are
added to the JAR archive recursively.
Let's assume you have a directory named "My Project" which contains all your java packages, classes, resources, etc. You need to jar "My Project" hence, you should do the following:
Navigate to the parent of the directory that contains "My Project" using command prompt (in windows) and terminal (in OSX or linux)
execute the jar command as follow (in windows - double quotes around My Project is because of space in directory name, you might not need it)
jar cf MyProject.jar "My Project"
Above command will give you the directory in jar.
For more info on creating jar see oracle documentation.
I can only link you to the oracle page : https://docs.oracle.com/javase/tutorial/deployment/jar/build.html
The command you are looking for seems to be :
jar cvf TicTacToe.jar TicTacToe.class audio images
Where audio and images are resource folders.
Good luck,
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Apologies for the generic nature of this question.
I have been learning Java for a few months now, and I've created a few simple projects which have some functionality. I wanted to send the projects to a friend and I'm running into countless errors and struggles. Passing a .jar file is causing "Main class not found" errors when they try to open it.
I tried using third party software to wrap the .jar files into an .exe file and the same errors still persist.
Beyond that, I'm convinced that passing around .jar files wrapped into .exe files via third party software is NOT how Java was intended to be used. I've read two books on Java and they all talk about structuring the language, but I'm confused about WHERE I'm supposed to be using this code because it has become painfully obvious that it is NOT intended to be passed around in file format.
Is this a server programming language? Used on the back end of websites mainly? I'm not sure where one would be using the code written in Java.
You should build an executable jar.
Check here and here.
You need to create your JAR file as an executable JAR file if you want someone to be able to run it. That is how you send around Java executables. Look here for more info:
How do I create executable Java program?
I'd recommend you spend some time with http://docs.oracle.com/javase/tutorial/. Java program basically runs on top of virtual machine (not directly on your physical machine). Java program is compiled into *.class files, and a collection of *.class is commonly bundled into a *.jar file.
If you want to run your java program, one common way is to execute the java virtual machine runtime (JRE) and specify your jar package to be loaded into the classpath, eg:
java -jar /path/to/my.jar
Your jar file has to be packaged properly such that it indicates what is the main class (if any)
Packaging jar into exe is possible, but is not best practice. Java paradigm is a write & compile once -- runs everywhere.
from Oracle:
If you have an application bundled in a JAR file, you need some way to indicate which class within the JAR file is your application's entry point. You provide this information with the Main-Class header in the manifest, which has the general form:
Main-Class: classname
The value classname is the name of the class that is your application's entry point.
Recall that the entry point is a class having a method with signature public static void main(String[] args).
After you have set the Main-Class header in the manifest, you then run the JAR file using the following form of the java command:
java -jar JAR-name
The main method of the class specified in the Main-Class header is executed.
Setting an Entry Point with the JAR Tool:
The 'e' flag (for 'entrypoint'), introduced in JDK 6, creates or overrides the manifest's Main-Class attribute. It can be used while creating or updating a jar file. Use it to specify the application entry point without editing or creating the manifest file.
For example, this command creates app.jar where the Main-Class attribute value in the manifest is set to MyApp:
jar cfe app.jar MyApp MyApp.class
You can directly invoke this application by running the following command:
java -jar app.jar
If the entrypoint class name is in a package it may use a '.' (dot) character as the delimiter. For example, if Main.class is in a package called foo the entry point can be specified in the following ways:
jar cfe Main.jar foo.Main foo/Main.class
Setting an Application's Entry Point
For a quick answer, libraries are bundled in jars, which are then added to the classpath of another application.
Pretend you invent a new sort algorithm which is faster than all the others. You could bundle up a small number of classes into a jar, which is basically just a zip file containing your compiled .class files.
Now your friend needs to sort some data and wants to use your classes. He would write his code to import your classes (using import at the top of his .java files), and then work with them in his code. When it came time for him to compile his .java files into .class files, he would add your jar to his classpath. Eclipse/netbeans can set this up for you, or if you're running javac from the command line it would look something like this:
javac ... -cp "fastsorting.jar" ...
Sometimes (rarely, in the real world) someone has a JAR which is really a fully fledged program, meant to be run. I say rarely, because jars aren't the most common way to distribute software. More popular is as a web service or through an applet on a website. In this case, a jar's manifest file (just a text file telling java information about this jar) will have a main class, which is run when the the jar is invoked through java.
This issue is related to running a Java program (jar) dependent on thirdparty jar library even after setting classpath and trying so many other methods by reading articles in Internet.
I want to use a thirdparty Pack1.jar (it is not a part of jvm) as dependency of my programme.
I do not know where the Pack1.jar file could be in the deployment machine and I want the deployer to specify the path for the thirdparty libraries
I have tried the following alternatives in vain
Setting the java.class.path programatically
String class_path = args[0];
System.setProperty("java.class.path",class_path);
Here I am assuming that deployer would supply the classpath as first argument while running the program
Setting the CLASSPATH env_var to locate the thirdparty directory
While running, using the classpath option
java -classpath /path/to/Pack1.jar -jar Pack2.jar
I think this would not work because documentation says that classpath is ignored when program is run with "java -jar"
Setting the java.ext.dirs programatically.
Setting the java.library.path programatically.
I do not want to specify the Class-Path in manifest because that takes only relative path and I do not know where the thirdparty library would be kept in deployment machine
But I am unable to get the jar running.
How can I fix this problem any help please.
Go for option 3. Put both jars on the classpath like this:
java -classpath '/path/to/Pack1.jar:/path/to/Pack2.jar' com.packagename.yourclassname
Note, that this is for Linux. on Windows, you would separate classpath elements with semicolons:
java -classpath "/path/to/Pack1.jar;/path/to/Pack2.jar" com.packagename.yourclassname
http://en.wikipedia.org/wiki/Classpath_%28Java%29
You can use Pack2.jar without running it using -jar--put it on the classpath and call the entry point listed in its manifest file.
I usually wrap that up in a launcher script to avoid those kinds of problems, and allow jar paths to be set using an argument.
Name the secondary JAR(s) in the Class-path entry of the Manifest.MF of the main JAR file, and use java -jar.
Your objection to this technique doesn't make sense. If you supply and deploy the secondary JAR files, as you should, you have the same degree of control over their location as you do over that of the major JAR file. It doesn't matter where else the user may have copies of them.
This question already has answers here:
Including all the jars in a directory within the Java classpath
(25 answers)
Closed 4 years ago.
I have been using so many 3rd party libraries(jar files) that my CLASSPATH is completely messed up as i have to include the path for every single jar file that i use.
I've been wondering if there is a way to include all the jar files in a folder using wildcard(*) operator (like *.jar). But it seems to be not working. Is there any other way that can shorten the CLASSPATH that currently looks like an essay ;) on my PC?.
From: http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html
Class path entries can contain the basename wildcard character *, which is considered equivalent to specifying a list of all the files in the directory with the extension .jar or .JAR. For example, the class path entry foo/* specifies all JAR files in the directory named foo. A classpath entry consisting simply of * expands to a list of all the jar files in the current directory.
This should work in Java6, not sure about Java5
(If it seems it does not work as expected, try putting quotes. eg: "foo/*")
This works on Windows:
java -cp "lib/*" %MAINCLASS%
where %MAINCLASS% of course is the class containing your main method.
Alternatively:
java -cp "lib/*" -jar %MAINJAR%
where %MAINJAR% is the jar file to launch via its internal manifest.
Basename wild cards were introduced in Java 6; i.e. "foo/*" means all ".jar" files in the "foo" directory.
In earlier versions of Java that do not support wildcard classpaths, I have resorted to using a shell wrapper script to assemble a Classpath by 'globbing' a pattern and mangling the results to insert ':' characters at the appropriate points. This would be hard to do in a BAT file ...
If you mean that you have an environment variable named CLASSPATH, I'd say that's your mistake. I don't have such a thing on any machine with which I develop Java. CLASSPATH is so tied to a particular project that it's impossible to have a single, correct CLASSPATH that works for all.
I set CLASSPATH for each project using either an IDE or Ant. I do a lot of web development, so each WAR and EAR uses their own CLASSPATH.
It's ignored by IDEs and app servers. Why do you have it? I'd recommend deleting it.