编译期间 java 和 运行 期间类加载器的顺序
order of classloader in java during compile time and run time
我在 class 下面创建了 java 中的限定名称 java.lang.String
。
package java.lang;
public class String {
public int getValue() {
return 42;
}
}
在 Main Class 中,我添加了以下代码。
public class Main {
public static void main(String[] args) {
String s = new String();
System.out.println(s.getValue());
}
}
代码编译正常。当我 运行 代码时,它失败并出现以下错误。
Exception in thread "main" java.lang.NoSuchMethodError: java.lang.String.getValue()I
at com.Main.main(Main.java:12)
我了解到 java.lang.String
是由 bootstrap classloader 在 运行 时间从 rt.jar 文件加载的。
所以,我认为class加载的顺序在编译时和运行时应该是不同的。能否请您给出 class 在编译时和 运行 时加载的顺序。
首先,此测试在 Java 9 或更高版本中不起作用。尝试编译 String
class 将出现此错误:
java/lang/String.java:1: error: package exists in another module: java.base
package java.lang;
^
在 Java 8,我得到了你看到的行为。假设调整后的 String
class 在同一源代码树中,Main
class 可以编译,但是当您尝试 运行 它时会出现异常。
这似乎被报告为 bug 4929425。解决方案是这是一个文档错误,他们澄清了 javac
命令的文档......虽然可能还不够。
总之,还是有区别的,而且是微妙的。
java
命令仅按以下顺序搜索:
- bootstrap class路径
- 扩展目录
- class路径
javac
命令首先搜索源目录。如果它在那里找到源文件,它会在同一位置查找相应的 class 文件,并(如有必要)编译或重新编译它。如果未找到源文件,则它会在 class 路径中搜索 class 文件,如上文所述 java
.
请注意,需要非常仔细地阅读 javac
手册条目才能弄清这一点。很容易错过。 (https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#searching)
(IMO,他们可以使手册页更清晰。但是,如果您试图覆盖 bootstrap class 路径上的某些 class 或在扩展目录中。而您以错误的方式进行操作。基本上,这是一种边缘情况。清楚地记录晦涩的边缘情况的问题在于,您最终可能会使正常情况下的文档更加混乱。)
我在 class 下面创建了 java 中的限定名称 java.lang.String
。
package java.lang;
public class String {
public int getValue() {
return 42;
}
}
在 Main Class 中,我添加了以下代码。
public class Main {
public static void main(String[] args) {
String s = new String();
System.out.println(s.getValue());
}
}
代码编译正常。当我 运行 代码时,它失败并出现以下错误。
Exception in thread "main" java.lang.NoSuchMethodError: java.lang.String.getValue()I
at com.Main.main(Main.java:12)
我了解到 java.lang.String
是由 bootstrap classloader 在 运行 时间从 rt.jar 文件加载的。
所以,我认为class加载的顺序在编译时和运行时应该是不同的。能否请您给出 class 在编译时和 运行 时加载的顺序。
首先,此测试在 Java 9 或更高版本中不起作用。尝试编译 String
class 将出现此错误:
java/lang/String.java:1: error: package exists in another module: java.base
package java.lang;
^
在 Java 8,我得到了你看到的行为。假设调整后的 String
class 在同一源代码树中,Main
class 可以编译,但是当您尝试 运行 它时会出现异常。
这似乎被报告为 bug 4929425。解决方案是这是一个文档错误,他们澄清了 javac
命令的文档......虽然可能还不够。
总之,还是有区别的,而且是微妙的。
java
命令仅按以下顺序搜索:
- bootstrap class路径
- 扩展目录
- class路径
javac
命令首先搜索源目录。如果它在那里找到源文件,它会在同一位置查找相应的 class 文件,并(如有必要)编译或重新编译它。如果未找到源文件,则它会在 class 路径中搜索 class 文件,如上文所述 java
.
请注意,需要非常仔细地阅读 javac
手册条目才能弄清这一点。很容易错过。 (https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#searching)
(IMO,他们可以使手册页更清晰。但是,如果您试图覆盖 bootstrap class 路径上的某些 class 或在扩展目录中。而您以错误的方式进行操作。基本上,这是一种边缘情况。清楚地记录晦涩的边缘情况的问题在于,您最终可能会使正常情况下的文档更加混乱。)