【问题标题】:Elasticsearch JAR hell errorElasticsearch JAR 地狱错误
【发布时间】:2016-03-02 17:50:24
【问题描述】:

我使用 Elasticsearch Java API 创建了一个 Java 文件。在 NetBeans 中,一切正常。

但是,我开始收到以下错误:

org/elasticsearch/plugins/PluginsService.java:342:in `loadBundles': java.lang.IllegalStateException: failed to load bundle [file:/D:/ELK-2.0/elasticsearch-2.0.0/plugins/license/license-2.0.0.jar, file:/D:/ELK-2.0/elasticsearch-2.0.0/plugins/license/license-core-2.0.0.jar, file:/D:/ELK-2.0/elasticsearch-2.0.0/plugins/license/license-plugin-api-2.0.0.jar, file:/D:/ELK-2.0/elasticsearch-2.0.0/plugins/marvel-agent/marvel-agent-2.0.0.jar] due to jar hell
        from org/elasticsearch/plugins/PluginsService.java:113:in `<init>'
        from org/elasticsearch/node/Node.java:144:in `<init>'
        from org/elasticsearch/node/NodeBuilder.java:145:in `build'
        from spamdetection/SpamDetection.java:63:in `client'
        from spamdetection/SpamDetection.java:30:in `SpammerDetector'
        from java/lang/reflect/Method.java:497:in `invoke'
        from spam.rb:53:in `(root)'
        from spam.rb:53:in `(root)'
Caused by:
JarHell.java:120:in `parseClassPath': java.lang.IllegalStateException: Classpath should not contain empty elements! (outdated shell script from a previous version?) classpath=''
        from JarHell.java:95:in `parseClassPath'
        from PluginsService.java:338:in `loadBundles'
        from PluginsService.java:113:in `<init>'
        from Node.java:144:in `<init>'
        from NodeBuilder.java:145:in `build'
        from SpamDetection.java:63:in `client'
        from SpamDetection.java:30:in `SpammerDetector'
        from NativeMethodAccessorImpl.java:-2:in `invoke0'
        from NativeMethodAccessorImpl.java:62:in `invoke'
        from DelegatingMethodAccessorImpl.java:43:in `invoke'
        from Method.java:497:in `invoke'
        from JavaMethod.java:451:in `invokeDirectWithExceptionHandling'
        from JavaMethod.java:312:in `invokeDirect'
        from InstanceMethodInvoker.java:45:in `call'
        from CachingCallSite.java:326:in `cacheAndCall'
        from CachingCallSite.java:170:in `call'
        from spam.rb:53:in `__file__'
        from spam.rb:-1:in `load'
        from Ruby.java:857:in `runScript'
        from Ruby.java:850:in `runScript'
        from Ruby.java:729:in `runNormally'
        from Ruby.java:578:in `runFromMain'
        from Main.java:395:in `doRunFromMain'
        from Main.java:290:in `internalRun'
        from Main.java:217:in `run'
        from Main.java:197:in `main'

尝试从 JRuby 调用我的 Java JAR 文件时。是什么导致了这个错误?

【问题讨论】:

  • 我在运行测试时遇到了同样的问题,在我的情况下根本无法删除重复的 jar - 许多 trasitive 依赖项。只是想知道除了修改弹性搜索代码之外是否还有其他解决方案?请在此处查看问题:github.com/elastic/elasticsearch/issues/14348

标签: elasticsearch java


【解决方案1】:

您可以在您的src/test/java 中创建一个名为org.elasticsearch.bootstrap 的包,并将此类放入其中:

package org.elasticsearch.bootstrap;
import java.net.URL;
public class JarHell {
    private JarHell() {}
    public static void checkJarHell() throws Exception {}
    public static void checkJarHell(URL urls[]) throws Exception {}
    public static void checkVersionFormat(String targetVersion) {}
    public static void checkJavaVersion(String resource, String targetVersion) {}
    public static URL[] parseClassPath() {return new URL[]{};}
}

这样做的好处是使用节点构建器初始化节点的生产代码可以保持干净,只有在单元测试中禁用 jar hell 检查。

