Java 是否有任何方式可以多次执行静态块?如果是的话,那怎么办?
我的理解 静态块在类加载期间执行,如果类已加载,则除了类重新加载之外,没有其他方法加载该类 疑问/问题 1) 是否有JVM重新加载类的时间 我的理解 类内加载JVM加载Java文件的字节码,因此它无法将所有数千个类的字节码保存在内存中,因此它可能会丢弃很少使用的代码,并在必要时重新加载,在重新加载过程中JVM不会再次初始化静态变量和块(可能使用某种跟踪机制) 疑问/问题Java 是否有任何方式可以多次执行静态块?如果是的话,那怎么办?,java,classloader,Java,Classloader,我的理解 静态块在类加载期间执行,如果类已加载,则除了类重新加载之外,没有其他方法加载该类 疑问/问题 1) 是否有JVM重新加载类的时间 我的理解 类内加载JVM加载Java文件的字节码,因此它无法将所有数千个类的字节码保存在内存中,因此它可能会丢弃很少使用的代码,并在必要时重新加载,在重新加载过程中JVM不会再次初始化静态变量和块(可能使用某种跟踪机制) 疑问/问题 2) 如果我的上述理解不正确,请纠正我的错误。Java语言规范详细介绍了类的加载、卸载和重新加载机制 加载是指查找具有特定名称
2) 如果我的上述理解不正确,请纠正我的错误。Java语言规范详细介绍了类的加载、卸载和重新加载机制 加载是指查找具有特定名称的
类
或接口
类型的二进制形式的过程,可能是通过动态计算,但更典型的是通过检索编译器以前从源代码计算的二进制表示,并从该二进制形式构造,表示类或接口的Class
对象
Java虚拟机规范的第5章给出了加载的精确语义(每当我们在本书中提到Java虚拟机规范时,我们指的是JSR 924修订的第二版)。这里,我们从Java编程语言的角度对该过程进行了概述
类或接口的二进制格式通常是上述Java虚拟机规范中所述的类文件格式,但也可以使用其他格式,只要它们满足§13.1中规定的要求。class ClassLoader
的defineClass
方法可用于从类文件格式的二进制表示中构造class
对象
在某些情况下,可以卸载类和接口,这可能会导致无法预防的重新加载
Java编程语言的实现可以卸载类。如§12.6所述,当且仅当垃圾收集器可以回收类或接口的定义类加载器时,才可以卸载该类或接口。引导加载程序加载的类和接口可能无法卸载
类卸载是一种有助于减少内存使用的优化显然,程序的语义不应取决于系统是否以及如何选择实现优化,如类卸载。否则将损害程序的可移植性。因此,类或接口是否已卸载对于程序来说应该是透明的
但是,如果类或接口C在其定义加载程序可能可访问时被卸载,则C可能会被重新加载。人们永远无法确保这不会发生
事实上,它是为了解决您的具体问题:
例如,如果类具有以下情况,则重新加载可能不透明:
- 静态变量(其状态将丢失)
- 静态初始值设定项(可能有副作用)。
- 本机方法(可能保持静态)
据我所知,JVM永远不会重新加载类本身;一旦类被加载,它将永远保持加载状态。因此,类定义保存在“PermGen”内存池中
但是,您的类的字节码有可能由多个类加载器加载,每次发生这种情况时,静态块都会再次执行,因为这是一个新类。每个类仅在其自己的类加载器的作用域内可见,而通常任何类加载器都可以看到位于类路径上的字节码,因此这是一种可能的情况(如果不需要的话)。I如果显式使用新的类加载器再次加载该类,将再次执行此类的静态块。如果加载类的
类加载器无法访问,则可以卸载类:
当且仅当类或接口的定义类加载器可由
// 1st Static block invoked first.
static{
System.out.println("hello...1");
}
// 2nd Static block, invoked after 1st static block above.
static{
System.out.println("hello...2");
}
public static void Staticmeth() {
System.out.println("hello...3");
}
public static void main(String ag[]){
}