build> jar cvfe test\MyJavaLibrary.jar Main -C test\java Main.class foo\SomeClass.class
foo\SomeClass.class : no such file or directory
added manifest
adding: Main.class(in = 444) (out= 308)(deflated 30%)
The corresponding directory structure is
build/
test/
java/
foo/
SomeClass.class
Main.class
It is very strange that it works correctly when using test\java\foo\SomeClass.class as the last argument instead. Fine, but that doesn't work when I do the same for the first argument, that is test\java\Main.class. The behaviour appears to be very inconsistent.
Why can it not find foo\SomeClass.class, or better, what is the right way to create the Jar?
java version "1.8.0_102"
The executable that you're running from the command-line appears to start in the build directory, and as such, it doesn't know where the foo\SomeClass.class file is relative to build - this would also explain why test\java\foo\SomeClass.class works (it knows how to find the file relative to the execution directory).
If you were to have the foo folder on the top level inside build, I believe it would work correctly, but because foo is nested within two layers of directories, the executable has no idea where to look for a folder with that name in its current directory.
I just found the answer in a documentation page I haven't seen before.
-C dir
Temporarily changes directories to dir while processing the following inputfiles argument. Multiple -C dir inputfiles sets are allowed.
So apparently the -C argument would need to be placed for every input, not just specified once.
Source: http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jar.html
Related
I have just shifted back from an IDE to Notepad to write a Java program. The program is using 20 JARs. I compiled successfully. When I decided to run the Java class file using
java -cp ".\\*" MyProgram
it was giving the standard error "Couldn't find or load main class....".
I was confused because when I used to run the java command with all files in an existing folder, it would just get those JARs as the current folder is already in the classpath. As the program is running from the current folder, I tried using -cp "." to include it explicitly in the classpath but that didn't work either.
Finally I was able to run the program with this command:
java -cp ".\\*;." MyProgram.java
I am asking this question to understand the actual logic behind Java's classpath.
Correct me if I am wrong, but I think that the JAR is just a standard archive in which all the packages are encapsulated in respective folders. If all the JARs are in my current folder including my main class file then why can't I run it with:
java -cp "." MyProgram
or simply:
java MyProgram
If the problem is with the multiple JAR files to include and that's why we used ".\\*" to include all the JARs in the classpath, then why do we have to explicitly include the current folder again in the classpath using:
java ".\\*;." MyProgram
To include all jar required to run your program in command prompt use wildcard *:
java -classpath E:\lib\* HelloWorld
You are using "." that defines current directory and "./*" defines all files in current directory.
The class path is a list of jar files and directories containing the classes and resources of your program. Mentioning a jar file adds its contents to the class path.
"./*" will get you only the jar files in the current directory, "." adds the current directory to the class path. This allows to access all classes (and the jar files as raw file resources but not its contents, i.e. the classes contained in them).
If you need both in the class path, you have to specify both.
You've answered your own question, sort of.
. means that it will look for .class files in the current directory.
JARs act just like a directory. So to have the abc.jar "directory" you would specify abc.jar in your classpath.
If you need both the .class files present in the current directory, and the .class files packaged into JARs found in the current directory, you would have the following classpath: -cp ".:*.jar
All the answers here are telling you to use the wildcard without extension (* or ./*) but this is a bad practice, you don't want Java to go look into irrelevant files, so specify the extension: *.jar.
"." means current directory not files in the directory
"./*" means all files in current directory.
So you want to use all jars in current directory so 2nd will work
I'm having trouble running the jar command in cygwin. The input-files parameter isn't treating the directory I'm passing it recursively when I'm referencing it with ".."s in my path.
For example, I'm running this in the same directory as the "src" directory. src/ contains my package structure of class and java files. This runs properly and creates a jar containing my source and class files.
jar cf jarname.jar src
However when I run this next command, I get an empty jar except for a manifest file.
jar cf jarname.jar localdir/../src
I need to run this from a script that needs to find this directory with a ".." directory so I need the 2nd command to work.
Anybody know why this isn't working or have a workaround? I tried using realpath but it complains that it can't find that path at all. I may be using it wrong though.
The Directory path in cygwin is different . To navigate to any drive for example to C drive we need to type in:
/cygdrive/c
A very easy work around i found useful is just to type cmd in the terminal . This allows you to use the actual path than the cygwin specific path .
try typing cmd and then running the command , it worked for me
I have a jar file which I do not have the source code but want to use.
The jar file prompts for a file to read and generates an output file using a combinatin of the input file and a number of 'helper' files it uses for data. It works perfecty fine if run from its expected home directory, but I'm trying to write a script which will allow running the jar from anywhere.
The problem is that if I try running the jar file from anywhere other then its home directories it fails to find the support files it needs to properly generate its data.
If I run the file from its expected home directory I have to give the full address of the input file or it won't find it. I would prefer to be able to give just the relative path and Java know to look at whatever directory the person calling my script is in.
Is there a way I can have a bash script pass a command line argument to Java that would ensure that this jar looks at both of the relevant directories (directory of the helper files and the current dir of the person calling the script) when trying to resolve a relative file path? Something like the -classpath argument?
With the --classpath (or -cp) you can tell your Java program where it should take the dependency classes. So, probably if you do like in your files directory
$JAVA_HOME/bin/java -cp '.:/path/to/the/original/program' My.class myfile.txt
then it will wind the program, and find your files as well.
UPDATE
If it doesn't work, you can try to force the file loading some other way. The Javadoc says:
By default the classes in the java.io package always
resolve relative pathnames against the current user directory. This
directory is named by the system property user.dir, and
is typically the directory in which the Java virtual machine was
invoked.
So, you can try running the program from the original directory this way:
$JAVA_HOME/bin/java -Duser.dir=/path/to/the/files/directory My.class myfile.txt
UPDATE2:
As I wrote in a comment, you can try symlinks. Execute the following commands in the original directory:
ln -s /path/to/the/files/directory datafiles
$JAVA_HOME/bin/java My.class datafiles/myfile.txt
Sorry - ignore. I missed the first line of your question.
You could pass the two paths as an argument to the jar file - then append the path location at runtime. Many ways to do that, here is one:
java -DdirectoryA="/somewhere" -DdirectoryB="/elsewhere" -jar program.jar
and in your code
String pathA = System.getProperty("directoryA");
I've been learning about JAR files and wanted to try and create and run one myself. I carried out the following steps:
Created a project folder with a 'source' subfolder and a 'classes' subfolder
I wrote 2 source files, one with a main method which creates an instance of the other class and runs a simple method in it.
Compiled these to the 'classes' subfolder. I checked to see if they would run. They did
I created a manifest.txt file and filled in the Main-Class: xxxx and hit the return key. I saved this in the sources subfolder
Created a jar file in the classes subfolder by writing
jar -cvmf manifest.txt zzz.jar *.class
Tried to execute the jar file by typing
java -jar zzz.jar
This gives a ClassNotFound exception. If I try to execute the jar by double clicking on it in windows I get an errorbox saying "Could not find the main class xxxx"
I've double checked the spelling of the class inside the manifest file and it's correct.
Possibly important: I have to compile my programs using java -cp . xyz as there is an issue with my classpath. Does this mean that I need to execute jars in a different way as well? I tried
java -cp . -jar zzz.jar
but ended up with the same exception.
Edit: I ended up starting from scratch and now it runs (with the basic -jar zzz.jar command). Frustrating that I don't know what I was doing wrong but glad that it is working!
Shouldn't number 5. be run in the classes subfolder, where all your class files are? And if your classes are in packages, which they should be, you'll likely want to use * instead of *.class..?
To check what your jar file contains you can run:
jar tf zzz.jar
You will probably have to supply the entire path of the .class file you wish to execute after the classpath. ie java -cp xxx.jar classes.mainProgram.class. Where classes is the name of the folder which contains your class files.
Back story:
Long ago, before dinosaurs were around, there was a contractor that wrote a small Java program, that does some stuff, and prints some stuff to the screen.
Current: No one here knows much about Java but me - and I am not fluent.
The program works, but we kind of need just a bit more information on the screen. From the documentation available, I think I know how to go about that, and I definitely know how to print stuff, as it's simply using System.out.println() for this.
I have a .jar file, which I'm 99% certain is being loaded/used, which contains .java files matching every .class file within.
Is there an easy way to (and how might I) slightly modify one of the .java files, and "compile" the new version to replace the current matching .class file within the .jar?
I'm able to open and read the java source file, of course, but don't remember to procedures to turn java into "class" files, and especially not sure if I can just drop the resulting .class file into the .jar file as a replacement.
at the basic level, javac is the compiler; that will produce the .class files. There is also a "jar" command that will regenerate your jar file. Depending on the number of dependencies, that can get complicated quick. You can just type "javac" and "jar" (w/o quotes) to get the args to run it. Another option is to setup an ant build script...
so you could do something like (assuming windows OS):
javac -cp %MY_CLS_PTH% *.java
where MY_CLS_PTH is where any dependent classes are. If you have a package structure, this gets a little more complicated.
jar -cvf .\my_class_dir MyJarFile.jar
where my_class_dir is the directory that contains the .class files.
I think that is right (didn't run it myself) but that should be about the basics...
EDIT: There is a way to just add/re-add a single .class file to an existing jar file. Check out the "jar" command's usage, looks like "-u" will update it (of course you have to pass in the .class file). Also remember that any package structure you have in these classes, you need that directory structure and you reference the class via that dir structure. (Hope that is clear...)
Add myclass.class to the top level directory in myjar.jar:
jar uf myjar.jar myclass.class
Add myclass.class to the subdir directory in myjar.jar:
jar uf myjar.jar -C subdir myclass.class
Add a Version attribute to the manifest of myjar.jar:
First create a file somefile containing the line Version: "X.Y.Z", then
jar umf somefile myjar.jar