【问题标题】:Java 9 HttpClient java.lang.NoClassDefFoundError: jdk/incubator/http/HttpClientJava 9 HttpClient java.lang.NoClassDefFoundError: jdk/incubator/http/HttpClient
【发布时间】:2018-05-08 03:18:09
【问题描述】:

我正在尝试在 Java 9 maven 项目中使用孵化器中的 HttpClient。我没有收到任何编译问题。项目成功构建。但是当我尝试运行 Main 类时,它给了我以下异常:

Exception in thread "main" java.lang.NoClassDefFoundError: jdk/incubator/http/HttpClient
at java9.http_client.Main.main(Main.java:18)
Caused by: java.lang.ClassNotFoundException: jdk.incubator.http.HttpClient
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)....

我的代码只是一个模块信息文件和一个 Main 类,它只调用 google.com 并尝试读取响应:

模块信息.java

module java9.http_client {   
    requires jdk.incubator.httpclient;
}

Main.java

public final class Main {

public static void main(String[] args) {
 try {
        HttpClient client = HttpClient.newHttpClient();
        URI httpURI = new URI("http://www.google.com/");
        HttpRequest request = HttpRequest.newBuilder(httpURI).GET().build();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());

        String responseBody = response.body();
        int responseStatusCode = response.statusCode();
        System.out.println(responseBody + "\n" + responseStatusCode);

    } catch (URISyntaxException | IOException | InterruptedException e) {
        throw new RuntimeException("Unable to run Java 9 Http Client examples", e);
    }
}
}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javacodegeeks.java9</groupId>
<artifactId>http_client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Java9HttpClient</name>
<description>Java Http Client example</description>
<properties>
    <java-version>1.9</java-version>

    <maven-compiler-plugin-version>3.6.1</maven-compiler-plugin-version>
    <maven-shade-plugin-version>3.0.0</maven-shade-plugin-version>
</properties>

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin-version}</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>${maven-shade-plugin-version}</version>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>${java-version}</source>
                <target>${java-version}</target>
                <verbose>true</verbose>

            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.javacodegeeks.java9.http_client.Main</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

我错过了什么?我找到了很多关于这个的文章,但他们都是这样做的。

感谢任何帮助。谢谢!

使用 --add-modules 时执行的命令

cd /home/mansi/NetBeansProjects/java9-http-client; JAVA_HOME=/home/mansi/jdk-9 /home/mansi/netbeans-dev-201709070001/java/maven/bin/mvn "-Dexec.args=--add-modules=jdk.incubator.httpclient -classpath %classpath java9.http_client.Main" -Dexec.executable=/home/mansi/jdk-9/bin/java -Dexec.classpathScope=runtime org.codehaus.mojo:exec-maven-plugin:1.5.0:exec

不使用 --add-modules 时

cd /home/mansi/NetBeansProjects/java9-http-client; JAVA_HOME=/home/mansi/jdk-9 /home/mansi/netbeans-dev-201709070001/java/maven/bin/mvn "-Dexec.args=-classpath %classpath java9.http_client.Main" -Dexec.executable=/home/mansi/jdk-9/bin/java -Dexec.classpathScope=runtime org.codehaus.mojo:exec-maven-plugin:1.5.0:exec

【问题讨论】:

  • 是的,上面链接的有编译错误的解决方案,但我没有遇到任何编译问题。项目成功构建。但是当我尝试运行 Main 类时,它给了我提到的异常
  • 我运行Main 类,只需右键单击并运行文件。是的,我在您提到的另一个链接中看到了答案,根据您的回答,使用 --add-modules 是使用 module-info.java 的替代方法,不是吗?
  • 运行 Main 类时,请确保添加 VM 参数 --add-modules jdk.incubator.httpclient
  • 行得通!非常感谢。是否必须使用此 VM 选项?有没有不用的办法?
  • 孵化器模块是标准 JDK 构建生成的 JDK 运行时映像的一部分。但是,默认情况下,类路径上的应用程序不会解析孵化器模块。类路径上的应用程序必须使用 --add-modules 命令行选项来请求解析孵化器模块。作为模块开发的应用程序可以直接指定需要或需要对孵化器模块的传递依赖。来自openjdk.java.net/jeps/11

标签: java java-9 java-module java-http-client


【解决方案1】:

如果接受的答案仍然不适合你,那么..

缺少的秘诀是还包含具有相同编译器参数的maven-surefire-plugin

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>10</source>
                    <target>10</target>
                    <compilerArgument>--add-modules=jdk.incubator.httpclient</compilerArgument>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.21.0</version>
                <configuration>
                    <argLine>--add-modules=jdk.incubator.httpclient</argLine>
                </configuration>
            </plugin>
        </plugins>
    </build>

【讨论】:

    【解决方案2】:

    执行期间的区别在于使用类路径与模块路径。 JEP11#Incubator Modules 中要注意的语句为

    ... 孵化器模块默认情况下不会为应用程序解析 类路径。

    所以为了使用类路径执行代码

    类路径上的应用程序必须使用--add-modules 用于请求解析孵化器模块的命令行选项。


    如果您想在不使用--add-modules 选项的情况下执行,同时创建一个新的module 并尝试执行Main 类,请确保使用模块路径使用参数执行java 命令:

    -p or --module-path <module path>
    

    从分号分隔 (;) 的目录列表中搜索目录。每个目录都是一个模块目录。

    -m or --module <module>/<mainclass
    

    指定要解析的初始模块的名称,如果模块未指定,则指定要执行的主类的名称。

    完整的命令将是(例如)类似:

    .../jdk-9.0.1.jdk/Contents/Home/bin/java 
           -p .../jdk9-httpincubate-maven/target/classes 
           -m jdk.httpincubate.maven/http2.Main
    

    注意

    • 在我创建的示例项目中遵循上述目录结构on GitHub 以复制相同的内容。

    • 只是添加到它并且没有任何宣传我正在使用 intelliJ 的 2017.3 EAP,它也让我运行没有 VM 参数的 Main 类(使用包含上述参数的命令。)

    【讨论】:

    • 问题:如果我要求在编译时通过--add-modules 参数解析孵化器模块,为什么这些模块不包含在编译/打包产生的WAR/JAR 中?我认为编译后的代码已经解析了模块,因此它们的类被包含在内,我也不需要破解我的应用服务器来添加相同的参数......
    • @ZalánMeggyesi 为什么这些模块不包含在编译/打包产生的 WAR/JAR 中? ...回答这个问题,JDK 中没有任何模块将包含在您创建的 JAR 中...执行将依赖于您将用于启动应用程序的 JDK/JRE,因此根据具体情况来解析模块.. 对于我可以建议使用 HTTP模块,您可以等待并迁移到 JDK11(也是 LTS 版本),然后使用 the standardized HTTP module 本身。
    • 感谢您为我解决这个问题!老实说,我只是觉得奇怪的是,即使是带阴影的 JAR 也缺少这些模块,但是由于在这种特定情况下的应用服务器是我控制下的独立 Jetty,因此破解它是绝对可行的,尽管有点牵强。该应用程序对我来说几乎是一个测试平台,所以我也跳转到 JDK11。
    猜你喜欢
    • 2017-05-30
    • 2017-10-31
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多