今天学习Spring,突然想重新复习一下Java类加载和类反射的。巩固一下底层原理。部分参考了李刚老师的《疯狂Java讲义》和陈雄华、林开雄的《Spring3.x企业应用开发实战》。

一、一个命令对应一个进程。

当我们启动一个Java程序,即启动一个main方法时,都将启动一个Java虚拟机进程,不管这个进程有多么复杂。而不同的JVM进程之间是不会相互影响的。这也就是为什么说,Java程序只有一个入口——main方法,让虚拟机调用。而两个mian方法,对应的是2个JVM进程,启动的是两个不同的类加载器,操作的实际上是不同的类。故而不会互相影响。

二、类加载。

当我们使用一个类,如果这个类还未加载到内存中,系统会通过加载、连接、初始化对类进行初始化。

1、类加载:指的是将类的class文件读入JVM,并为之创建一个Class对象。

2、类连接:指的是把类的二进制数据合并到JRE中,这又分为3个阶段:

a)、校验:检查载入Class文件数据的正确性。

b)、准备:给类的静态变量分配存储空间,并进行默认初始化。

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

3、初始化:对类的静态变量、静态初始化块进行初始化。

(注意:一个final类型的静态属性,如果在编译时已经得到了属性值,那么调用该属性时,不会导致该类初始化,因为这个相当于使用常量;

使用ClassLoader()方法,只是加载该类,并未初始化。)

三、类加载器。

类加载器就是负责将.class文件加载到内存中,并为之生成对应的java.lang.Class对象,它负责加载所有的类,而一旦一个类被加载入JVM中,就不会被再次载入了。

在Java中,一个类用其全限定类名(即包名+类名)作为标识。

而在JVM中,一个类用其全限定类名和其类加载器作为标识。

JVM运行时会产生3个ClassLoader,分别为:BootstrapClassLoader(根类加载器)、ExtClassLoader(扩展类加载器)和AppClassLoader(系统类加载器)。UML结构如下:

其中,BootstrapClassLoader负责加载JRE的核心类库,它不是ClassLoader的子类,使用C++编写,因此我们在Java中看不到它,通过其子类的getParent()方法获取时,将返回null。BootstrapClassLoader负责装载JRE目标下的rt.jar、charsets.jar等Java核心类库。

如图可知,ExtClassLoader和AppClassLoader为ClassLoader的子类。在API中看不到它们,他们位于rt.jar文件中。全限定类名分别为:

sun.misc.Launcher$ExtClassLoader 和 sun.misc.Launcher$AppClassLoader.

其中,ExtClassLoader负责装载JRE扩展目录ext中JAR包,而AppClassLoader负责装载Classpath路径下的类包。

测试如下:

package com.stopTalking.crazy;

public class TestClassLoader {

public static void main(String[] args) {
        //获取当前线程的类装载器
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        //获取System类的类装载器
        ClassLoader loader1 = System.class.getClassLoader();
        //获取本类TestClassLoader的类装载器loader2
        ClassLoader loader2 = TestClassLoader.class.getClassLoader();
        //获取loader2的父类
        ClassLoader loader3 = loader2.getParent();
        //获取loader2的父类的父类
        ClassLoader loader4 = loader3.getParent();
        System.out.println(loader);
        System.out.println(loader1);
        System.out.println(loader2);
        System.out.println(loader3);
        System.out.println(loader4);
    }
}

控制台输出:

//当前线程类获取的类加载器是AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
//System类为根装载器加载,java中访问不到,所以为null
null
//本类的类加载器当然也是AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
sun.misc.Launcher$ExtClassLoader@1c78e57
null

四、类加载机制。

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

1、全盘负责:当一个类加载器负责加载某个Class的时候,该Class所依赖的和引用的其他Class也将由该类加载器负责载入。

2、父类委托:先委托父加载器试图加载该类,只有在父加载器无法加载该类时才从自己的类路径中查找并装载该类。

3、缓存机制:缓存机制保证所有被家加载过的类都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存中搜寻。缓存中搜寻不到,才会重新读取该类对应的二进制数据,并创建对应的Class对象。

(注意:类加载器之间的父子关系,并不是类继承上的父子关系,而是类加载器实例之间的关系)

五、反射

以下是反射简单用法。

1、ClassLoader对象。

可以通过2种方式获得当前ClassLoader对象,一种是通过当前线程:

ClassLoader loader = Thread.currentThread().getContextClassLoader();

若已经有了Class对象,那么可以通过Class对象的getClassLoader()方法:

ClassLoader loader2 = Xxx.class.getClassLoader();

2、Class对象。

获得Class对象有3种方式:

a)、Class类的forName方法,传入全限定类名。需要抛出异常ClassNotFoundException

b)、调用该类的class属性。

c)、调用某对象的getClass()方法。

3、通过Class对象创建对象:

例如有一个Apple类。Class clazz = Class.forName(“com.stopTalking.crazy.Apple”);

该Apple类有一个默认构造器、一个String类型参数的构造器、一个String类型、int类型的构造器。

获得Apple对象有2种方式:

a)、用Apple类默认构造器:Object o1 = clazz.newInstance();

