`
supben
  • 浏览: 330159 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

classloader浅谈

    博客分类:
  • JVM
 
阅读更多
1.classloader的作用,主要作用加载.class文件,次要作用:加载其他格式的文件。

2. classpath:
classpath 决定了一个class loader的职能范围。
Bootstrap ClassLoader、Extension ClassLoader、System ClassLoader的区别就是其classpath不同。


3.URLClassLoader
  url不是classpath结构体系中的一个层级。他是实现一个classloader的方法。
  public URLClassLoader(URL[] urls, ClassLoader parent) ;

4 class的加载链。从A的main方法进入程序之后,A引用到的类B,由A的classLoader尝试加载。

5 双亲委派模式
  双亲委派模式不是一种语言规范,仅仅是一种实现细节。自己重写classloader的时候,完全可以打破这种模式(比如tomcat的 WebappClassLoader)

6.标准实现里,加载配置文件也是双亲委派模式。getResources相关的所有方法,最终调用的都是getResource方法。我们常用的getClassAsStream只能读取自己classpath下的配置文件。如果在父类的classpath下存在同名文件,则这个配置文件永远无法被读取。

7. 加载class的相关方法最终调用的都是loadClass方法。 加载class其实也是加载一个资源,只不过发现后缀是.class,就如何如何,重要的方法包括defineClass,resolveClass 。

8. loader class defineClass,resolveClass 主要干下面的工作:
       装载:查找和导入类或接口的字节码;
       链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;
         校验:检查导入类或接口的二进制数据的正确性;
         准备:给类的静态变量分配并初始化存储空间;
         解析:将符号引用转成直接引用;

9.A.class.getClassLoader();
  和Thread.currentThread().getContextClassLoader()是有很大的区别的。正如上文所说前者得到的classloader是明确的,就是加载A的那个loader。后者是不明确的,所有不建议使用后者的方式,实际上,getContextClassLoader()得到的结果仅仅依赖于setgetContextClassLoader()。你甚至是可以把当前线程上下文的classloader设置成Bootstrap classLoader。

10.ClassLoader.getCallerClassLoader()。 这个方法很强,就是仅仅是知道类名的时候,返   回A.class.getClassLoader()一样的效果。他是怎么做到的?

11.class.forName和 loadClass的区别。class.forName在load class之后,执行了初始化的工作,即static变量和static块的工作。 而loadclass没有。 如果你仅仅是执行一个类的static块,而不想干别的。那么可以用class.forName, 比如jdbc驱动的注册。

12.newInstance和new的区别, newInstance只能构造无参的对象。 都是loader之后,初始化,然后实例化的过程。

13,一个classloade进来后拥有唯一表示ClassLoader#类的全包名。classLoader会记录真正装载自己的那个loader。事实上loadeClass方法第一步都会有个从cache里get的过程。
ClassLoaderName#类的全包名是天然的键值。再回头看问题10,根据类名得到加载他的classLoader的具体型号,是可以实现的。

14 web容器的classloader组成,Bootstrap ClassLoader、Extension ClassLoader肯定是少不了。 app Classloader树里重要的有loader 有Common(负责加载serlet-api等) Shared(可以把所有项目公用的放在里边) webapp1  webapp2 ..(自己独特的)

15 tomcat的类加载 打破了类的双亲委派模式。先找自己。
比如在工程目录的web-inf/lib 目录下放一个 servlet-api 会发生什么?访问会报错。
因为从容器--项目业务方法--容器这个过程就是通过servlet-api里边的request和response  link上关系的。
现在CommonClassLoader#javax.servlet.http.HttpServletRequest 和 WebappClassLoader#javax.servlet.http.HttpServletRequest会被jvm认为是两个不同的类。
可以想象,上文讲的class.forName 会有点问题,因为#后面的类名查class loader的型号,可能查出多个来。class只有在用到的时候才会去load,绝不是上来就一股脑load。然后放在缓存里。


16 其他的web容器比如jetty是标准实现,比如在工程目录里放一个 servlet-api会如何? 不会有任何问题,子类的classLoader loader的时候,会调用Common ClassLoader的loader方法,然后发现CommonClassLoader#javax.servlet.http.HttpServletRequest已经存在。就直接返回了,也就是说工程目录下的servelt-api会被无视掉。


17 如果一个classPath里下有2个一样的jar? 先入为主的原则,所以版本如果有差异就会出问题。依赖于高版本需要的某个方法,在低版本里没有。


18 reload。 第一步:classloader的classpath需要更新。实际上urlClassLoader就有动态添加classPath的方法addURL。第二步,把中间过程干掉,比如缓存,load class的过程必须要重新来,因为.class文件可能会被改。

19. 一般web 服务都是大并发。直接kill 进程再start的方式并不友好。所以都要提供平滑重载机制reload。 掌握了class loader的机制,写一个reload的过程并不难。 像web容器的热重启机制,就是起一个单独的线程,去监控classPath下所有改动需重启的文件比如.class文件,配置文件或者jar文件,比对他们的文件修改时间。一旦有改动,马上reload。 所以算是比较耗费性能的一件事。

20. 其实比较粗暴一点的reload方式,是干掉classLoader重写创建一个。这样带来的缺点是由于上一个classLoader被干掉,通过他load进来的class(对他有引用和被引用的关系)的引用链就断了,产生一堆垃圾对象。 不过作者观察过,所有被前一个废弃的classLoaderload进来的class会被垃圾收集机制正常的回收。



分享到:
评论

相关推荐

    浅谈Android Classloader动态加载分析

    Android Classloader动态加载分析 Android Classloader动态加载分析是Android应用程序中一个非常重要的知识点。ClassLoader是Java虚拟机(JVM)中的一种机制,负责加载Java类文件到内存中,并将其转换为java.lang....

    浅谈java中的四个核心概念

    ### 浅谈Java中的四个核心概念 随着信息技术的飞速发展与互联网的普及,Java作为一门面向对象的、跨平台的编程语言,在软件开发领域占据了举足轻重的地位。Java不仅仅是一门语言,它更是一个庞大的技术平台。为了更...

    浅谈计算机软件开发的JAVA编程语言.pdf

    另外,JAVA7.0版本以后的升级类加载classloader架构提升了独立性和运行速度,以及支持使用catch语句进行智能选择,都使得JAVA语言在众多编程语言中脱颖而出,成为计算机软件开发的重要工具。 在计算机软件开发的...

    浅谈java项目与javaweb项目导入jar包的区别

    浅谈Java项目与JavaWeb项目导入JAR包的区别 Java项目和JavaWeb项目是两种不同的项目类型,虽然它们都使用Java语言,但是它们在项目结构、类加载器和JAR包导入方面存在着明显的差异。本文将对Java项目和JavaWeb项目...

    浅谈Java中类的实例化步骤

    ClassLoader使用双亲委托模型进行工作,即首先尝试父类的ClassLoader去查找类,如果找不到再由当前类Loader查找,直至到达顶层Bootstrap ClassLoader。如果始终找不到,JVM会抛出ClassNotFoundException。 类的初始...

    浅谈Java中的class类

    系统中有多个类加载器,如Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader,它们各自负责加载不同层次的类。`Class`对象的`getClassLoader()`方法可以获取到加载该类的类加载器。 `Class`对象还...

    浅谈JVM核心之JVM运行和类加载

    - **应用程序类加载器(Application ClassLoader)**:也称为系统类加载器,负责加载环境变量`CLASSPATH`或`-cp`指定的类。 - **自定义类加载器**:开发者可以继承`java.lang.ClassLoader`,实现自己的类加载逻辑。...

    浅谈java 中文件的读取File、以及相对路径的问题

    实际操作中,如果要读取某个配置文件,如`log4j.properties`,可以使用类加载器提供的方法,比如`ClassLoader.getSystemResourceAsStream("config/log4j.properties")`。这个方法会返回一个输入流,然后可以使用`...

    浅谈spring中scope作用域

    singleton 作用域与 GOF 设计模式中的单例模式不同,singleton 作用域表示一个容器对应一个 bean,而不是一个 ClassLoader 中只有一个 class 存在。 配置实例: ```xml ``` 或者 ```xml ``` prototype 作用域 --...

    浅谈Android中关于静态变量(static)的使用问题

    在Android上,类的卸载并不常见,因为默认的ClassLoader与进程生命周期同步,只要进程不结束,类就不会被卸载。 2. **进程与静态变量**: - Android的进程管理与PC上的JVM不同。Android可能会根据系统资源的需要...

Global site tag (gtag.js) - Google Analytics