1 一个java程序运行时,只能指定一个入口地址,也就是指定一个类的main方法

 

2 类加载或者类初始化(实际上涵盖了下面三个流程)

 

2.1 类加载

JVM把.class文件读入内存,生成java.lang.Class实例。class是描述的对象的抽象概念,但是使用时候,也是需要一个实例去实现。这个java.lang.Class<M>的实例(代表一个M的类或者接口)就可以去创建M类的实例。

就像一个哲学问题:即概念是用来抽象具体事物,但概念的本身也是具体事物

 

类的加载由类加载器完成,用户可以继承ClassLoader来创建自己的类加载器:

(1)从本地文件系统加载class

(2)从jar包加载class

 

2.2 连接

把类的二进制数据合并到jre中,主要下面三点:

(1)校验:jvm的类加载是否正确

(2)分配:为类变量(static)分配内存,设置默认初始值(用户设置的初始值,在类的初始化中完成)

(3)解析:

 

2.3 初始化

由jvm对类变量进行初始化,static变量初始化为用户的设置值,static{}静态块的执行。

 

类初始化的时机:

(1)使用new,反射newInstance ,反序列化来创建实例

(2)调用类static方法

(3)访问或者赋值类的静态变量和接口变量

(4)强行初始化:Class.forName("User"),如果这个类没有初始化,则初始化,并返回User对应的java.lang.Class对象(注意ClassLoader.loadClass()只会加载这个类,Class.forName()才会初始化类)

(5)初始化子类时,其父类未被初始化过,则初始化所有父类

(6)主类(main方法,入口所在类)会先于其他类被初始化

 

3 类加载器

实现类加载需要类加载器。JVM启动会三种类加载器

(1)bootstrap classLoader 引导类加载器,如加载JAVA_HOME/jre/lib下的

(2)extension classLoader 扩展类加载器,如加载JAVA_HOME/jre/lib/ext下的

(3)system classLoader 系统类加载器,加载classPath下的

 

 

4 编译时类型和运行时类型

编译时类型和运行类型可能不同,如果要在运行时操作真实的运行对象,有两种方法

(1)编译时就知道运行时类型,则采用:instanceof + 强制转换

(2)编译时不知道运行时类型,采用反射:Object.getClass()返回运行时类型,是一个Class类型的对象

 

5 java.lang.Class<T>

有一下三个方式获取Class<T>,其中(1)(2)只能获取编译时类型,而(3)获取运行是类型:

(1)Class类的静态方法:Class.forName("完整的包名.类名")

(2)某类的class静态属性:User.class

(3)object.getClass()方法,所有实例都有,可以获取到该实例的运行时类型

 

只要拿到这个java.lang.Class clazz的对象,就能拿到此类的所有信息

(1)构造器对象

(2)方法对象

(3)属性对象

(4)接口对象

(5)注解对象

(6)完成包名.类名

(7)加载这个类的classLoader