b)、用一个String类型参数的构造器:Object 02 = clazz.getConstructor(String.class).newInstance(“apple”);

c)、用一个String类型、int类型的构造器:Object 02 = clazz.getConstructor(String.class,int.class).newInstance(“apple”,”3”);

4、调用方法:

Method m = clazz.getMethod(方法名,参数类型);//根据方法名和参数类型创建Method对象。

m.invokej(对象,属性值);//根据对象和方法参数调用方法。

若需调用private方法,先调用Method对象的setAccessible(true);

5、访问属性:

Field f = clazz.getDeclaredField(属性名);//根据属性名获取Field对象

f.get(对象);//根据对象得到属性值。

6、操作数组:

Object arr = Array.newInstance(String.class,10);//创建一个简单的String数组。

Array.set(arr,5,”abc”);//给该数组下标为5的元素赋值

Object name = Array.get(arr,5);//获取该元素

Java类加载和类反射回顾的更多相关文章

  1. Java中的类反射

    一.反射的概念 : 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...

  2. 【转】两道面试题,带你解析Java类加载机制(类初始化方法 和 对象初始化方法)

    本文转自 https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html 关键语句 我们只知道有一个构造方法,但实际上Ja ...

  3. java -类加载器与反射

    类加载器 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. l  加载 就是指将class文件读入内存,并为之创建一个Class ...

  4. java类加载及类初始化

    1.前言 java是跨平台语言,主要是因为它的java虚拟机的存在,java有事编译语言,所以需要将编写的java文件编译成jvm可运用的class字节码文件.在java中一切皆对象.对于Java虚拟 ...

  5. java 类加载机制和反射机制

    一.类的加载机制 jvm把class文件加载到内存,并对数据进行校验.解析和初始化,最终形成jvm可以直接使用的java类型的过程.(1)加载         将class文件字节码内容加载到内存中, ...

  6. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  7. 一文读懂Java类加载机制

    Java 类加载机制 Java 类加载机制详解. @pdai Java 类加载机制 类的生命周期 类的加载:查找并加载类的二进制数据 连接 验证:确保被加载的类的正确性 准备:为类的静态变量分配内存, ...

  8. java学习:用反射构造bean

    先贴一些反射的基本知识:-------------------------------------------------------------------- 一.什么是反射:反射的概念是由Smit ...

  9. ClassLoader类加载器 & Java类加载机制 & 破坏双亲委托机制

    ClassLoader类加载器 Java 中的类加载器大致可以分成两类: 一类是系统提供的: 引导类加载器(Bootstrap classloader):它用来加载 Java 的核心库(如rt.jar ...

随机推荐

  1. 什么是XMLA-- XML for Analysis

    在我刚开始接触OLAP时,同事就告诉我 XMLA会让他使用更方便. 什么是XMLA? Providers 供应商 ActivePivot Hyperion Essbase IBM Infosphere ...

  2. 【转】简析 .NET Core 构成体系

    前文介绍了.NET Core 在整个.NET 平台所处的地位,以及与.NET Framework的关系(原文链接),本文将详细介绍.NET Core 框架的构成和各模块主要功能,以及如何实现跨平台. ...

  3. Bootstrap弹出框(modal)垂直居中

    最近在做一个eit项目,由于此项目里面一些框架要遵循nttdata的一些规则,故用到了Bootstrap这个东东,第一次碰到这个东东,有很大抵触,觉得不好,但用起来我觉得和别的弹出框真没什么两样.废话 ...

  4. ORACLE数据库的限制

    ORACLE数据库最多可以拥有多少个表空间(Tablespace)?数据库最多拥有多少个数据文件(Database files).数据库的数据文件最大可以多大?遇到这些问题只能查询官方文档,人的记忆能 ...

  5. [20140928]创建连接到MySQL的连接服务器

    首先要安装 mysql odbc 然后 odbc下创建DSN,并且要在系统DSN下. 最后执行 exec sp_addlinkedserver  @server= 'XY',        --这是链 ...

  6. FP并行算法的几个相关方向

    1 集群系统中的 FP-tree 并行算法(many for one一个任务 还是 云计算one for many多个任务?) 计算机集群系统利用网络把一组具有高性能的工作站或者 PC 机按一定的结构 ...

  7. Centos修改DNS重启或者重启network服务后丢失问题处理

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 阅读目录 介绍 起因 处理 GitHub 本文版 ...

  8. 一个update的小故事

    偶尔测试了一段小代码,写个循环 if object_id('tempdb..#TB') is not null drop table #TB go create table #TB ( ID int ...

  9. Activiti之 Exclusive Gateway

    一.Exclusive Gateway Exclusive Gateway(也称为XOR网关或更多技术基于数据的排他网关)经常用做决定流程的流转方向.当流程到达该网关的时候,所有的流出序列流到按照已定 ...

  10. 新手开发android容易出现的错误(不断更新中...)

    才开始开发android app,因为以前一直是java开发,学习也比较容易. 记录下自己开发过程中出现的一些小问题: 静态变量 在开发中,因为习惯性的问题,经常将一些常用数据(如用户信息等)进行st ...