- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
为了让我的问题更清楚,请考虑以下用例:
假设有一个包允许在给定平台上进行一组操作,例如在 Windows 上编辑注册表的类。这个包在其他平台上不存在,因为在其他操作系统上没有等效的操作。
为了简单起见,考虑
windows/Registry.java
package windows;
public class Registry {
static Registry instance = null;
static{
System.out.println("print from static block");
}
private Registry() {
System.out.println("Registry instance created!");
}
public static synchronized Registry getInstance() {
if (null == instance) {
instance = new Registry();
}
return instance;
}
public void foo() {
System.out.println("foo called.");
}
}
以及我将有条件地使用注册表的类:main/Main.java
package main;
import windows.Registry;
public class Main {
public static void test1(boolean onWindows) {
if (onWindows) {
Registry instance = Registry.getInstance();
System.out.println("We are on Windows: ");
instance.foo();
} else {
System.out.println("We are somewhere else!");
}
}
public static void main(String[] args) {
System.out.println("Entered main");
boolean onWindows = args.length > 0 ? Boolean.parseBoolean(args[0]) : false;
test1(onWindows);
}
}
问题是,如果Main.class
中没有明确执行函数或类,是否保证Registry.class
中的代码不会被执行?
我能够在多个桌面平台和不同的 java 版本上测试此示例,但我想知道是否记录了此行为并且可以依赖它,是否因此在其他平台上也是预期的行为,例如JRE 的 android 或嵌入式版本。
如果没有这样的保证,因为(可能是自定义的)类加载器可能决定加载类路径中的所有 .class
文件,我可以假设代码在没有 的情况下也可以工作java.lang.NoClassDefFoundError
如果 onWindows
为假并且我从类路径中删除 Registry.class
?
到目前为止我观察到的行为是
rm -rf bld; mkdir bld && javac -d bld src/windows/Registry.java src/main/Main.java && java -classpath bld main.Main true
Entered main
print from static block
Registry instance created!
We are on Windows:
foo called.
rm -rf bld; mkdir bld && javac -d bld src/windows/Registry.java src/main/Main.java && java -classpath bld main.Main false
Entered main
We are somewhere else!
rm -rf bld; mkdir bld && javac -d bld src/windows/Registry.java src/main/Main.java && rm -r bld/windows && java -classpath bld main.Main false
Entered main
We are somewhere else!
rm -rf bld; mkdir bld && javac -d bld src/windows/Registry.java src/main/Main.java && rm -r bld/windows && java -classpath bld main.Main true
Entered main
Exception in thread "main" java.lang.NoClassDefFoundError: windows/Registry
at main.Main.test1(Main.java:9)
at main.Main.main(Main.java:20)
Caused by: java.lang.ClassNotFoundException: windows.Registry
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 2 more
是否定义了这些行为(惰性类加载器和删除 Registry.class
)?
最佳答案
The question is, if no function or class is explicitly executed in
Main.class
, is it guaranteed that no code fromRegistry.class
is executed?
这并不直接涉及类加载,而是涉及类初始化,这是相关类中的任何代码被执行的第一个点。具体来说,在这个阶段执行静态初始化 block 和静态成员的初始化器。有问题的类此时必须已经加载和验证,但它可能已经加载了任意时间。
根据 JLS 12.4.1 ,
A class or interface T will be initialized immediately before thefirst occurrence of any one of the following:
T is a class and an instance of T is created.
A
static
method declared by T is invoked.A
static
field declared by T is assigned.A
static
field declared by T is used and the field is not a constant variable
因此,如果您从不实例化该类或访问它的任何静态方法或字段(读取作为“常量变量”的静态字段除外),则不会执行该类中的任何代码。
但是一个类没有被初始化并不意味着不会尝试加载它。 JLS 不禁止实现预先加载类。事实上,JLS 12.2.1具体来说:
a class loader may cache binary representations of classes and interfaces, prefetch them based on expected usage, or load a group of related classes together.
因此,不,依靠您的类 main.Main
表示的应用程序在没有 java.lang.NoClassDefFoundError
或其他加载错误的情况下运行是不安全的当类 windows.Registry
无法加载时,无论是否可以预期实际使用。但是,您可以在适当的情况下依赖未初始化的类,因此不会执行其中的任何代码。
关于java - 如果从不使用相应的类,类加载器是否会加载类文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71356282/
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 6 年前。 Improve t
notificationCenterPublisher = NotificationCenter.default .publisher(for: .NSManagedObjec
我有以下 Rust 代码: #[inline(never)] fn x() -> i32 { 21 } pub fn main() -> i32 { x() } 如果没有优化 (-C
notificationCenterPublisher = NotificationCenter.default .publisher(for: .NSManagedObjec
我有以下 Rust 代码: #[inline(never)] fn x() -> i32 { 21 } pub fn main() -> i32 { x() } 如果没有优化 (-C
假设我的 ASPX 页面没有内联 C# 代码块。 所以,我可以安全地设置 ...在我的 web.config 文件中,不用担心编译错误。 就性能而言,使用以下设置是否会有任何损失? 即“自动”检测
应用程序.js var win1 = Titanium.UI.createWindow({ title:'Tab 1', backgroundColor: 'black', l
基本上,我正在为实现多级优先级队列的 xv6 内核实现一个调度程序。我有一个严重的问题,我不明白,我类(class)的助教不明白,我已经错过了这个项目的最后期限,所以现在帮助我不会给我任何加分 - 但
我想避免 git 自动 merge 我的 composer.json。这样我就可以在 develop 分支中有一个使用 dev-develop 包的 composer.json,而 master 中的
当比较两种不同的算法实现时(因此,不关心它们的绝对性能,而只关心相对性能)我是否最好强制 Java 只运行解释代码? 也就是说,打开 -Xint 标志会更好吗? 最佳答案 我不认为禁用 JIT 会更好
class A{ const size_t number; public: A(size_t number): number(number) {} void f(){
问题 寻找在以下之间切换的方法: 总是 从不 仅在静默模式下 仅当不处于静默模式时 这些选项在手机上的路径---菜单>>设置>>声音>>振动---找到。 通过手机导航很容易更改(顺便说一句,我的手机是
如何设置电源设置关闭:从不(关闭显示器=从不,让计算机进入休眠状态=从不),通过c#代码 最佳答案 这个问题中给出的链接可以告诉你一个方法。 Programmatically change Windo
我是一名优秀的程序员,十分优秀!