类的加载机制和反射——一、类的加载、连接和初始化

类的加载、连接和初始化

1.JVM和类

(1)当调用java命令运行某个Java程序时,该命令会启动一个Java虚拟机进程,不管该Java程序有多么复杂,该程序启动了多少线程,他们都处于该Java虚拟机进程里。

(2)同一个JVM的所有线程、所有变量都处于同一个进程里,他们都使用该JVM进程的内存区。

  下面的ATast1和ATest2的输出结果分别是7和6,因为这两个不是位于同一个JVM中的。

public class A {
    //定义该类的类变量
    public static int a = 6;
}
public class ATest1 {
    public static void main(String args[]){
        //创建A的实例
        A a = new A();
        //让a实例的类变量a的值自增
        a.a++;
        System.out.println(a.a);
    }
}
public class ATest2 {
    public static void main(String[] args) {
        A b = new A();
        System.out.println(b.a);
    }
}

(3)JVM进程被终止的情况:

  ①程序运行到最后正常结束;

  ②程序运行到使用System.exit()或者Runtime.getRuntime().exit()代码处结束程序;

  ③程序执行中遇到未捕获的异常或错误而结束;

  ④程序所在平台强制结束了JVM进程。

2.类的加载

(1)当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化三个步骤来对该类进行初始化。JVM将会连续完成这三个步骤,所以有时也吧这三个步骤统称为类加载或类初始化;

(2)类加载指的是将类的class文件读入内存,并为之创建一个Class对象,当程序使用任何类时,系统都会为之创建一个Class对象;

(3)类的加载由类加载器完成,类加载器通常由JVM提供,同时,开发人员也可以通过继承ClassLoader类来创建自己的类加载器;

(4)通过使用不同的类加载器可以从不同来源加载类的二进制数据,类的二进制数据通常有如下几个来源:

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

  2)从jar包加载class文件;

  3)通过网络加载class文件;

  4)把一个java源文件动态编译,并执行加载。

(5)类加载器无须等到首次使用类时才加载该类,Java虚拟机允许系统预先加载某些类。

3.类的连接

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

(2)类连接的三个阶段:

  1)验证:验证被加载的类是否有正确的内部结构,并和其他类协调一致;

  2)准备:类的准备阶段负责为类的类变量分配内存,并设置默认初始值;

  3)解析:将类的二进制数据中的符号引用替换成直接引用。

4.类的初始化

(1)类初始化阶段,虚拟机负责对类进行初始化,主要是对类变量进行初始化。

(2)对类变量指定初始值的两种方式:

  1)声明类变量时指定初始值;

  2)使用静态代码块为类变量指定初始值。

public class Test {
    //声明变量a时指定初始值;
    static int a =5;
    static int b;
    //没有指定初始值,也没有用静态代码块指定初始值,其默认为0
    static int c;
    //静态代码块中为b设置初始值
    {
        b = 6;
    }
}    

(3)声明变量时指定初始值,静态初始化块都被当成类的初始化语句,JVM会按这些语句在程序中的排列顺序依次执行。

public class Test {
    static{
        //使用静态初始化块为变量b指定初始值
        b = 6;
        System.out.println("==============");
    }
    //声明a时指定初始值
    static int a = 5;
    static int b = 9;
    static int c;
    public static void main(String args[]){
        System.out.println(Test.b);
    }
}

(4)JVM初始化一个类的步骤:

  1)若该类未被加载和连接,则先加载、连接该类;

  2)若该类的直接父类未被初始化,则先初始化该类的直接父类;

  3)若类中有初始化语句,则依次执行这些初始化语句。

5.类初始化的时机

(1)当Java程序首次通过下面六种方式来使用某个类或者接口时,系统会初始化该类或接口:

  1)创建类的实例(包括使用new关键字、通过反射创建、通过反序列化创建);

  2)调用某个类的静态方法;

  3)访问某个类的类变量,或为该类变量赋值;

  4)初始化某个类的子类;

  5)使用反射强制创建某个类或接口对应的Class对象;

  6)适应java.exe命令来运行某个主类;

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

(3)当使用ClassLoader类的loadClass()方法来加载某个类时,该方法只是加载该类,并不会执行该类的初始化。使用Class的forName()静态方法才会导致强制初始化该类。

