`
come_for_dream
  • 浏览: 120360 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

再次深入理解类加载机制(一)

    博客分类:
  • java
阅读更多

在刚刚接触Java的时候就对类的加载体系做过一个小小的总结,但是现在感觉很有必要再次总结一下。

 

一、类的加载方法

1、ClassLoader的的基本概念:

       与c与c++编写的程序不同,Java程序并不是可执行文件,而是有许多的类文件组成,每个文件对应一个Java类。而且这些类并不是全部装进内存,而是根据程序运行的需要逐步装载。ClassLoader是JVM的实现的一部分。

 

2、ClassLoader的加载流程

       当运行第一个程序的时候JVM启动,运行bootstrap classloader,该加载器负责加载核心Java API,然后调用ExtClassLoader加载扩展API,最后AppClassLoader加载CLASSPATH目录下面定义的Class。

 

 

首先我们应该要知道ClassLoader除了将Class加载到JVM中之外,还有一个重要的作用就是审查每个类应该由谁进行加载,这是一种父类优先的机制。

除了这两个作用还有就是将Class字节码重新解析成JVM统一要求的格式。

 

下面是ClassLoader类的loadClass方法:

 

 
    protected synchronized Class<?> loadClass(String name, boolean resolve)
	throws ClassNotFoundException
    {
	// First, check if the class has already been loaded
	Class c = findLoadedClass(name);
        //该类还没有被加载,那么则
	if (c == null) {
	    try {
                //如其父类不为空,那么则使用其父类进行加载(父类委托机制)
		if (parent != null) {
		    c = parent.loadClass(name, false);
		} 
                //如果其父类为空则使用BootstrapClass进行加载
                else {
		    c = findBootstrapClass0(name);
		}
	    } catch (ClassNotFoundException e) {
	        // If still not found, then invoke findClass in order
	        // to find the class.
                //如果此类的父类加载器无法加载该类,那么有此类加载器的findClass进行类字节码                  的加载
	        c = findClass(name);
	    }
	}
        //是否需要解析类,如果resolve=true时,则保证已经装载,而且已经连接了。resolve=falses时,则仅仅是去装载这个类,不关心是否连接了,所以此时可能被连接了,也可能没有被连接
	if (resolve) {
	    resolveClass(c);
	}
	return c;
    }

 上面的代码可以看出,一个类的加载过程使用了一种父类委托的模式,这种模式的好处主要有两种:

1、可以避免重复加载,当父类已经加载了该类的时候就没有必要子ClassLoader再加载一次。

2、考虑到安全因素,如果不使用这种委托模式,那么可以随时使用自定义的String来动态代替Java核心API中定义的类型,这样做会存在非常大的安全隐患,而父类委托模式就可以避免这种情况,因为服加载器已经在启动时被加载,所以,用户自定义类是无法加载一个自定义的String的。

 

 

 除了上面的loadClass方法外方法还有几个比较重要的 

 

protected final Class<?> defineClass
protected Class<?> findClass(String name)
protected final void resolveClass(Class<?> c) 

 

 

上面的loadClass方法的作用只是启动类的加载,指定类应该由谁进行加载。而具体的怎么加载需要用到

defineClass方法:其能够将byte字节流解析成JVM能够识别的Class对象。

然后还有一个findClass方法:

findClass:负责取得需要加载的类的字节码,然后可以调用definedClass方法生成类的Class对象。

有了这样两个方法我们不仅仅可以通过class文件实例化对象,还可以通过网络接受字节码实例化对象。

一般我们配合使用defineClass和findClass 方法,直接覆盖ClassLoader父类的findClass方法来实现类的加载规则,findClass取得需要加载的类的字节码,defineClass根据字节码创建类对象

 

 

 破坏双亲委派模型

  

双亲委派模型第一次被破坏:

    双亲委派模型在jdk1.2的时候才被引入,提供了findClass方法供用户进行重写以指定自己的类加载规则,但是在jdk1.2之前用户继承ClassLoader的目的就是为了重写loadClass方法,但是双亲委派的具体逻辑就实现在这个方法之中,所以在JDK1.2之后就不提倡用户覆盖loadClass方法,而应当把自己得把类加载逻辑卸载findClass方法中,如果父类加载其加载失败会调用自己的findClass进行类的加载,这样就可以保证心写出来的类加载器符合双亲委派模型。

 

双亲委派模型第二次被破坏:

 双亲委派模型的第二次破坏是由这个模型本身造成的,这个模型中是越基础的类越由上层的加载器加载,之所以基础是因为他们总是被作为用户调用的API但是事无绝对,如果基础类又要调用用户的代码怎么办???

    一个典型的例子就是JNDI,他的代码由启动类进行加载,但是JNDI的目的是对资源进行集中管理和查找,他需要调下用调用独立厂商实现并部署在应用程序ClassPath

下的JNDI接口提供者,这个问题的解决是在程序中引入了不太优雅的设计:线程上下文类加载器,JNDI可以使用这个线程上下文类加载器去加载所需要的SPI,也就是父类加载器请求自类加载器去完成类加载的动作,这已经违反了双亲委派模型的一般性原则,在Java中所有涉及SPI的如jNDI  ,   JDBC  , JCE ,  JAXB和JBI都使用这种模型来进行类的加载。

 

 

 双亲委派模型第三次被破坏:

这里主要是说OSGI为了实现Java模块化热部署而自定义的类加载机制的实现。它把双亲委派模型的树状结构改编成了自己的更加复杂的网状结构,具体的这里已经暂时超过了小菜的讨论范围

 

 

 

 

 

0
0
分享到:
评论

相关推荐

    类加载机制ClassLoader

    类加载机制支持双亲委派模型,即一个类通常由父类加载器先尝试加载,如果父类加载器无法加载,则传递给子类加载器。这样能确保核心类库(如rt.jar)始终由系统类加载器加载,保证安全。 博客链接中提到的是ITEE博客...

    JAVA类加载器分析--热部署的缺陷(有代码示例,及分析)

    总之,“JAVA类加载器分析--热部署的缺陷”这篇博文深入探讨了Java中的类加载机制,特别是热部署过程中可能出现的问题,以及如何通过理解这些机制来优化和解决问题。了解这些知识对于开发和维护大型Java应用至关重要...

    Java类加载器学习总结.pdf

    了解Java类加载器的工作原理,可以帮助开发者更加深入地掌握Java程序的执行机制,同时也对排查类加载相关的故障(如类找不到、类重复加载等问题)提供帮助。在实际开发中,合理使用自定义类加载器,可以实现热部署、...

    JAVA 基础培训,JDK和JVM,核心类的介绍和使用

    - **Cache机制**:类加载器使用缓存机制,即首次加载类后,会将类的信息保存在缓存中,再次请求相同类时,直接从缓存中获取,提高加载效率。 #### 二、JDK的classloader机制实战 **2.1 动态加载与更新** 在某些...

    Android-Gif-Load-ReTry-Refresh只需要一张Gif图一行代码支持初次加载重试加载加载后再次刷新

    "Android-Gif-Load-ReTry-Refresh"是一个专为解决这个问题而设计的库,它允许开发者仅用一张Gif图和一行代码就能实现初次加载、重试加载以及加载后的再次刷新功能。这个库大大简化了在Android应用中集成动态GIF图片...

    tomcat 源码分析系列文档

    10. "tomcat类加载机制.pdf":再次聚焦于Tomcat的类加载机制,可能深入到更多细节和技巧,如类加载的优化和调试。 综上所述,这个文档集合为学习和研究Tomcat提供了全面的视角,从基础的HTTP协议到复杂的源码分析,...

    Android做的一个滑动到底部自动加载

    在Android应用开发中,"滑动到底部自动加载"是一种常见的功能,特别是在...通过研究这个代码,你可以更深入地理解如何在Android应用中实现滑动到底部自动加载的功能,并学习到如何结合软缓存和懒加载策略来优化性能。

    深入理解计算机系统真题

    ### 深入理解计算机系统真题解析 #### 一、IEEE浮点数标准 - **选项分析**: - **A**:不正确。IEEE浮点数的标准中,`exponent bits` 和 `fraction bits` 的分配确实会影响能够表示的数值范围。例如,增加指数...

    Java ClassLoader Tutorial.zip

    3. 双亲委派模型:Java的类加载机制遵循双亲委派模型,即当一个类加载器接收到加载类的请求时,它首先会委托父类加载器去尝试加载,只有当父类加载器无法加载时,当前类加载器才会尝试自己加载。 二、ClassLoader ...

    itemRenderer 提前加载问题

    标签"源码"表明讨论可能深入到源代码级别,可能包含对Flex或ActionScript框架的源代码分析,以理解其内部加载机制。"工具"可能指的是用于调试或分析性能的工具,例如Flex Builder、Flash Builder或各种第三方性能...

    Android 图片缓存机制的深入理解

    Android 图片缓存机制的深入理解 Android加载一张图片到用户界面是很简单的,但是当一次加载多张图片时,情况就变得复杂起来。很多情况下(像ListView、GridView或ViewPager等组件),屏幕上已显示的图片和即将滑动...

    Android异步加载例子

    在"Android异步加载图片"这个标签下,我们还可以探讨使用Loader API,这是Android提供的另一种异步数据加载机制,适用于更复杂的数据加载场景。Loader能够监控数据源的变化,并在数据更新时自动重载数据。 文件...

    深入理解linux内核(3)-part7

    在深入理解Linux内核系列的第三部分,我们聚焦于第7章——进程调度。这一章是内核核心功能的关键组成部分,因为它关乎系统如何高效、公平地分配CPU资源给多个并发运行的任务。进程调度是操作系统中的一项重要机制,...

    Java分布式应用学习笔记02再谈JVM

    从内存管理、线程模型、类加载机制到性能调优和集群部署,每一个环节都对应用的整体表现有着至关重要的作用。掌握这些核心知识,不仅能够提升个人的技术能力,还能为团队和项目带来显著的效益。在不断发展的IT领域中...

    安卓图片加载工具

    在Android开发中,图片加载是一项重要的任务,因为它不仅关乎到应用的性能,还直接影响用户体验。本文将深入探讨“安卓图片加载...通过深入理解和运用这些知识点,开发者可以更好地应对Android应用中的图片加载挑战。

    异步加载图片示例DEMO,防止图片错位

    在移动应用开发中,尤其是涉及到大量图片展示时,...通过这个DEMO,开发者可以深入理解异步加载图片的原理和实践,提高应用的用户体验。同时,这也是一个很好的学习资源,帮助开发者掌握Android开发中的性能优化技巧。

Global site tag (gtag.js) - Google Analytics