类加载机制与反射(一)

类的加载、连接和初始化

1.JVM和类

当调用java命令运行某个java程序时,该命令会启动一个java虚拟机进程,不管该Java程序有多么复杂,该程序启动了多少个线程,它们都处于该java虚拟机进程里。
当系统出现以下几种情况时,JVM进程将被终止:
(1)程序运行到最后正常结束
(2)使用 Systerm.exit()或者 Runtime.getRuntime().exit()
(3)执行过程中遇到未捕获的异常或者错误而结束
(4)程序所在平台强制结束JVM进程

例子:
A.java

package com.example;

public class A
{
    //类变量
    public static int a = 5;
    public static void main(String[] args)
    {
    }
}

AText.java


package com.example;

/**
 * Created by zhoujian on 2017/4/3.
 */

public class AText
{
    public static void main(String[] args)
    {
        A a = new A();
        a.a++;
        //运行结果:6
        System.out.println(a.a);
    }
}

BText.java

package com.example;

/**
 * Created by zhoujian on 2017/4/3.
 */

public class BText
{
    public static void main(String[] args)
    {
        A b = new A();
        //运行结果:5
        System.out.println(b.a);
    }
}

两次运行,处于不同的JVM中,两个JVM之间并不会共享数据

2.类的加载

当程序使用某个类时,如果该类该类还未被加载到内存中,则系统会通过加载、连接和初始化这三个步骤来对该类进行初始化。这三个步骤称为类加载或类初始化

类加载指的是将类的class文件读入内存,并为之创建一个java.lang.Class对象

类的加载由类加载器完成,类加载器通常由JVM提供

通过不同的类加载器,可以从不同来源加载类的二进制数据

  • 从本地系统加载class 文件
  • 从JAR包加载class文件
  • 通过网络加载class文件
  • 把一个java 文件动态编译,并执行加载

类加载器无需等到使用时才去加载该类,java 虚拟机规范允许系统预先加载某些类

3.类的连接

当类被加载之后,系统为之生成一个对应的Class 对象,接着将进入连接阶段,连接阶段负责把二进制数据合并到JRE中。类连接又分为三个阶段

  • 验证:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致
  • 准备:类准备阶段负责为类的类变量分配内存,并设置默认初始值
  • 解析:将类的二进制数据中的符号引用替换成直接引用

4.类的初始化

在类的初始化阶段,虚拟机负责对类进行初始化,主要是对类变量初始化。
在java类中对变量指定初始值有两种方式:

  • 声明类变量时指定初始值
  • 使用静态初始化块为类变量指定初始值

package com.example;

/**
 * Created by zhoujian on 2017/4/3.
 */

public class AText
{
    //声明变量 b时指定初始值
    static int b = 2;
    static
    {
        //使用静态初始化块为变量b指定初始值
        b = 5;

    }


    public static void main(String[] args)
    {

        A a = new A();
        a.a++;
        System.out.println(a.a);
        System.out.println(AText.b);
    }
}

5.类初始化的时机

当 Java 程序首次通过下面6种方式来使用某个类或者接口,系统就会初始化该类或者接口

  • 创建类的实例
  • 调用某个类的方法(静态方法)
  • 访问某个类或接口的类变量,或者为该类变量赋值
  • 使用反射的方式来强制创建某个类或者接口对应的 java.lang.Class 对象
  • 初始化某个类的子类。那么该子类所有父类都会被初始化
  • 直接使用java.exe 命令来运行某个主类

对于一个final 型的类变量,如果该类变量在编译的时就可以确定下来,那么这个类变量相当于“宏变量”。java 编译器会在编译时直接把这个类变量出现的地方替换成它的值,因此即使程序使用该静态类变量,也不会导致该类的初始化

package com.example;

public class MyTest
{

    static
    {
        //静态初始化块

    }

    //变量name可以在编译的时候确定下来,相当于一个常量
    static final String name = "zhoujian";
    
    public static void main(String[] args)
    {
        //不会初始化MyTest类
        System.out.println(MyTest.name);
    }

}

当使用ClassLoader 类的loadClass()方法来加载某个类时,该方法只是加载类,并不会执行该类的初始化。

使用Class的forName()静态方法才会导致强制初始化该类

类加载器

类加载器负责将.class 文件加载到内存中,并为之生成对应的java.lang.Class 对象

1. 类加载器简介

类加载器负责加载所有的类,系统为所有被载入内存中的类生成一个java.lang.Class 实例

当JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构

  • Bootstrap ClassLoader:根类加载器
  • Extension ClassLoader:扩展类加载器
  • System ClassLoader:系统类加载器

例子:获取根类加载器所加载的核心类库

package com.example;

import java.net.URL;

/**
 * Created by zhoujian on 2017/4/3.
 */

public class Text
{
    public static void main(String[] args)
    {
        //获取根类加载器所加载的全部URL数组
        URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
        for (int i = 0; i < urls.length; i++)
        {
            //输出根类加载器的全部url
            System.out.println(urls[i].toExternalForm());
        }
    }
}

Snip20170404_1.png

Extension ClassLoader:扩展类加载器,它负责加载JRE的扩展目录(%JAVA_HOME%jre/lib/ext或者由java.ext.dirs系统属性指定的目录)中JAR包的类

System ClassLoader:系统类加载器,可以通过ClassLoader的静态方法 getSystemClassLoader()来获取系统类加载器

2. 类加载机制

JVM的类加载机制主要要三种:

  • 全盘负责 :就是当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其它Class也将由该类加载器负责载入
  • 父类委托:先让父类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类
  • 缓存机制:所有加载过得Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存中获取,只要缓存中不存在该Class对象时,系统才会读取对应的二进制数据,并转换成Class对象,存入缓存中。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容