自己写了一个redis工具,在Jfinal启动的时候发现有不同的类加载器都要加载Jedis这个类,导致启动失败。后面发现将undertow的开发模式关闭(热加载关闭),就能正常启动。
# 设置为false可正常启动 undertow.devMode=false
undertow的开发模式下,我在代码里打印了下类加载器:
Class<?> jedisClass = null; try { jedisClass = Class.forName("redis.clients.jedis.Jedis"); ClassLoader loader = jedisClass.getClassLoader(); System.out.println("Jedis loaded by: " + loader); System.out.println("Parent loader: " + loader.getParent()); } catch (ClassNotFoundException e) { throw new RuntimeException(e); }
结果是:
Jedis loaded by: com.jfinal.server.undertow.hotswap.HotSwapClassLoader@1b75c2e3 Parent loader: sun.misc.Launcher$AppClassLoader@18b4aac2 Exception in thread "main" java.lang.LinkageError: loader constraint violation: loader (instance of sun/misc/Launcher$AppClassLoader) previously initiated loading for a different type with name "redis/clients/jedis/Jedis" at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:170) at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:566) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:306) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:233) at redis.clients.jedis.util.Pool.getResource(Pool.java:38) at redis.clients.jedis.JedisPool.getResource(JedisPool.java:378)
只要将开发模式关闭,打印的就都是sun.misc.Launcher,则能正常启动。
------收个尾------
按照评论区热心人士小杜同学的方法解决了,虽然现在仍不明白这个类为什么会被热加载器补捕获。方法如下:
UnsertowServer.create(...).addSystemClassPrefix("redis.clients.jedis.").start();
通过addSystemClassPrefix方法将其强行推给系统级classLoader来加载。
------还得收个尾------
这就是redis.clients会被热加载爱上的原因了。
文档的 第4 小结 配置