zoukankan      html  css  js  c++  java
  • Java反射、类加载、初始化

     Java反射、类加载、初始化

    一、 先了解一下基本知识:

    1.      字节码和机器码是什么,有什么联系

    二、反射、类加载器、初始化

    2.      反射:

    2.1,反射理解:

    2.2Class类常用方法:

    2.3获取某个类的class 实例四种方法:

    2.4反射优点、缺点:

    2.5,反射在实际开发中的使用场景:

     

    3,类加载ClassLoader:

    3.1,类加载器的一个主要方法:getResourceAsStream(String str): 获取类路径下的指定文件的输入流

    3.2 类加载器和inputStream 加载配置文件的区别:

    3.3 配置文件的路径问题:

    3.4  Class.getResource(String path) 与 Class.getClassLoader.getResource (String path) 区别:

    4,类的加载机制

    4.1 类的加载:

    4.2类加载的时机

    4.3 类加载器分类:

    4.4 类加载的双亲委派模型

    转载1:https://www.cnblogs.com/qiumingcheng/p/5400265.html  《机器码和字节码》

    转载2:https://www.cnblogs.com/yangyongjie/p/11002844.html  《Java类加载和初始化》

    转载3:https://blog.csdn.net/iechenyb/article/details/81871306 《JAVA类加载与初始化顺序》

    转载4:https://blog.csdn.net/qq_28505705/article/details/106462462 《Java基础----反射 (一) 反射机制、Class类、类的加载和类加载器ClassLoader、反射的使用》

    一、 先了解一下基本知识:

    1.      字节码和机器码是什么,有什么联系

    机器码:顾名思义,机器可以读懂的码;就是0、1啦;原生码(Native Code),是电脑的CPU可直接解读的数据

    字节码:字节码(Bytecode)是一种包含执行程序、由一序列 op 代码/数据对 组成的二进制文件字节码是一种中间码,它比机器码更抽象,需要直译器转译后才能成为机器码的中间代码。(ps:OP (操作码operation code))

    举例:java  bytecode; 首先通过java语言编译器编写代码,生成.java 文件,然后编译器实行javac 指令,生成.class 文件(字节码文件),然后jvm 跨平台,在直译器的翻译下生成机器码,让CPU 解读。(ps:编译器的作用:编译器里我们通过高级java 高级语言,编写代码,理由编译器自带的javac 命令,生成字节码.class 文件,然后再通过编译器的java 命令,运行代码,查看结果。)

    联系:字节码是一种中间状态(中间码)的二进制代码(文件)。需要直译器转译后才能成为机器码。

    二、反射、类加载器、初始化

    2.      反射:

    2.1,反射理解:照镜子

    对象通过反射可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个结构(class/interface/enum/annotation/primitive type/void/[])的有关信息。

    概念:Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Refle反射的API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

    在Object类中定义了public final Class getClass()方法,方法返回值的类型是一个Class类。
    Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象。

    2.2Class类常用方法:

    2.3获取某个类的class 实例四种方法:

    法1:  // 已知具体的类,调用运行时类的属性:.class;它主要应用于原始数据类型,并且仅在我们知道类的名称时才使用。要创建的Class对象的类名在编译时确定。    
    Class<?> clazz = String.class;
    法2: //已知某个类的实例,调用该实例的getClass()方法获取Class对象 String str = new String("string"); Class c3 = str.getClass(); 法3:调用Class的静态方法:forName(String classPath) Class<?> clazz = Class.forName(“某个类的类名(路径)”); 法4:方式四:使用类的加载器:ClassLoader ClassLoader classLoader = ReflectionTest.class.getClassLoader(); Class<?> clazz4 = classLoader.loadClass("reflection_mechanism.Person");

    2.4反射优点、缺点:

    优点:提高了程序的灵活性和扩展性,降低模块的耦合性;例如通过反射机制可以让程序创建和控制任何类的对象,无需提前硬编码目标类;反射是框架的灵魂,使用反射可以避免将代码写死在框架中。

    缺点:性能问题:反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。把本来应该在项目启动阶段做的事情,延迟到了项目运行阶段来做。这样就增加了项目运行阶段的系统开销。安全限制:使用反射技术要求程序必须在一个没有安全限制的环境中运行。因为有内部的暴露。

    2.5,反射在实际开发中的使用场景:

    ♢反射使用不好,对性能影响比较,一般项目中很少直接使用,主要用在底层框架中。使用反射机制,①模块开发,通过反射调用对应字节码;②动态代理模式;③spring框架、Hibernate框架等;

    反射是框架设计的灵魂。

    举例:

    • ① 用 IoC 来注入和组装 bean;
    • ②工厂模式:Factory类中用反射的话,添加了一个新的类之后,就不需要再修改工厂类Factory
    • ③数据库JDBC中通过Class.forName(Driver).来获得数据库连接驱动;
    • ④动态代理、面向切面、bean 对象中的方法替换与增强,也使用了反射;
    • ⑤定义的注解,也是通过反射查找

    ps:什么是IoC?--- “控制反转”, 获的对象的过程被反转了,依赖注入。 控制权的转移,应用程序本身不负责依赖对象的创建和维护,而是有外部容器的创建和维护。例如将对象的依赖交给配置文件来配置

     

    3,类加载ClassLoader:

    3.1,类加载器的一个主要方法:getResourceAsStream(String str): 获取类路径下的指定文件的输入流

    3.2 类加载器和inputStream 加载配置文件的区别:

    类加载器作用:

    加载“.classpath”的资源文件,例如xml、properities文件。注意:该方式只能读取类路径(.classpath)的配置文件

    InputStream 读取配置文件:

    注:该方式的优点在于可以读取任意路径下的配置文件

    3.3 配置文件的路径问题:

    类加载器作用:加载“.classpath”的资源文件,例如xml、properities文件

    注意:该方式只能读取类路径(.classpath)的配置文件

    ps:查看eclipse中的.classpath 文件:Window-》show View-》Navigator(Deprecated)

       配置文件的路径是个疑惑!!!,从使用相对路径时频繁报错!!!,其实Class.getClassLoader.getResource (String path) 默认是从.classpath根下获取。

          

    //PolymorphicFunction这一行的完整代码 pro.load(HeroFactories.class.getClassLoader().getResourceAsStream("PolymorphicFunction/Pro.properties"));

    3.4  Class.getResource(String path) 与 Class.getClassLoader.getResource (String path) 区别:

    Class.getResource(String path)

    ☆ path不以'/'开头时,默认是从此类所在的包下取资源;

    path'/'开头时,则是从项目的ClassPath根下获取资源

    class.getResource("/") == class.getClassLoader().getResource("")

    Class.getClassLoader.getResource (String path) 

    ♢默认是从ClassPath根下获取,path不能以’/'开头,根是src(bin),classPath文件到配置文件xml或者properties文件;

     path不能以'/'开头path是指类加载器的加载范围,在资源加载的过程中,使用的逐级向上委托的形式加载的,'/'表示Boot ClassLoader,类加载器中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null。

    4,类的加载机制

    4.1 类的加载:

       类的加载:指的是将类的.class字节码文件中的二进制数据读入到jvm内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构。

    4.2类加载的时机:

    类从被加载到虚拟机内存中开始,到卸载出内存为止,整个生命周期包括以下7个阶段:加载、验证、准备、解析、初始化、使用、卸载。

     其中验证、准备、解析3个部分统称为连接。 因此生命周期可以简记为:加载、连接(验、准、解)、初始化、使用、卸载(加连初使卸)

    4.3 类加载器分类:

    加载器主要有四种:

    ①   jvm启动类加载器bootstrap loader,用c++实现为jvm的一部分(仅指sun的hotspot),负责 JAVA_HOME/lib下面的类库中的类的加载,这个加载器,java程序无法引用到。

    ②   扩展类加载器Extension Loader,由sun.misc.Launcher$ExtClassLoader类实现,可在java中使用,负责JAVA_HOME/lib/ext 目录和java.ext.dir目录中类库的类的加载。

    ③   应用系统类加载器Application System Loader,由sun.misc.Louncher$AppClassLoader实现,负责加载用户类路径中类库中的类,如果没有使用自定义的加载器,这个就是默认的 加载器!

    ④   用户自定义加载器 自己定义从哪里加载类的二进制流。

    4.4 类加载的双亲委派模型:

    各个加载器都是先委托自己的父加载器加载类,若确实没加载到再自己来加载,于是java默认的类查找加载顺序是自顶向下的,树状结构。

     

  • 相关阅读:
    Java并发学习笔记
    OSI七层网络模型
    网络寻址过程
    ThinkPhp之Rce分析
    Java cc6
    Java cc1
    Yso中的URLDNS分析学习
    JWT攻防
    权限维持之创建本地账号(T1136.001)
    redis配置修改后不生效的原因
  • 原文地址:https://www.cnblogs.com/shan333/p/14749678.html
Copyright © 2011-2022 走看看