简体   繁体   English

找不到Java 10 Spring Boot Infinispan org.jgroups.logging.Slf4jLogImpl

[英]Java 10 Spring Boot Infinispan org.jgroups.logging.Slf4jLogImpl not found

I have a Spring Boot application which I'm building and running with Java 10. If I run the app using 我有一个正在使用Java 10构建并运行的Spring Boot应用程序。

java -jar

Everything works fine. 一切正常。 The app starts just OK. 该应用程序启动就可以了。

But if I put my app inside a Docker container with the exactly same Java version, my app throws this exception: 但是,如果我将应用程序放入具有完全相同的Java版本的Docker容器中,则我的应用程序将引发以下异常:

Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.jgroups.logging.Slf4jLogImpl
    at org.jgroups.logging.LogFactory.getLog(LogFactory.java:101)
    at org.jgroups.conf.XmlConfigurator.<clinit>(XmlConfigurator.java:33)
    at org.jgroups.conf.ConfiguratorFactory.getStackConfigurator(ConfiguratorFactory.java:62)
    at org.jgroups.JChannel.<init>(JChannel.java:122)
    at org.infinispan.remoting.transport.jgroups.JGroupsTransport.buildChannel(JGroupsTransport.java:591)
    at org.infinispan.remoting.transport.jgroups.JGroupsTransport.initChannel(JGroupsTransport.java:405)
    at org.infinispan.remoting.transport.jgroups.JGroupsTransport.start(JGroupsTransport.java:389)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.infinispan.commons.util.SecurityActions.lambda$invokeAccessibly$0(SecurityActions.java:79)
    ... 104 common frames omitted

I'm using this version of Java: 我正在使用此版本的Java:

java version "10.0.2" 2018-07-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)

Docker version is: Docker版本为:

Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        e68fc7a
 Built:             Tue Aug 21 17:21:31 2018
 OS/Arch:           darwin/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       e68fc7a
  Built:            Tue Aug 21 17:29:02 2018
  OS/Arch:          linux/amd64
  Experimental:     true

My Docker is using an Alpine base image alpine:latest . 我的Docker使用的是Alpine基本映像alpine:latest I'm installing java in my container from this link: 我通过以下链接在容器中安装Java:

curl -jksSLH "Cookie: oraclelicense=accept-securebackup-cookie" -o /tmp/java.tar.gz \
      http://download.oracle.com/otn-pub/java/jdk/10.0.2+13/19aef61b38124481863b1413dce1855f/jdk-10.0.2_linux-x64_bin.tar.gz

I'm really confused because from outside a docker container my app works fine, but inside a docker container it doesn't. 我真的很困惑,因为从Docker容器外部我的应用程序运行正常,但是在Docker容器内部却没有。 Either case I'm using the same Java version. 无论哪种情况,我都使用相同的Java版本。

UPDATE UPDATE

We tried Oracle JDK and OpenJDK, same behavior 我们尝试了Oracle JDK和OpenJDK,行为相同

UPDATE 2 更新2

We even tried java -jar from inside the container, no luck 我们甚至从容器内部尝试了java -jar ,没有运气

TL;DR TL; DR

There are three options to resolve. 有三个选项可以解决。

  1. Upgrade to version 4.0.16 of JGroups, currently in SNAPSHOT . 升级到JGroups的4.0.16版本,当前在SNAPSHOT中 Edit: Now released here . 编辑:现在在这里发布
  2. Make sure java properties for "user.language" and "user.country" are set. 确保设置了“ user.language”和“ user.country”的java属性。
  3. Force JDKLogImpl with -Djgroups.use.jdk_logger=true . 使用-Djgroups.use.jdk_logger=true强制JDKLogImpl。 (mentioned by Perimosh ) (由Perimosh提及)

Explanation 说明

Ran into this issue in the following scenario. 在以下情况下遇到此问题。

Apache Camel + JGroups worked fine in a local environment. Apache Camel + JGroups在本地环境中运行良好。 Deployed it elsewhere in a Docker instance, where we got the following stacktrace: 将其部署到Docker实例中的其他位置,我们在其中获得了以下堆栈跟踪:

