I am a Java beginner and trying to figure out how to use the apache commons lib.
Here is a source file Randstr.java:
import org.apache.commons.lang3.RandomStringUtils;
class Randstr {
public static void main(String[] args) {
String s = RandomStringUtils.random(12);
System.out.println(s);
}
}
I have the commons-lang3-3.1.jar file in /usr/share/java/ and have created a symlink in the current dir. Then I compiled it like this: javac -cp commons-lang3-3.1.jar Randstr.java, the complilation was fine, but when I execute java Randstr, I got the following error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang3/RandomStringUtils
at Randstr.main(Randstr.java:5)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.RandomStringUtils
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
And if I don't specify the jar file in the classpath, it will not even compile:
javac -cp . Randstr.java
# Randstr.java:1: error: package org.apache.commons.lang3 does not exist
# import org.apache.commons.lang3.RandomStringUtils;
# ^
# Randstr.java:5: error: cannot find symbol
# String s = RandomStringUtils.random(12);
# ^
# symbol: variable RandomStringUtils
# location: class Randstr
# 2 errors
javac -cp /usr/share/java/ Randstr.java
# Randstr.java:1: error: package org.apache.commons.lang3 does not exist
# import org.apache.commons.lang3.RandomStringUtils;
# ^
# Randstr.java:5: error: cannot find symbol
# String s = RandomStringUtils.random(12);
# ^
# symbol: variable RandomStringUtils
# location: class Randstr
# 2 errors
From reading other questions on stackoverflow, I see this can be solved by using an IDE, but I prefer a simple editor at the moment.
If you can compile it with
javac -cp commons-lang3-3.1.jar Randstr.java
then you can run it with
java -cp commons-lang3-3.1.jar:. Randstr
The JAR file has to be in the classpath.
Edit your profile file. vim ~/.bashrc
In your profile file add the following line:
export CLASSPATH=/usr/share/java/commons-lang3-3.1.jar:.
Log out and back in. Or source your profile file in the windows you have open. You can always add your classpath to every java and javac command you invoke but that becomes a pain. With the CLASSPATH environmental variable you don't have to add it on the command line any more. Note that if you are using an IDE such as NetBeans or Eclipse you still might have to add the library to your project's libraries within the IDE.
Clearly the contents of /usr/share/java/ don't automatically get added to the classpath - it's just a common location where APT packages put Java libraries. It's up the developer to reference them correctly.
JARs in the ext/ subdirectory of a Java installation do get added to the classpath automatically. However, do not put your own JARs in there. It's a terrible practice because it doesn't match how Java apps are deployed "in the real world".
The correct way is using the -cp parameter explicitly when compiling AND running your app. Java doesn't compile library code into your .class files, a .class file only refers to names of other classes which are then loaded as-needed from the class path when your app runs. The -cp parameter takes only .jar files, or directories with .class files in them. You can also use wildcards in the value of that parameter. For more information on wrangling the class path, check the tool documentation on setting the class path.
You using a build tool that sets it for you automatically, like an IDE or Maven or another build system with dependency management. (Gradle or Ant+Ivy.) If you're writing a Java app that uses third party libraries, I very strongly suggest you learn and use one of those. (Also, most IDEs can work with Maven's configuration files letting you use the same build settings in a team with people using mixed or no IDEs.) Generally if you're invoking a compiler directly you're not doing it right.
Related
I'm a dev student
I would love to use Picocli in my project, unfortunately I doesn't understand how to compile using Picocli
I trie to follow the instruction given here https://picocli.info/ or here https://picocli.info/quick-guide.html but the step to compile aren't detailed. I'm not using Gradle nor Maven but they aren't really listed as required.
This is how it tried to compile the Checksum example given in the picocli.info webpage :
jar cf checksum.jar Checksum.java ; jar cf picocli-4.6.1.jar CommandLine.java && echo "hello" > hello
Then I simply copy paste this gived command : https://picocli.info/#_running_the_application
java -cp "picocli-4.6.1.jar:checksum.jar" CheckSum --algorithm SHA-1 hello
And get the following result :
Error: Could not find or load main class CheckSum
Caused by: java.lang.ClassNotFoundException: CheckSum
I tried to compile everything myself and then add the .jar like this :
java CheckSum -jar picocli-4.6.1.jar
But then the error output looks like this:
Exception in thread "main" java.lang.NoClassDefFoundError: picocli/CommandLine
at CheckSum.main(Checksum.java:33)
Caused by: java.lang.ClassNotFoundException: picocli.CommandLine
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more
Witch I don't understand since I added the dependency.
What am I missing ?
Thanks in advance
The problem is that the command jar cf checksum.jar Checksum.java only creates a jar file (jar files are very similar to zip files) that contains the Checksum.java source file.
What you want to do instead is compile the source code first. After that, we can put the resulting Checksum.class file (note the .class extension instead of the .java extension) in the checksum.jar. The Java SDK includes the javac tool that can be used to compile the source code. Detailed steps follow below.
First, open a terminal window and navigate to a directory that contains both the Checksum.java source file and the picocli-4.6.1.jar library.
Now, the command to compile (on Windows) is:
javac -cp .;picocli-4.6.1.jar Checksum.java
Linux uses : as path separator instead of ;, so on Linux, the command to compile is:
javac -cp .:picocli-4.6.1.jar Checksum.java
The -cp option allows you to specify the classpath, which should contain the directories and jar/zip files containing any other class files that your project uses/depends on. Since Checksum.java uses the picocli classes, we put the picocli jar in the classpath. Also add the current directory . to the classpath when the current directory contains any classes. I just add . habitually now.
Now, if you list the files in the current directory, you should see that a file Checksum.class has been created in this directory.
Our Checksum class has a main method, so we can now run the program with the java tool:
On Windows:
java -cp .;picocli-4.6.1.jar Checksum
On Linux:
java -cp .:picocli-4.6.1.jar Checksum
Note that when running the program with java you specify the class name Checksum, not the file name Checksum.class.
You can pass arguments to the Checksum program by passing them on the command line immediately following the class name:
java -cp .:picocli-4.6.1.jar Checksum --algorithm=SHA-1 /path/to/hello
When your project grows, you may want to keep the source code and the compiled class files in separate directories. The javac compile utility has a -d option where you can specify the destination for the compiled class files. For example:
javac -cp picocli-4.6.1.jar:otherlib.jar -d /destination/path /path/to/source/*.java
This should generate .class files for the specified source files in the specified destination directory (/destination/path in the example above).
When you have many class files, you may want to bundle them in a single jar file. You can use the jar command for that. I often use the options -v (verbose) -c (create) -f (jar file name) when creating a jar for the compiled class files. For example:
jar -cvf MyJar.jar /destination/path/*.class /destination/path2/*.class
Enjoy!
I am trying to run .jar file for my java code from a .sh shell script file. the jar file name contains "." which is making the Cygwin terminal think it is a directory. Here is the command and the results:
java -jar ./lib/javax.json-1.0.jar
Result:
no main manifest attribute, in lib\javax.json-1.0.jar
Then:
error: package javax.json does not exist
import javax.json.Json;
With this mark ^ below the period (right after javax).
How can I solve it? I am working on Windows 10. Thanks!
EDIT:
I have written many forms of the .sh file to get it run, but it won't run. The current one is:
# !bin/bash
java -jar ./lib/javax.json-1.0.jar
java -jar ./lib/javax.json-api-1.0.jar
javac ./src/TimeTester.java
java TimeTester
Does this look good?
I am getting the following error:
.\src\TimeTester.java:22: error: package javax.json does not exist
import javax.json.Json; (With this ^ below the '.')
AND:
.\src\TimeTester.java:159: error: cannot find symbol
private static JsonObject getJsonFromString(String jsonStr){
And many similar lines in the error.. Any help?
EDIT 2:
This is my current file:
javac -cp ./lib/javax.json-1.0.jar:./lib/javax.json-api-1.0.jar ./src/TimeTester.java
java -cp ./lib/javax.json-1.0.jar:./lib/javax.json-api-1.0.jar:./src TimeTester
But I am getting:
.\src\TimeTester.java:22: error: package javax.json does not exist
import javax.json.Json;
^
With With this (^) under the last dot (.Json)
EDIT 3:
The current .sh file is:
#!/usr/bin/env bash
cd src
javac -cp '../lib/javax.json-1.0.jar;../lib/javax.json-api-1.0.jar' TimeTester.java
java -cp '../lib/javax.json-1.0.jar;../lib/javax.json-api-1.0.jar' TimeTester
The first command (javac) works and generates the .class file. BUT, the second command (java) does not work and it gives the following error:
Error: Could not find or load main class TimeTester
Your help is really appreciated!
Final EDIT:
Thanks for Jim, the shell script now works. Now I got a java execution error:
java.io.FileNotFoundException: .\in_input\in.txt (The system cannot find the path specified)
Thanks
TL;DR It is a pain to use Cygwin with programs written for Windows because of the conflicting command-line shell conventions between bash and cmd.exe. To compile and run Java programs it is much better to use an IDE such as Eclipse or Netbeans.
However, if you must...
None of this works because you are trying to pass Linux-style paths to the Windows JVM. However you seem to have a more basic misunderstanding:
# !bin/bash
java -jar ./lib/javax.json-1.0.jar
java -jar ./lib/javax.json-api-1.0.jar
javac ./src/TimeTester.java
java TimeTester
I am surmising that you think the first two statements make the libraries available to the compiler for the third javac line. This is not true, those two lines attempt to execute the jar file, which of course fails since the jar does not contain a main class
What you should be doing is providing those two library paths as arguments to the -cp option of the javac command.
This is where it gets quite tricky, as you are mixing a Linux-style shell emulator with a Windows JVM. Paths that are intended for the shell must remain in Linux style, while paths that are going to be consumed by the JVM must be converted to Windows format, and path strings for the JVM must be delimited with semicolon (Windows style) instead of colon (Linux style). That introduces a further complication since the semicolon in Cygwin (Linux) is the delimiter for multiple commands on one line, so the path string must be quoted to prevent the semicolon from breaking things.
Also problematic is the naming of the class to be compiled. You have not shown us the package declaration of the Java file, but I'm assuming it's in the default package (i.e. there is no package declaration and it's not package src;). In that case you should be in the src directory, not one directory above.
Finally, once you specify -cp, you must also add the current directory to the classpath on Windows if you want it to be included, otherwise it will not find your newly-compiled .class file.
So the compile and execute commands should be
javac -cp '../lib/javax.json-1.0.jar;../lib/javax.json-api-1.0.jar' TimeTester.java
java -cp '.;../lib/javax.json-1.0.jar;../lib/javax.json-api-1.0.jar' TimeTester
For simple relative paths the Windows JVM will accept forward slashes, but if you have absolute Linux paths (i.e. /cygdrive/c/..., or with the cygdrive path set to /, paths like /c/user/...) the JVM will not understand them and they will need to be translated using cygpath.
None of your 4 commands work:
java -jar ./lib/javax.json-1.0.jar does not work because javax.json-1.0.jar is not an executable jar file.
java -jar ./lib/javax.json-api-1.0.jar does not work because javax.json-api-1.0.jar is not an executable jar file.
javac ./src/TimeTester.java does not work because your class requires classes from the javax.json package to be on the classpath, and you haven't set the classpath. Classes from the javax.json package are found in the javax.json-1.0.jar file.
java TimeTester does not work because the compilation failed.
To fix all that, remove the first two lines, and specify the classpath on the other two lines, e.g.
javac -cp ./lib/javax.json-1.0.jar:./lib/javax.json-api-1.0.jar ./src/TimeTester.java
java -cp ./lib/javax.json-1.0.jar:./lib/javax.json-api-1.0.jar:./src TimeTester
Notice that you also had to list ./src on the classpath when executing your program.
I have trying to compile java files at the windows command line using commands such as:
java myProg once I have used javac to create class files.
Problems arise when I use packages with a number of source files.
Often but not always I get main not found errors even though a main exists.
I am not quite sure what some of the directives mean and that is why it seems hit or miss.
Question
what does -cp mean exactly? java -cp src\myDirectory.myfile
sometimes I see:
./ infront of source eg .\src\myDirectory.myfile
on other sites I have found
% javac -cp .;stdlib.jar MyProgram.java
% java -cp .;stdlib.jar MyProgram
while compiling a jar library with java source files
what doesthe ".;" mean?
basically how do I compile three java source java files in one package at the windows command line and what does -cp and .; mean?
-cp means class path if I'm not mistaken.
try reading the following java docs
-classpath path
Specifies the path javac uses to look up classes needed to run javac or being referenced by other classes you are compiling. Overrides the default or the CLASSPATH environment variable if it is set. Directories are separated by semi-colons. It is often useful for the directory containing the source files to be on the class path. You should always include the system classes at the end of the path. For example:
javac -classpath .;C:\users\dac\classes;C:\tools\java\classes ...
https://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/tooldocs/win32/javac.html
Answering your question directly, -cp means classpath or path.
Details on commandline arguments used while compiling and running a Java application can be found here: javac - Java programming language compiler
Extracting the description of -cp from that page:
-cp path or -classpath path:
Specify where to find user class files, and (optionally) annotation processors and source files. This class path overrides the user class path in the CLASSPATH environment variable. If neither CLASSPATH, -cp nor -classpath is specified, the user class path consists of the current directory. See Setting the Class Path for more details.
. means the current directory.
To compile multiple files in a directory use the following:
javac *.java // compliles all java files in the dir
java MyClass // runs the particular file
There are also a bunch of other related questions that should help you resolve this:
How to run a java program from the command line
How do I run java program with multiple classes from cmd?
Problems running a java program from the command line interface
Can't run multiple-class program from command line using packages
I have been testing the examples (HelloWorld.java) from Sphinx4 with Eclipse, but I would like to compile and run them from the command line.
The application needs 5 .jars to be able to run, I have read that in order to compile a java class with multiple .jars I need to execute the following command (as an example I will show short names):
javac -cp one.jar:two.jar:three.jar:four.jar:five.jar HelloWorld.java
The console does not throw any error messages:
parias001#parias001-pc:~/Projects/citadel_voices/sphinx_test > javac -cp jsapi.jar:sphinx4.jar:TIDIGITS_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar:WSJ_8gau_13dCep_8kHz_31mel_200Hz_3500Hz.jar:WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar HelloWorld.java
parias001#parias001-pc:~/Projects/citadel_voices/sphinx_test >
I think that the compilation succeeded. Now I would like to run the application, I read that in order to do this, I have to execute the command as follows (Using short name example as before):
java -cp one.jar:two.jar:three.jar:four.jar:five.jar HelloWorld
This is the message that the console throws:
parias001#parias001-pc:~/Projects/citadel_voices/sphinx_test > java -cp jsapi.jar:sphinx4.jar:TIDIGITS_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar:WSJ_8gau_13dCep_8kHz_31mel_200Hz_3500Hz.jar:WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar HelloWorld
Error: Could not find or load main class HelloWorld
I don't know what is going on here, I should also say that I do not have a lot of experience using external .jars.
The names of the .jars are:
jsapi.jar
sphinx4.jar
TIDIGITS_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar
WSJ_8gau_13dCep_8kHz_31mel_200Hz_3500Hz.jar
WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar
I appreciate any help you can give me.
You have to include current directory in classpath:
java -cp .:one.jar:two.jar:three.jar:four.jar:five.jar HelloWorld
Note the leading .:
From this reference:
The default class path is the current directory. Setting the CLASSPATH variable or using the -classpath command-line option overrides that default, so if you want to include the current directory in the search path, you must include "." in the new settings.
This should be simple but I have never done it before and didn't find any solution.
I am currently using Eclipse to code my program, which imports some external JAR library such as google data api library. I can use Eclipse to compile/build/run the program.
But now I want to run it in terminal, so where should I put those JAR files, and how to build and run the program?
Thanks!
You can do :
1) javac -cp /path/to/jar/file Myprogram.java
2) java -cp .:/path/to/jar/file Myprogram
So, lets suppose your current working directory in terminal is src/Report/
javac -cp src/external/myfile.jar Reporter.java
java -cp .:src/external/myfile.jar Reporter
Take a look here to setup Classpath
For compiling the java file having dependency on a jar
javac -cp path_of_the_jar/jarName.jar className.java
For executing the class file
java -cp .;path_of_the_jar/jarName.jar className
you can set your classpath in the in the environment variabl CLASSPATH.
in linux, you can add like
CLASSPATH=.:/full/path/to/the/Jars, for example ..........src/external
and just run in side ......src/Report/
Javac Reporter.java
java Reporter
Similarily, you can set it in windows environment variables.
for example, in Win7
Right click Start-->Computer
then Properties-->Advanced System Setting --> Advanced -->Environment Variables
in the user variables, click classPath, and Edit and add the full path of jars at the end.
voila
Suppose your jar application "myapp.jar" has the following code snippet written inside it.
import org.json.JSONObject;
public class Main {
public static void main(String[] args) {
// write your code here
System.out.println("Hello World!");
JSONObject jo = new JSONObject("{ \"abc\" : \"def\" }");
System.out.println(jo.toString());
}
}
It is using the external library json.jar from which we imported "org.json.JSONObject".
Running the following command will result in an error.
java -jar myapp.jar
Exception message:
Exception in thread "main" java.lang.NoClassDefFoundError: org/json/JSONObject at com.reve.Main.main(Main.java:10)
Caused by: java.lang.ClassNotFoundException: org.json.JSONObject at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source) at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
We must include the json.jar file while running the jar file. We have to specify the class path of the file before building our myapp.jar file.
Inside META-INF/MANIFEST.MF file:
Manifest-Version: 1.0
Class-Path: lib/json.jar lib/example2.jar
Main-Class: com.reve.Main
Specify the external libraries separated by spaces under the Class-Path keyword. Then after building the project and the artifact, we can run the jar file by simply writing the same command we discussed above.