Java中spi机制是否打破类加载器可见性原则
java中的类加载器遵循可见性原则,即类加载器只能加载其父加载器或自身加载的类。然而,有文章提出,java中的服务提供者接口(spi)机制可能会破坏此原则。
使用spi机制的代码片段
public static <S> ServiceLoader<S> load(class<S> service) { ClassLoader cl = Thread.currentThread().getContextClassLoader(); return ServiceLoader.load(service, cl); }
违反可见性原则的说法
立即学习“Java免费学习笔记(深入)”;
该代码使用sun.misc.launcher.appclassloader加载实现了servletcontainerinitializer接口的类。launcher.appclassloader是应用程序类加载器,它不能加载由引导类加载器加载的类。因此,有人认为这违反了可见性原则。
实际情况
事实上,java.util.serviceloader的load方法最终仍会使用双亲委派机制。serviceloader.lazyiterator#nextservice方法中调用class.forname方法加载类,而class.forname会沿着双亲委派链向上委派,直到找到该类为止。
因此,即使使用spi机制,load方法仍然可以通过双亲委派机制加载由其他类加载器加载的类。这不会破坏可见性原则。
打破双亲委派机制的经典范例
虽然spi机制本身不会打破双亲委派机制,但它确实是一个违反此机制的经典范例。这是因为spi允许第三方类加载器加载实现接口的类,而这些类可能无法由引导类加载器或应用程序类加载器直接访问。