Java 8 Windows下扩展类加载器加载任意扩展名文件:设计还是Bug?
这其实是设计使然,并非Bug,背后是两类类加载器的定位和职责差异导致的:
扩展类加载器的设计目标:兼容与容错
扩展类加载器(Extension ClassLoader)负责加载Java平台的扩展组件,早期Java的很多核心扩展(比如JCE加密扩展、JDBC驱动扩展)都是放在$JAVA_HOME/lib/ext目录下。它的设计逻辑是尽可能扫描目录内的所有文件,尝试从中加载类——不管文件扩展名是什么。这种设计是为了兼容早期可能出现的非标准归档格式,或者用户误命名的文件,确保合法的扩展组件不会因为文件名问题无法加载,最大化容错性。应用类加载器的设计目标:严谨与性能
应用类加载器(Application ClassLoader)是处理用户自己的应用代码,通过-cp/CLASSPATH指定的路径加载类。它只识别.jar/.JAR扩展名的文件(以及包含类文件的目录),这是为了避免加载无关文件(比如日志、配置、临时文件等),减少不必要的文件解析操作,提升加载性能,同时也符合开发者的常规预期——只有明确标记为Java归档包的文件才会被纳入类路径。关于官方文档的补充
虽然你没找到Oracle的直接说明,但Java 8官方文档中关于「Java扩展机制」的章节其实隐含了这一点:lib/ext目录的定位就是放置平台扩展,类加载器会尝试解析目录内的所有可归档文件。另外需要注意,Java 9及以后的版本已经废弃了这个扩展机制,改用模块化系统,lib/ext目录也不再被类加载器扫描,这个差异也就不存在了。
如果你想验证这个逻辑,可以做个小测试:把包含类文件的归档包改成.txt或者任意扩展名放到lib/ext,启动Java程序后依然能加载到类;但把同样的文件放到应用类路径的文件夹下,应用类加载器会直接忽略它。
内容的提问来源于stack exchange,提问作者Peter Tarlos

