javac -classpath not doing the trick - java

I have a source file SerialTalk.java, in directory C:\javasrc\BattProj
This file imports classes from RXTXcomm.jar, eg.
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
...
RXTXcomm.jar is in the same directory as SerialTalk.java. I compile specifying a classpath pointing to the current directory:
javac -verbose -classpath . SerialTalk.java
Invariably, I get the following error. (Actually, many instances & variants of this error):
SerialTalk.java:3: error: package gnu.io does not exist
import gnu.io.CommPortIdentifier;
When I open the RXTXcomm.jar (eg. with 7-Zip) I can see the gnu.io structure, and the specific .class files that I'm trying to import.
So what am I doing wrong? The same .java (source) file has been compiled and run on another workstation within the Netbeans IDE. The difference here is I'm trying to compile it using javac from the command line. (Environment is Win7, 32 bit, jdk1.7.0_03)

So what am I doing wrong?
You're not putting the jar file on the class path. Putting the directory on the class path doesn't do it. That only tells javac where to find .class files in the directory structure, not jar files containing class files. You want:
javac -verbose -classpath .;RXTXcomm.jar SerialTalk.java

Related

NoClassDefFoundError for dependencies when compiling executable jar with no build tools

I'm trying to compile my Java program into an executable jar file, and I've tried following all the instructions in various places, but I'm encountering an issue.
Class Files
The first thing I do is compile everything to class files with this command.
javac -d ./build src/main/**/*.java -cp lib/main/commons-cli-1.4/commons-cli-1.4.jar:lib/main/commons-io-2.8.0/commons-io-2.8.0.jar
This compiles all the .java files in src/main (I don't want to compile the tests of course) into a folder called build. It also sets the classpath to all the .jar files that the code depends on (Apache Commons CLI and Apache Commons IO).
Jar Files
The next step is to generate the .jar file. For this, I use the following command (after cd ./build).
jar cvfm ../bin/program.jar manifest.txt .
Here, manifest.txt is in the folder build and contains the following. (It ends with a trailing newline, as per the documentation dictates.)
Main-Class: cli.Cli
Here, cli.Cli refers to the class named Cli located in src/main/cli/Cli.java which contains the main method.
Running the Jar
Now I use the following command to try to run the produced program.jar file, but I get this error.
$ java -jar build/program.jar
Error: Unable to initialize main class cli.Cli
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/cli/ParseException
This error is referring to one of the import statements in src/main/cli/Cli.java, which is supposed to be in the same .jar file as all the other import statements. The IDE does recognise the import, but I'm not sure why I am unable to run the file. Here is an extract of my imports from Cli.java.
package cli;
import java.io.IOException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.io.FilenameUtils;
// more imports...
Edit
I tried to change the manifest to contain a classpath, but that didn't seem to help at all. I tried the following two versions of the manifest.
Relative to bin/ or build/:
Main-Class: cli.Cli
Class-Path: ../lib/main/commons-cli-1.4/commons-cli-1.4.jar:../lib/main/commons-io-2.8.0/commons-io-2.8.0.jar
Relative to workspace folder (which is the current directory when I run the jar):
Main-Class: cli.Cli
Class-Path: lib/main/commons-cli-1.4/commons-cli-1.4.jar:lib/main/commons-io-2.8.0/commons-io-2.8.0.jar
Edit 2
I changed my code to not use ParseException but then another of the imports caused the same error.
Turns out the classpath in the manifest needed to be space-separated, with the paths to each jar relative to bin/, like so:
Main-Class: cli.Cli
Class-Path: ../lib/main/commons-cli-1.4/commons-cli-1.4.jar ../lib/main/commons-io-2.8.0/io-2.8.0.jar program.jar

Using javac with import

I try to compile this code:
package edu;
import java.io.*;
public class Main { ... }
with javac called from command line. I know that I need to do it this way:
javac -classpath /lib/* Main.java
and put .jar file with the 'java.io.*' classes in 'lib' folder in my project's directory.
Is my javac command correct - especially path to '/lib/*'?
How do I find the desired .jar file(s) so that I can copy them to my project's lib directory?
package java.io is part of core java, you do not have to put anything extra into your classpath

Compiling a java file using javac and the command line

I am trying to learn more about javac and how to use developer tools for Java using the command line.
As far as I understood, the option -classpath is needed to specify the path where javac searches for our classes and resource files, if we are not in the current directory, because usually the class path is set to our current working directory.
This is my current working directory:
/Users/user1/Desktop
And I am trying to compile a .java file which is in:
/Users/user1/Desktop/PF/
and the file is called MainClass.java.
I am trying to compile it using the following command:
javac -classpath /PF MainClass.java
But it does not seem to work, in fact I keep receiving the following:
javac: file not found: MainClass.java
Usage: javac <options> <source files>
use -help for a list of possible options
What am I doing wrong?
Classpath is for .class files, not for .java files.
javac command needs correct path to the .java file to compile it. So
javac ./PF/MainClass.java
Will create the class file in current directory.
If your MainClass.java depends on any class files to compile correctly, then you put those class/jar files in classpath.
That isn't how the classpath works. You use the classpath to point to classes that your Java file needs in order to compile. You don't use the classpath to point to the Java file itself.
Either go into the PF directory and do this:
javac MainClass.java
That will create the MainClass.class file inside the PF directory. If instead you want to create the MainClass.class file on your desktop, then from your desktop, do this:
javac PF/MainClass.java
-classpath
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 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.
class path is used to specify the compiled sources that need to be used in your class. For example in this code if you are accessing another class then you should specify the location of the compiled sources of the that class.
In your case if don't have any class dependency then simply remove classpath option and compile using[navigate inside folder]
javac Mainclass.java
Remove the -classpath. And if you are in the place where the java file is required (which currently you arent) you can remove that PF/ too.

Class not recognized

I've just installed the Java SDK 8, set the PATH and the CLASSPATH variables, put javax.mail.jar file in the bin directory, but when I try to compile my problem, all javax.mail classes aren't recongnized:
C:\Java>javac SendMail.java
SendMail.java:5: error: package javax.mail does not exist
import javax.mail.Message;
Here is the content of my CLASSPATH variable:
C:\Java>echo %CLASSPATH%
C:\"Program Files"\Java\jdk1.8.0_25\lib;.
And here is the content of the bin directory:
C:\Java>dir C:\"Program Files"\Java\jdk1.8.0_25\lib\*.jar
ant-javafx.jar
dt.jar
javafx-mx.jar
javax.mail.jar
jconsole.jar
sa-jdi.jar
tools.jar
What's the problem?
Classpath should contain the individual JAR files, not the directory that contains the jar files. Also the lib directory contains stuff you normally don't need. So you want just:
set CLASSPATH="C:\Program Files\Java\jdk1.8.0_25\lib\javax.mail.jar"
Also you can add classpath on your java.exe command line:
java.exe -cp "C:\Program Files\Java\jdk1.8.0_25\lib\javax.mail.jar" SendMail
(I haven't checked that myself, but...)
c:\"Program Files"\something doesn't seem like a good path to me.
Try setting CLASSPATH to:
"C:\Program Files\Java\jdk1.8.0_25\lib";.

Class not found / wrong name when using wsgen

I'm having an issue with wsgen and while I've seen some answers that worked none of those solutions seems to be working for me. I believe the problem is related to the structure of the source and binaries.
My WSTest project is setup with the following folders:
bin
└───com
└───example
└───ws
src
└───com
└───example
└───ws
The main class is Test which resides in package com.example.ws.
I'm running wsgen from the main project folder WSTest using the following command:
wsgen -cp ./bin/com/example/ws -d ./src/com/example/ws -s ./src/com/example/ws Test
This results in:
Exception in thread "main" java.lang.NoClassDefFoundError (wrong name: com/example/ws/Test)
This makes sense since the class is part of a package. So I change my command to the following:
wsgen -cp ./bin/com/example/ws -d ./src/com/example/ws -s ./src/com/example/ws com.example.ws.Test
But now I get class not found from the wsgen tool:
Class not found: "com.example.ws.Test"
Usage: WSGEN [options]
What am I missing?
Have you tried something like this?
wsgen -cp ./bin -d ./src -s ./src com.example.ws.Test
The classpath folder is were wsgen looks for class files. The package within the class is resolved to folder paths, so com.example.ws.Test should be a file like com/example/ws/Test.class within the bin classpath folder.
From the Java documentation:
Each classpath should end with a filename or directory depending on what you are setting the class path to:
For a .jar or .zip file that contains .class files, the class path ends with the name of the .zip or .jar file.
For .class files in an unnamed package, the class path ends with the directory that contains the .class files.
For .class files in a named package, the class path ends with the directory that contains the "root" package (the first package in the full package name).

Categories

Resources