本节对类加载进行简要总结,本人其实很不喜欢那种大批量复制定义的那种,自己也记不住,浏览的人也不好理解,当然也记不住,其实好多东西都是重在理解,而是让大家去理解的,但是往往好多东西就是不太好理解,大多数情况下很难理解到位,希望本节的内容,以简短+实例的方式帮助大家理解这些生涩的知识点吧
类的加:将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区中,然后在内存中创建一个java.lang.Class对象(规范并为说明Class对象位于哪里,HotSpot虚拟机将其放在方法区中)用来封装类在方法区内的数据结构。
类加载的三个过程:
除了上述七种情况,都不会导致类的初始化。可能以上不全面的地方,后面会在进行修补,望读者能多多提意见,感谢…
上面已经总结了比较多的定义,记下来主要对主动使用的进行实例分析。
/**
* @author lijk
* @date 2019/12/25 11:36
*/
public class Mytest {
public static void main(String[] args) {
System.out.println(Dog .str);
}
}
class Animal{
public static String str="Animal field str";
static {
System.out.println("Animal Initialization");
}
}
class Dog extends Animal{
public static String str2="dog field str2";
static {
System.out.println("dog Initialization");
}
}
输出结果为
Animal Initialization
Animal field str
Process finished with exit code 0
以上可以看出子类调用父类的静态变量,子类并没有初始化,只有父类进行了初始化。这里怎么理解那?
对处于静态字段来说,只有直接定义了该字段的类才会被初始化(当前便是Animal类),所以只有父类进行初始化。虽Dog 这个类直接调用这个父类的静态变量,Dog没有被初始化,但是并不代表前两部的加载、连接没有进行,接下来对Dog这个类究竟做了什么进行分析?
以上是以idea进行设置,如图所示:
在VM options 添加vm参数
[Loaded java.lang.Class$MethodArray from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded java.lang.Void from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded com.mfhcd.jvm.chapter_1.webnesday.Animal from file:/E:/workSpace/CurrentProjects/jvm/target/classes/]
[Loaded com.mfhcd.jvm.chapter_1.webnesday.dog from file:/E:/workSpace/CurrentProjects/jvm/target/classes/]
Animal Initialization
Animal field str
[Loaded java.lang.Shutdown from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded java.net.Inet6Address from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded java.net.URI from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded java.net.URI$Parser from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded sun.net.spi.DefaultProxySelector$NonProxyInfo from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded sun.net.spi.DefaultProxySelector$3 from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded java.net.Proxy from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded java.net.Proxy$Type from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded java.util.ArrayList$Itr from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded sun.net.NetHooks from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
[Loaded java.net.Inet6Address$Inet6AddressHolder from D:\E\Java\jdk1.8.0_151\jre\lib\rt.jar]
以上只是一部分,上面一大堆的rt,jar包加载Loaded省略了,主要分析在Animal Initialization出现的时候,[Loaded com.mfhcd.jvm.chapter_1.webnesday.dog from file:/E:/workSpace/CurrentProjects/jvm/target/classes/]我们看到dog这个类被加载了,说明第一步加载是完成完成了的。
/**
* @author lijk
* @date 2019/12/25 11:36
*/
public class Mytest {
public static void main(String[] args) {
System.out.println(dog.str2);
}
}
class Animal{
public static String str="Animal field str";
static {
System.out.println("Animal Initialization");
}
}
class dog extends Animal{
public static String str2="dog field str2";
static {
System.out.println("dog Initialization");
}
}
输出结果为:
Animal Initialization
dog Initialization
dog field str2
Process finished with exit code 0
这个结果就很正常了,当一个子类在初始化时,要求其父类全部都需要已经初始化完毕了。
public class Mytest {
public static void main(String[] args) {
System.out.println("-------");
}
}
class Animal{
public static String str="Animal field str";
static {
System.out.println("Animal Initialization");
}
}
class dog extends Animal{
public static String str2="dog field str2";
static {
System.out.println("dog Initialization");
}
}
输出结果:
-------
Process finished with exit code 0
所有的Java虚拟机实现,必须在每个类或者接口的静态变量被Java程序‘首次主动使用‘时才初始化他们,上面的子类调用父类静态变量和子类调用子类静态变量都是可以印证这一点。
本节这里到此就结束了,以上主要从理论和实例角度进行了分析,下节将从字节码角度进行分析,正式认识Java代码,稀罕的点个关注…