前天禅道上给了我一个BUG,我最终找到了原因但是 需要修改原有框架里面的东西,修改的东西不多,但是如何去修改呢?
第一时间我想到的就是先将框架的jar包进行反编译修改完之后在进行打包,在放到仓库里面。于是在网上搜集这样的工具,网上也有很多反编译的工具,但是我看下来有一个问题,每一个工具都不能原模原样的把源码里面的东西进行复原,并且由于不同的解析语法,可能解析出来的代码格式也不一致,比如有的解析支持Java8的lamdam表达式和stream流,有的却不支持。
于是就暂时举步维艰,今天早上来问了下老大,人家给了我一个最简单的方案:
如果你想要修改你引入Jar包的源码,你可以在你的项目目录下创建一个相同路径的类,再把要扩展的类的内容全部都粘贴复制到自己定义的类,然后再次基础上进行自己的扩展,这样的话JVM类加载器就会加载你自己定义的类,而不会加载框架里的类。原因肯定是跟JVM类加载的顺序有关。
class file
存在于本地硬盘上,可以理解为设计师画在纸上的模板,而最终这个模板在执行的时候是要加载到JVM当中来根据这个文件实例化出n个一模一样的实例。class file
加载到JVM中,被称为DNA元数据模板
,放在方法区
。.class文件->JVM->最终成为元数据模板
,此过程就要一个运输工具(类装载器Class Loader
),扮演一个快递员的角色。
加载阶段完成三件事
全限定名
获取定义此类的二进制字节流
方法区
的运行时数据结构在内存中生成一个代表这个类的java.lang.Class对象
,作为方法区这个类的各种数据的访问入口在这里突然想到了JVM类加载器的双亲委派机制,双亲委派机制的作用就是① 避免类的重复加载 ②保护程序安全,防止核心API被随意篡改 【保护核心API】
Bootstrap ClassLoader
)C/C++
语言实现的,嵌套在JVM内部。JAVAHOME/jre/1ib/rt.jar、resources.jar或sun.boot.class.path
路径下的内容),用于提供JVM自身需要的类java.lang.ClassLoader
,没有父加载器。java、javax、sun
等开头的类Extension ClassLoader
)Java
语言编写,由sun.misc.Launcher$ExtClassLoader
实现。ClassLoader
类jre/1ib/ext子目录(扩展目录)
下加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。AppClassLoader
)java
语言编写,由sun.misc.LaunchersAppClassLoader
实现ClassLoader
类classpath
或系统属性 java.class.path
指定路径下的类库classLoader#getSystemclassLoader()
方法可以获取到该类加载器不言而喻,JVM是根据全限定名进行加载clsss,而且同一个路径的类只会加载一次,于是这就引起了类的加载优先级的问题,由结果可得知,
- 先是
Bootstrap ClassLoader
加载java、javax、sun
等开头的类,Extension ClassLoader
加载java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/1ib/ext子目录(扩展目录)
下加载类库。AppClassLoader
加载我们正常项目中的classAppClassLoader
加载我们maven项目中引入jar包的class