问题描述:
在新项目中因为MYSQL数据库的版本为5.6,对应的jdbc驱动包为5.1.40。但是引用后一直提示jar包版本不符合,看了很久一直没找到问题、最后没办法只能全局搜看还有没有其它JDBC驱动包。结果发现不知道什么时候在jre/lib/ext的目录下放了一个mysql-connect-jdbc.5.18.jar的包,把改jar删除问题解决。
在网上搜了下造成这个问题的主要原因为:JAVA类加载时采用树形的委托机制,默认有三个类加载器,bootstrap:主要加载jdk中jre/lib/rt.jar中的类,ExtClassLoader加载jre/lib/ext/*.jar,AppClassLoader加载classpath指定的jar或者目录,
这三个类加载器bootstrap是处在树的根节点,然后是ExtClassLoader,接着是子节点AppClassLoader。
bootstrap不是一个java类,其他两个都是java类,他们执行顺序是,bootstrap最先加载,然后ExtClassLoader加载。再AppClassLoader。
他们是采取向上委托的,即,如果AppClassLoader需要加载类时,首先它自己不加载,它向ExtClassLoader询问,ExtClassLoader也不加载,直接向bootstrap询问。这时,bootstrap是根节点,它没有上级,它直接去它的目录加载,如果加载成功,那就ok了,如果没有加载成功,那bootstrap会退回到ExtClassLoader,ExtClassLoader去它目录加载,如果加载成功,那就ok,如果没有成功,退回到AppClassLoader,AppClassLoader去它目录加载,如果加载成功那ok,如果不成功,如果AppClassLoader还有子的类加载器,AppClassLoader也不会退回到他的子加载器,AppClassLoader会直接抛异常。
“如果将JAR文件放入jre/lib/ext目录中,那么jre/lib/ext目录下是ExtClassLoader类加载器加载的,它会优先与AppClassLoader加载,所以导致项目启动后一直加载的是jre/lib/ext目录中的JDBC驱动。
另外在《Java核心编程》安全一章中有如下miao描述
警告:如果将JAR文件放入jre/lib/ext目录中,并且在它的类中有一个类需要调用既不是系统类也不是扩展类,那么就会遇到麻烦。扩展类加载器并不使用类路径。在使用扩展目录来解决文件的冲突之前,要牢记这种情况