从java的动态性到类加载机制

 

我们知道,Java是一种动态语言。

那么怎样理解这个“动态”呢?

或者说一门语言具备了什么特性,才能称之为动态语言呢?

对于java,我是这样理解的。

我们都知道JVM(java虚拟机)执行的不是本地机器码指令,

而是执行一种称之为字节码的指令(存在于class文件中)。

这就要求虚拟机在真正执行字节码之前,先把相关的class文件加载到内存中。

虚拟机不是一次性加载所有需要的class文件,因为它在执行的时候根本不会知道以后会用到哪些class文件。

它是每用到一个类,就会在运行时“动态地”加载和这个类相关的class文件。

这就是java被称之为动态性语言的根本原因。

除了动态加载类之外,还会动态的初始化类,对类进行动态链接。

在JVM中负责对类进行加载的正是本文要介绍的类加载器(ClassLoader),所以,类加载器是JVM不可或缺的重要组件。

java中的类加载器及类加载器工作原理

 

java中(指的是javase)有三种类加载器。

每个类加载器在创建的时候已经指定他们对应的目录, 也就是说每个类加载器去哪里加载类是确定的,我认为在ClassLoader类中应该会有getTargetPath()之类的方法, 得到他们对应的路径,找了找jdk的文档,发现是没有的。

以下是这三种类加载器和他们对应的路径:

* AppClassLoader  --   加载classpath指定的路径中的类

* ExtClassLoader   --   加载jre/lib/ext目录下或者java.ext.dirs系统属性定义的目录下的类

* BootStrap           --   加载JRE/lib/rt.jar中的类

那么类加载器是如何工作的呢?

可以参看jdk中ClassLoader类的源码。这个类的实现使用了模板方法模式,首先是loadClass方法来加载类,loadClass方法又调用了findClass方法,该方法读取并返回类文件的数据,findClass方法返回后,loadClass方法继续调用defineClass方法,将返回的数据加工成虚拟机运行时可识别的类型信息。

