Java类加载器可见性原则
问题:
在加载一个接口的实现类时,Java.util.ServiceLoader#load方法使用了sun.misc.Launcher.AppClassLoader类加载器,这是否违背了Java类加载器可见性原则?
回答:
立即学习“Java免费学习笔记(深入)”;
要理解这个问题,首先需要了解SPI(服务提供者接口)的机制。SPI是一种Java机制,允许第三方提供程序实现特定接口,并在运行时加载这些实现。
在使用SPI时,Java类加载器会违反可见性原则,因为它会绕过双亲委派机制。正常情况下,类加载器只会从其父加载器中搜索类,但在使用SPI时,类加载器会直接从线程上下文类加载器中搜索实现类,这可能会加载其他类加载器已定义的类。
在给定的代码中,java.util.ServiceLoader#load方法使用了sun.misc.Launcher.AppClassLoader作为线程上下文类加载器来加载ServletContainerInitializer接口的实现类。这个类加载器是Java类加载层次结构中的应用程序类加载器,它是应用程序专用类加载器。
因此,虽然代码中没有显式调用java.lang.ClassLoader#loadClass(java.lang.String, Boolean)方法,但类加载器仍然会执行双亲委派机制。这是因为AppClassLoader是ClassLoader类的顶级抽象类,并且会委托给父加载器(bootstrap加载器),直到找到实现ServletContainerInitializer接口的类。
总之,使用SPI会导致违反Java类加载器可见性原则,因为它使用线程上下文类加载器直接加载实现类,这可能会加载其他类加载器已定义的类。