【讨论】:

  • 呃。我偶尔会遇到这个错误,我尝试过的解决方案都是一团糟。这就像一个魅力!谢谢
  • 在 ES5.6 中,函数 parseClassPath() 的签名发生了变化。所以,新的应该是public static Set&lt;URL&gt; parseClassPath() {return ImmutableSet.of();}
【解决方案2】:

您现在可以通过tests.jarhell.check 属性在测试期间disable“jar hell”检查。

【讨论】:

  • 请告诉我如何设置。我添加了这个测试 { systemProperties = System.properties systemProperty 'tests.security.manager', 'false' systemProperty 'tests.jarhell.check', 'false' } 但仍然无法正常工作。在哪里禁用它
  • 通过设置禁用 jarhell 仅在您尝试加载插件之前有效 - PluginManager 不会检查此标志。您需要从嵌入的“主”目录中删除所有插件文件。然后你可以通过类路径加载插件,见stackoverflow.com/questions/41298467/how-to-start。否则,只有在通过其他答案中提到的 hack 禁用 jarhell 时才能加载插件。
【解决方案3】:

如果您在运行单元测试时遇到“jar hell”错误,请遵循 hack 处理它 - 同意这不是一种优雅的方式。

String originalClassPath = System.getProperty("java.class.path");
  String[] classPathEntries = originalClassPath.split(";");
  StringBuilder esClasspath = new StringBuilder();
       for (String entry : classPathEntries) {
           if (entry.contains("elasticsearch") || entry.contains("lucene")) {
               esClasspath.append(entry);
               esClasspath.append(";");
           }
       }
  System.setProperty("java.class.path", esClasspath.toString());
  node = nodeBuilder().local(true).settings(settings).node();
  System.setProperty("java.class.path", originalClassPath);

【讨论】:

    【解决方案4】:

    我迟到了,但我认为我的答案可能会在将来对其他人有所帮助,这就是我发布它的原因。

    我认为正确的解决方案是找到根本原因并排除产生 jar hell 的库,而不是隐藏问题。例如,就我而言,我有以下重复的库:

    Caused by: java.lang.IllegalStateException: jar hell!
    class: org.hamcrest.BaseDescription
    jar1: C:\Users\Yeikel\.m2\repository\org\hamcrest\hamcrest-all\1.3\hamcrest-all-1.3.jar
    jar2: C:\Users\Yeikel\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar
            at org.elasticsearch.bootstrap.JarHell.checkClass(JarHell.java:275)
            at org.elasticsearch.bootstrap.JarHell.checkJarHell(JarHell.java:192)
            at org.elasticsearch.bootstrap.JarHell.checkJarHell(JarHell.java:89)
            at org.elasticsearch.bootstrap.BootstrapForTesting.<clinit>(BootstrapForTesting.java:90)
    

    我为解决这个问题所做的只是找到重复项并将其从我的库中排除。在这种情况下,该库也与 JUnit 捆绑在一起

    <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.hamcrest</groupId>
                        <artifactId>hamcrest-core</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    

    【讨论】:

      【解决方案5】:

      由于 elasticsearch 7.14.0 JarHell 类已移至 org.elasticsearch.jdk 包。要在 Elasticsearch 版本 >= 7.14 中禁用 jar hell 检查,只需在 org.elasticsearch.jdk 包中创建以下类。

      package org.elasticsearch.jdk;
      
      import java.net.URL;
      import java.util.HashSet;
      import java.util.Set;
      import java.util.function.Consumer;
      
      public class JarHell {
          private JarHell() {}
      
          public static void checkJarHell(Set<URL> urls, Consumer<String> output) throws Exception {}
      
          public static void checkJarHell(Consumer<String> output) {}
      
          public static void checkVersionFormat(String targetVersion) {}
      
          public static void checkJavaVersion(String resource, String targetVersion) {}
      
          public static Set<URL> parseClassPath() {
              return new HashSet<>();
          }
      
          static Set<URL> parseClassPath(String classPath) {
              return new HashSet<>();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-11-11
        • 1970-01-01
        • 1970-01-01
        • 2011-04-30
        • 2017-12-30
        • 1970-01-01
        • 2016-05-29
        • 1970-01-01
        • 2012-10-28
        相关资源
        最近更新 更多