2018-11-19 13:38:03.063  INFO 582 --- [           main] o.a.camel.spring.boot.RoutesCollector    : Loading additional Camel XML routes from: classpath:camel/*.xml
2018-11-19 13:38:03.064  INFO 582 --- [           main] o.a.camel.spring.boot.RoutesCollector    : Loading additional Camel XML rests from: classpath:camel-rest/*.xml
2018-11-19 13:38:03.107  INFO 582 --- [           main] o.a.camel.spring.SpringCamelContext      : Apache Camel 2.22.2 (CamelContext: camel-1) is starting
2018-11-19 13:38:03.111  INFO 582 --- [           main] o.a.c.m.ManagedManagementStrategy        : JMX is enabled
2018-11-19 13:38:03.480  INFO 582 --- [           main] o.a.camel.spring.SpringCamelContext      : StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at     http://camel.apache.org/stream-caching.html
2018-11-19 13:38:03.597  INFO 582 --- [           main] o.a.camel.spring.SpringCamelContext      : Apache Camel 2.22.2 (CamelContext: camel-1) is shutting down
2018-11-19 13:38:03.616  WARN 582 --- [           main] o.a.camel.spring.SpringCamelContext      : Error occurred while shutting down service: org.apache.camel.component.jgroups.cluster.    JGroupsLockClusterService@10fa5af5. This exception will be ignored.
java.lang.NullPointerException: null
    at org.apache.camel.component.jgroups.cluster.JGroupsLockClusterView.doStop(JGroupsLockClusterView.java:109)
    at org.apache.camel.support.ServiceSupport.stop(ServiceSupport.java:102)
    at org.apache.camel.impl.cluster.AbstractCamelClusterService.lambda$doStop$2(AbstractCamelClusterService.java:134)
    at org.apache.camel.util.concurrent.LockHelper.doWithReadLockT(LockHelper.java:54)
    at org.apache.camel.impl.cluster.AbstractCamelClusterService.doStop(AbstractCamelClusterService.java:130)
    at org.apache.camel.support.ServiceSupport.stop(ServiceSupport.java:102)
    at org.apache.camel.util.ServiceHelper.stopService(ServiceHelper.java:142)
    at org.apache.camel.util.ServiceHelper.stopAndShutdownService(ServiceHelper.java:205)
    at org.apache.camel.impl.DefaultCamelContext.shutdownServices(DefaultCamelContext.java:3663)
    at org.apache.camel.impl.DefaultCamelContext.shutdownServices(DefaultCamelContext.java:3688)
    at org.apache.camel.impl.DefaultCamelContext.shutdownServices(DefaultCamelContext.java:3676)
    at org.apache.camel.impl.DefaultCamelContext.doStop(DefaultCamelContext.java:3567)
    at org.apache.camel.support.ServiceSupport.stop(ServiceSupport.java:102)
    at org.apache.camel.impl.DefaultCamelContext.stop(DefaultCamelContext.java:3220)
    at org.apache.camel.spring.SpringCamelContext.stop(SpringCamelContext.java:148)
    ...

2018-11-19 13:38:03.679  INFO 582 --- [           main] o.a.camel.spring.SpringCamelContext      : Apache Camel 2.22.2 (CamelContext: camel-1) uptime 0.570 seconds
2018-11-19 13:38:03.680  INFO 582 --- [           main] o.a.camel.spring.SpringCamelContext      : Apache Camel 2.22.2 (CamelContext: camel-1) is shutdown in 0.082 seconds
2018-11-19 13:38:03.716  INFO 582 --- [           main] org.mongodb.driver.connection            : Closed connection [connectionId{localValue:2, serverValue:2}] to localhost:43115 because the pool has been closed.

As you can see, Apache Camel attempts to start, but never does and ends up shutting down. 如您所见,Apache Camel尝试启动,但是从不启动,最终关闭。 Thus, JGroups gets a NPE because it expects Camel to be up. 因此,JGroups获得了NPE,因为它希望骆驼起来。 After debugging the code, it appeared that there was an exception being thrown during the Camel start up process which was getting eaten. 调试代码后,似乎在Camel启动过程中抛出了一个异常,该异常被吞噬了。 From there, discovered that the creation of an instance of Slf4jLogImpl in org.jgroups.logging.LogFactory#getLog(java.lang.Class<?>) ( new Slf4jLogImpl(clazz) ) was a problem Method threw 'java.lang.ExceptionInInitializerError' exception. 从那里,发现在Slf4jLogImpl的实例的创建org.jgroups.logging.LogFactory#getLog(java.lang.Class<?>) new Slf4jLogImpl(clazz) )是一个问题Method threw 'java.lang.ExceptionInInitializerError' exception. :

java.lang.NullPointerException: null
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.jgroups.logging.LogFactory.getLog(LogFactory.java:101)
at org.jgroups.conf.XmlConfigurator.<clinit>(XmlConfigurator.java:33)
at org.jgroups.conf.ConfiguratorFactory.getXmlConfigurator(ConfiguratorFactory.java:210)
at org.jgroups.conf.ConfiguratorFactory.getStackConfigurator(ConfiguratorFactory.java:91)
at org.jgroups.JChannel.<init>(JChannel.java:130)
...

Running ( new Slf4jLogImpl(clazz) ) the second time onward in the debugger results in the following stacktrace that mirrors the original posted issue: 在调试器中第二次开始运行( new Slf4jLogImpl(clazz) )将导致以下new Slf4jLogImpl(clazz)new Slf4jLogImpl(clazz)跟踪反映了原始发布的问题:

java.lang.NoClassDefFoundError: Could not initialize class org.jgroups.logging.Slf4jLogImpl
at org.jgroups.logging.LogFactory.getLog(LogFactory.java:101)
at org.jgroups.conf.XmlConfigurator.<clinit>(XmlConfigurator.java:33)
at org.jgroups.conf.ConfiguratorFactory.getXmlConfigurator(ConfiguratorFactory.java:210)
at org.jgroups.conf.ConfiguratorFactory.getStackConfigurator(ConfiguratorFactory.java:91)
at org.jgroups.JChannel.<init>(JChannel.java:130)

This difference in results is due to the class loader caching the result of the Class.forName() call previously to determine that the class definition was not found. 结果的差异是由于类加载器先前缓存Class.forName()调用的结果以确定未找到类定义而导致的。

Finally, we tracked the previous NPE to be thrown from java.util.Locale#Locale(java.lang.String, java.lang.String, java.lang.String) , since country was null . 最后,由于country为null ,因此我们跟踪了从java.util.Locale#Locale(java.lang.String, java.lang.String, java.lang.String)抛出的先前的NPE。 This is because JGroup's org.jgroups.logging.Slf4jLogImpl is definine a LOCALE field using java properties for "user.language" and "user.country". 这是因为JGroup的org.jgroups.logging.Slf4jLogImpl是使用“ user.language”和“ user.country”的java属性定义的LOCALE字段。 The former was not set in our docker instance, so Locale.java threw the NPE. 前者未在我们的Locale.java实例中设置,因此Locale.java抛出了NPE。 Adding both of these java properties should fix this issue. 添加这两个java属性应该可以解决此问题。 Alternatively you can force using the JDKLogImpl so that the Slf4jLogImpl is never attempted to be instantiated. 另外,您可以强制使用JDKLogImpl这样就不会尝试实例化Slf4jLogImpl This was mentioned in the previous answer, by passing in -Djgroups.use.jdk_logger=true . 在前面的答案中,通过传递-Djgroups.use.jdk_logger=true提到了这一点。

Edit: Fixed in the latest version released here . 编辑:在此处发布的最新版本中已修复。

Now, it looks like this will be fixed in the upcoming JGroup release of 4.0.16.Final ( https://github.com/belaban/JGroups/commit/61578c657138f02178c32a564ac9eae7c3976093#diff-93eb0f6a8a4953312098be459bd7ce76 ). 现在,看来这将在即将发布的JGroup 4.0.16.Final( https://github.com/belaban/JGroups/commit/61578c657138f02178c32a564ac9eae7c3976093#diff-93eb0f6a8a49533120120be459bd7ce76 )中得到修复。 Until then, you can get the snapshot version with the fix at https://repository.jboss.org/nexus/content/repositories/snapshots/org/jgroups/jgroups/4.0.16-SNAPSHOT/ . 在此之前,您可以通过https://repository.jboss.org/nexus/content/repositories/snapshots/org/jgroups/jgroups/4.0.16-SNAPSHOT/获取带有修复程序的快照版本。

This is not a real solution, but since it unblocked us, I will share it. 这不是一个真正的解决方案,但是由于它解除了我们的封锁,我将与您分享。 Also, maybe somebody can think about the real problem by looking at this workaround. 另外,也许有人可以通过查看此变通办法来思考真正的问题。 We added this JVM argument to by pass SLF4J for jgroups and use JDKLogImpl 我们为jgroups通过传递SLF4J添加了此JVM参数,并使用JDKLogImpl

-Djgroups.use.jdk_logger=true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM