Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `javac -cp` not need `.`, while `java -cp` does?

Tags:

java

javac

I have two questions:

Why does javac -cp not need .?

$ javac -cp /home/t/programs/java/test/junit-4.11.jar TestCase.java

Why does java -cp need .?

$ java -cp /home/t/programs/java/test/junit-4.11.jar:/home/t/programs/java/test/hamcrest-core-1.3.jar org.junit.runner.JUnitCore TestCase
JUnit version 4.11
Could not find class: TestCase

Time: 0.002

OK (0 tests)

$ java -cp .:/home/t/programs/java/test/junit-4.11.jar:/home/t/programs/java/test/hamcrest-core-1.3.jar org.junit.runner.JUnitCore TestCase
JUnit version 4.11
.running TestCase test1
.running TestCase test2

Time: 0.023

OK (2 tests)

TestCase.java:

import static org.junit.Assert.*;
import org.junit.Test;

// define a test case class, whose instances represent test cases
public class TestCase {

  @Test
  public void test1() {
      System.out.println("running TestCase test1");
      assertTrue(true);
  }

  @Test
  public void test2() {
      System.out.println("running TestCase test2");
      assertTrue(true);      
  }

}
like image 604
Tim Avatar asked Apr 11 '19 12:04

Tim


2 Answers

Because javac handles files, java handles fully qualified class names.

EDIT

To expand a bit, when you're compiling, you're passing the files you want to compile directly to javac, so the classpath is only meant to contain the packages you need to compile the files you're passing in as argument. That is, the file you're compiling doesn't need to be in the classpath.

On the other hand, when you're executing with java, you're telling the JVM "run this class from the classpath". Granted, the default classpath is .. But then you decided to specify a custom classpath with -cp, which does not add to the classpath, but ovverides it. So you have to add it back explicitly.

See the last section of the official tutorial for confirmation.

like image 124
Federico klez Culloca Avatar answered Nov 01 '22 14:11

Federico klez Culloca


. being part of the compiler's classpath is the result of a couple of things happening implicitly. In order to be able to compile, generated classes referenced in other classes need to be accessible via classpath. So the compiler adds the class-file-destination path to the classpath. If you don't provide anything in particular, that directory is the source-directory. If you don't provide that specifically the process' working directory is used which is by default ..

Calling javac -help shows you the different possible settings:

"c:\Program Files\Java\jdk1.8.0_181\bin\javac.exe" -help
Usage: javac <options> <source files>
where possible options include:
  -g                         Generate all debugging info
  -g:none                    Generate no debugging info
  -g:{lines,vars,source}     Generate only some debugging info
  -nowarn                    Generate no warnings
  -verbose                   Output messages about what the compiler is doing
  -deprecation               Output source locations where deprecated APIs are used
  -classpath <path>          Specify where to find user class files and annotation processors
  -cp <path>                 Specify where to find user class files and annotation processors
  -sourcepath <path>         Specify where to find input source files
  -bootclasspath <path>      Override location of bootstrap class files
  -extdirs <dirs>            Override location of installed extensions
  -endorseddirs <dirs>       Override location of endorsed standards path
  -proc:{none,only}          Control whether annotation processing and/or compilation is done.
  -processor <class1>[,<class2>,<class3>...] Names of the annotation processors to run; bypasses default discovery process
  -processorpath <path>      Specify where to find annotation processors
  -parameters                Generate metadata for reflection on method parameters
  -d <directory>             Specify where to place generated class files
  -s <directory>             Specify where to place generated source files
  -h <directory>             Specify where to place generated native header files
  -implicit:{none,class}     Specify whether or not to generate class files for implicitly referenced files
  -encoding <encoding>       Specify character encoding used by source files
  -source <release>          Provide source compatibility with specified release
  -target <release>          Generate class files for specific VM version
  -profile <profile>         Check that API used is available in the specified profile
  -version                   Version information
  -help                      Print a synopsis of standard options
  -Akey[=value]              Options to pass to annotation processors
  -X                         Print a synopsis of nonstandard options
  -J<flag>                   Pass <flag> directly to the runtime system
  -Werror                    Terminate compilation if warnings occur
  @<filename>                Read options and filenames from file

The options I referred to are -s and -sourcepath. -cp is used to define additional locations (directories and library files) where the compiler can look for already compiled classes. That's also the meaning of -cp when calling java, so there is no contradiction between these two executables.

like image 1
Lothar Avatar answered Nov 01 '22 14:11

Lothar