所以,我们如果开发自己的类加载器,只需要继承jdk中的ClassLoader类,并覆盖findClass方法就可以了,剩下的而工作,父类会完成。

  1. class MyClassLoader extends ClassLoader {
  2. @Override
  3. public Class<?> loadClass(String name) throws ClassNotFoundException {
  4. String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
  5. InputStream in = getClass().getResourceAsStream(fileName);
  6. if (in == null) {
  7. return super.loadClass(name);
  8. }
  9. byte[] b = null;
  10. try {
  11. b = new byte[in.available()];
  12. in.read(b);
  13. in.close();
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. return defineClass(name, b, 0, b.length);
  18. }
  19. }

其他java平台有的根据自己的需求,实现了自己特定的类加载器,

例如javaee平台中的tomcat服务器,Android平台中的dalvik虚拟机也定义了自己的类加载器。

虚拟机加载类有两种方式,一种方式就是上面提到的ClassLoader.loadClass()方法,

另一种是使用反射API,Class.forName()方法,其实Class.forName()方法内部也是使用的ClassLoader。

指定参数ClassLoader的话就用指定的;否则,返回的是调用者的类加载器。

Class类中forName方法的实现如下:

  1. public static Class<?> forName(String name, boolean initialize,
  2. ClassLoader loader)
  3. throws ClassNotFoundException
  4. {
  5. if (loader == null) {
  6. SecurityManager sm = System.getSecurityManager();
  7. if (sm != null) {
  8. ClassLoader ccl = ClassLoader.getCallerClassLoader();
  9. if (ccl != null) {
  10. sm.checkPermission(
  11. SecurityConstants.GET_CLASSLOADER_PERMISSION);
  12. }
  13. }
  14. }
  15. return forName0(name, initialize, loader);
  16. }
  17. /** Called after security checks have been made. */
  18. private static native Class forName0(String name, boolean initialize,
  19. ClassLoader loader)
  20. throws ClassNotFoundException;

深入理解java:1.1. 类加载器的更多相关文章

  1. 【深入理解Java虚拟机 】类加载器的命名空间以及类的卸载

    类加载器的命名空间 每个类加载器又有一个命名空间,由其以及其父加载器组成 类加载器的命名空间的作用和影响 每个类加载器又有一个命名空间,由其以及其父加载器组成 在每个类加载器自己的命名空间中不能出现相 ...

  2. Java中的类加载器

    转载:http://blog.csdn.net/zhangjg_blog/article/details/16102131 从java的动态性到类加载机制   我们知道,Java是一种动态语言.那么怎 ...

  3. 【深入理解JVM】:类加载器与双亲委派模型

    类加载器 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段“加载”过程中,需要通过一个类的全限定名来获取定义此类的二进制字 ...

  4. Java中的类加载器--Class loader

    学习一下Java中的类加载器,这个是比较底层的东西,好好学习.理解一下.  一.类加载器的介绍 1.类加载器:就是加载类的工具,在java程序中用到一个类,java虚拟机首先要把这个类的字节码加载到内 ...

  5. Java基础之类加载器

    Java类加载器是用户程序和JVM虚拟机之间的桥梁,在Java程序中起了至关重要的作用,理解它有利于我们写出更优雅的程序.本文首先介绍了Java虚拟机加载程序的过程,简述了Java类加载器的加载方式( ...

  6. 黑马程序员——【Java高新技术】——类加载器

    ---------- android培训.java培训.期待与您交流! ---------- 一.概述 (一)类加载器(class loader) 用来动态加载Java类的工具,它本身也是Java类. ...

  7. 深入理解java虚拟机【类加载机制】

    Java虚拟机类加载过程是把Class类文件加载到内存,并对Class文件中的数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型的过程. 在加载阶段,java虚拟机需要完成以下 ...

  8. Java中的类加载器以及Tomcat的类加载机制

    在加载阶段,虚拟机需要完成以下三件事情: 1.通过一个类的全限定名来获取其定义的二进制字节流. 2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构. 3.在Java堆中生成一个代表这个类 ...

  9. 黑马程序员:Java基础总结----类加载器

    黑马程序员:Java基础总结 类加载器   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个 ...

  10. Java基础加强-类加载器

    /*类加载器*/ 把.class文件从硬盘上加载出来,将类的字节码(二进制)加载到内存中 /*类加载器及其委托机制*/ Java虚拟机中可以安装多个类加载器(可以自己编写),系统默认三个主要类加载器, ...

随机推荐

  1. inoutfy与rsync进行实时同步

    更新阿里epel源 安装镜像源 curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo --- 扩展 ...

  2. JAVA语言程序设计-笔记摘录

    JAVA 程序语言设计(基础篇) 笔记摘录 为避免输入错误, 不要在nextByte().nextShort().nextInt()等等后面使用nextLine() nextXXXXX()都称为令牌读 ...

  3. DevExpress v19.1新版亮点——WinForms篇(四)

    行业领先的.NET界面控件DevExpress v19.1终于正式发布,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WinForms v19.1中新增的一些控 ...

  4. GO语言学习笔记3-int与byte类型转换

    1.主机字节序 主机字节序模式有两种,大端数据模式和小端数据模式.在网络编程中应注意这两者的区别,以保证数据处理的正确性.例如,网络的数据是以大端数据模式进行交互,而我们的主机大多数以小端模式处理,如 ...

  5. 【转载】mysqld_safe Directory ‘/var/run/mysqld’ for UNIX socket file don’t exists.

    This is about resetting the MySQL 5.7 root password in Ubuntu 16.04 LTS You probably tried something ...

  6. Android 通过应用设置系统日期和时间的方法

    Android 通过应用设置系统日期和时间的方法 android 2.3 android 4.0 测试可行,不过需要ROOT权限. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

  7. ZooKeeper设置开机启动

    1 在init.d目录下新建脚本文件 进入到/etc/rc.d/init.d目录下,命令是: cd    /etc/rc.d/init.d 新建一个名为zookeeper的文件,命令是: touch ...

  8. Windows Server 部署WEB API时内部错误

    Windows Server 部署WEB API时,发生HTTP 错误 500.21 - Internal Server Error,如图所示: 错误原因:IIS注册Framework4.0 解决方法 ...

  9. sqli-labs(23)

    基于get的过滤了的注入 0X1测试闭合 /?id=' http://127.0.0.1/sql1/Less-23/?id=1%27%27 0X02 然后就是组合拳的操作了 未报错 那么应该是’闭合 ...

  10. bootstraptable表格columns 隐藏方法

    隐藏:  visible: false,   显示:visible: true, visible属性没有true或者false,是visible,invisible和gone.visible:可见的: ...