javac classpath的顺序与Oracle文档矛盾? [英] javac classpath order contradicts Oracle documentation?

查看:77
本文介绍了javac classpath的顺序与Oracle文档矛盾?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Sierra/Bates SCJP 书页中797:

"java和javac首先在包含Java SE随附标准类的目录中查找. 然后他们查看由类路径定义的目录.

"java and javac [...] first look in the directories that contain the classes that come standard with Java SE. Then they look in the directories defined by classpaths"

Oracle文档说明了相同的顺序

(我知道我不应该这样做,但是...)为了测试此行为,我在目录中实现了 HashSet.java Lol.java : C:\ dev \ cmdline \ TestProject \ sources \ java \ util

(I know I shouldn't do that but...) To test this behaviour I implemented HashSet.java and Lol.java in directory: C:\dev\cmdline\TestProject\sources\java\util

package java.util;
public class HashSet {}

package java.util;
import java.util.HashSet;
public class Lol {
    public static void main(String... x) {
        HashSet a = new HashSet();
        a.add("lol");
    }
}

执行时出现编译错误: C:\ dev \ cmdline \ TestProject \ sources> javac java/util/Lol.java

I get a compilation error when executing: C:\dev\cmdline\TestProject\sources>javac java/util/Lol.java

java \ util \ Lol.java:6:错误:找不到符号 a.add("lol"); ^ 符号:方法add(String) 位置:HashSet类型的变量a

java\util\Lol.java:6: error: cannot find symbol a.add("lol"); ^ symbol: method add(String) location: variable a of type HashSet

...这意味着首先使用默认的类路径(当前目录).

...which means that the default classpath (current directory) is first used.

那么,Oracle文档是否错误?您将如何测试类路径顺序?

推荐答案

参考Oracle文档,SCJP书中的陈述可能被简化了. Oracle文档明确区分了"Java启动器"(java)和Java编译器javac.实际上,过程有所不同.

Referring to the Oracle Documentation, the statement from the SCJP book may be oversimplified. The Oracle Documentation explicitly differentiates between the "Java Launcher" (java) and the Java Compiler javac. And in fact, the processes are somewhat different.

我将尝试提取解释您所观察到的行为的相关部分:

I'll try to extract the relevant parts that explain the behavior that you are observing:

(来自如何找到类: Javac和JavaDoc如何查找类:)

(From How Classes are Found : How Javac and JavaDoc Find Classes:)

如果在类文件和源文件中都定义了引用的类,则javac将使用类文件,但是会自动重新编译它确定已过期的任何类文件.自动重新编译的规则记录在 Windows的javac文档中 Solaris .

If a referenced class is defined in both a class file and source file, [...] javac uses class files, but automatically recompiles any class files it determines to be out of date. The rules for automatic recompilation are documented in the javac document for Windows or Solaris.

这些链接的文档包含相应的小节(两种情况都相同),在此我再次引用:

These linked docments contain the corresponding subsection (which is the same in both cases), from which I'll quote here again:

(来自 javac-Java编程语言编译器:搜索类型:)

(From javac - Java programming language compiler : SEARCHING FOR TYPES:)

编译源文件时,编译器通常需要有关其定义未出现在命令行上给出的源文件中的类型的信息. [...]

When compiling a source file, the compiler often needs information about a type whose definition did not appear in the source files given on the command line. [...]

当编译器需要类型信息时,它将查找定义该类型的源文件或类文件. [...]

When the compiler needs type information, it looks for a source file or class file which defines the type. [...]

成功的类型搜索可能会产生类文件,源文件或两者.如果两者都找到,则可以使用-Xprefer选项来指示编译器使用哪个.如果给出 newer ,编译器将使用两个文件中的较新版本.如果给出了 source ,它将使用源文件.默认值为较新.

A successful type search may produce a class file, a source file, or both. If both are found, you can use the -Xprefer option to instruct the compiler which to use. If newer is given, the compiler will use the newer of the two files. If source is given, it will use the source file. The default is newer.

如果类型搜索本身或由于-Xprefer的设置而找到了所需类型的源文件,则编译器将读取源文件以获取所需的信息.另外,默认情况下,它也会编译源文件.您可以使用-implicit选项指定行为.如果给出,则不会为源文件生成任何类文件.如果给出 class ,将为源文件生成类文件.

If a type search finds a source file for a required type, either by itself, or as a result of the setting for -Xprefer, the compiler will read the source file to get the information it needs. In addition, it will by default compile the source file as well. You can use the -implicit option to specify the behavior. If none is given, no class files will be generated for the source file. If class is given, class files will be generated for the source file.

所以总结一下:javac编译器将为java.util.HashSet找到您的 source 文件,并从引导类中找到 class 文件.但是默认情况下,它将编译 source 文件.

So to summarize: The javac compiler will find your source file for java.util.HashSet, as well as the class file from the bootstrap classes. But by default, it will compile the source file.

(有趣的是,似乎没有一种简单的方法可以说服他不要使用源作为输入:-implicit选项仅确定是否 生成了.class文件,甚至如果设置了-implicit:none,它仍会使用从源代码创建的类...)

(And interestingly, there seems to be no easy way to convince him not to use the source as input: The -implicit option only determines whether a .class file is generated, but even if -implicit:none is set, it will still use the class that was created from the source...)

您还可以使用-verbose选项更详细地观看此过程:

You can also use the -verbose option to watch this process in more detail:

javac -verbose java/util/Lol.java

产生以下输出:

[parsing started RegularFileObject[java\util\Lol.java]]
[parsing completed 100ms]
[search path for source files: .]
[search path for class files: (A long list with rt.jar and related JARs)]
[loading RegularFileObject[.\java\util\HashSet.java]]
[parsing started RegularFileObject[.\java\util\HashSet.java]]
[parsing completed 0ms]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Object.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/String.class)]]
[checking java.util.Lol]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/AutoCloseable.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Byte.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Character.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Short.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Long.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Float.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Integer.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Double.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Boolean.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Void.class)]]
java\util\Lol.java:6: error: cannot find symbol
        a.add("lol");
         ^
  symbol:   method add(String)
  location: variable a of type HashSet
[checking java.util.HashSet]
[total 1072ms]
1 error

甚至不尝试从引导JAR加载HashSet`类,而是直接引用您的源文件:

It does not even try to load the HashSet` class from the bootstrap JARs, but instead, directly refers to your source file:

[loading RegularFileObject[.\java\util\HashSet.java]]

相反,当您省略自己的HashSet类时,您将看到预期的输出:

In contrast, when you omit your own HashSet class, you'll see the expected output:

[parsing started RegularFileObject[java\util\Lol.java]]
[parsing completed 100ms]
[search path for source files: .]
[search path for class files: (A long list with rt.jar and related JARs) ]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/util/HashSet.class)]]
[loading ZipFileIndexFileObject[c:\jdk1.8.0\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Object.class)]]
...

rt.jar获取HashSet类的地方.

这篇关于javac classpath的顺序与Oracle文档矛盾?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