class Tester{
    static{
        System.out.println("Tester类的静态初始化块。。。。。。");
    }
}
public class ClassLoaderTest {
    public static void main(String[] args) throws ClassNotFoundException{
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        //下面语句仅仅是加载Tester类
        cl.loadClass("Test4.Tester");
        System.out.println("系统加载Tester类");
        //这里才会初始化Tester类
        Class.forName("Test4.Tester");
    }
}
时间: 2024-10-02 20:17:12

类的加载机制和反射——一、类的加载、连接和初始化的相关文章

java8--类加载机制与反射(java疯狂讲义3复习笔记)

本章重点介绍java.lang.reflect包下的接口和类 当程序使用某个类时,如果该类还没有被加载到内存中,那么系统会通过加载,连接,初始化三个步骤来对该类进行初始化. 类的加载时指将类的class文件读入内存,并为之创建一个java.lang.class对象,也就是说,当程序中使用任何类时,系统都会为之建立一个java.lang.Class对象.(几乎所有的类都是java.lang.Class的实例); 所以JVM最先初始化的总是java.long.Object类. 在java中,一个类用

类的加载机制和反射——五、使用反射生成JDK动态代理

使用反射生成JDK动态代理 1.使用Proxy和InvocationHandler创建动态代理 (1)Proxy提供了用于创建动态代理类和动态代理对象的静态方法,他也是所有动态代理类的父类. (2)如果在程序中为一个或多个接口动态的生成实现类,就可以使用Proxy来创建动态代理类,如果需要为一个或多个接口动态的创建实例,也可以使用Proxy来创建动态代理实例. (3)Proxy提供了两个方法来创建动态代理类和动态实例: 1)static Class<?> getProxyClass(Class

异常处理、常用类、Java集合框架、反射

异常处理: 1.  异常:程序在执行过程中所产生的问题. 异常的三种类:①检查异常:又叫checdked异常或者受检异常.通常是用户错误或者不能被程序员所预见的问题.检查异常需要被解决之后才能通过编译. ②运行时异常:程序在运行过程中可能发生的.可以被程序员所避免的异常类型. ③错误:事实上错误不是异常,但却是用户和程序员无法控制的问题. 2.  异常的控制流程: 异常是被一个方法抛出的对象. (1) 处理异常的三个方法:①捕获这个异常,不让它沿着调用栈继续向下抛. ②捕获这个异常,并继续向下抛

C#通过反射调用类及方法

反射有个典型的应用,就是菜单的动态加载,原理就是通过反射调用某个窗体(类).下面演示一下通过反射调用类及方法: 1.新建一个类,命名为:ReflectionHelper,代码如下: #region 创建对象实例 /// <summary> /// 创建对象实例 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="assemblyN

jvm系列(一):java类的加载机制

java类的加载机制 原文:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不需要等到某个

Java温故而知新(10)类的加载机制

类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行. 研究类加载机制的第二个目的是让程序能动态的控制类加载,比如热部署等,提高程序的灵活性和适应性. 1.类加载机制 我们来了解一下虚拟机如何加载Class文件. 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被直接使用的java类型,这就是虚拟机的类加载机制. 类的生命周期包括加载(Loading).验证(Verification).准

java类的加载机制

文章来源: 转载自纯洁的微笑 原文链接:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不

java 27 - 1 反射之 类的加载器

说到反射,首先说类的加载器. 类的加载: 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 加载: 就是指将class文件读入内存,并为之创建一个Class对象. 任何类被使用时系统都会建立一个Class对象. 连接: 验证 是否有正确的内部结构,并和其他类协调一致 准备 负责为类的静态成员分配内存,并设置默认初始化值 解析 将类的二进制数据中的符号引用替换为直接引用 初始化: 就是我们以前讲过的初始化步骤 类初始化时机: 创建类的实

类的加载机制

ClassLoader Java程序并不是一个原生的可执行文件,而是由许多独立的类文件组成,每一个文件对应一个Java类.此外,这些类文件并非立即全部装入内存的,而是根据程序需要装入内存.ClassLoader专门负责类文件装入到内存. 数组类的 Class 对象不是由类加载器创建的,而是由 Java 运行时根据需要自动创建.数组类的类加载器由 Class.getClassLoader() 返回,该加载器与其元素类型的类加载器是相同的:如果该元素类型是基本类型,则该数组类没有类加载器. 从上图我