Retrofit2, Maven项目,非法反射访问警告

35

我刚开始一个新的Maven项目,并对Retrofit客户端进行了简单实现。我收到以下警告:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by retrofit2.Platform (file:/C:/Users/Admin/.m2/repository/com/squareup/retrofit2/retrofit/2.8.1/retrofit-2.8.1.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of retrofit2.Platform
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Process finished with exit code 0

这是代码

import retrofit2.Retrofit;
import retrofit2.SimpleXmlConverterFactory;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

public class RetrofitClient {

    private static Retrofit retrofit = null;
    private RetrofitClient() { }

    public static EndPoints getAPI(String baseUrl) {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(SimpleXmlConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
        }
        return retrofit.create(EndPoints.class);
    }
}

界面仅仅是

import retrofit2.Call;
import retrofit2.http.GET;

public interface EndPoints {
    @GET("teststatuses")
    Call<String> testStatus();
}

调用看起来像这样:

EndPoints endPoints = RetrofitClient.getAPI("http://localhost:8080/");
Call<String> repos = endPoints.testStatus();
System.out.println(repos.execute());

该项目使用Java语言11级别和SDK 11。

5个回答

37

有一个问题关于此事进行了报告,其中Retrofit的维护人员之一做出了回应:

反射修复了JDK中的一个错误,该错误在14中被修复,但仅用于默认方法。由于这只是一个警告,它不会阻止您的调用工作。

因此,您的选择是:

  1. 坚持使用Retrofit 2.8.x,并且
    • 忽略警告,或
    • 升级到Java 14
  2. 降级到Retrofit 2.7.*

为什么 Retrofit 2.8.X 没有对 JDK >= 14 有硬依赖,这会给你更好的错误提示?在 Java 领域中不可能吗? - Peheje
只是猜测:虽然使用 Maven 和 Enforcer 插件 可能确实可行,但 Retrofit 制造商可能只是不想使 JDK 14以下的用户无法使用 Retrofit 2.8。 - sschuberth
谢谢 sscuberth。知道这个很好。只是如果不使用JDK 14,用户如何使用Retrofit 2.8呢?因为它不能正常工作。 - Peheje
它确实可以工作。毕竟,这只是一个警告。 - sschuberth

5

如果你使用的Java版本在9到13之间,并且想要使用2.8或更高版本的Retrofit,你可以按照以下方式运行你的jar文件:

java --add-opens=java.base/java.lang.invoke=ALL_UNNAMED my_jar.jar

请注意,这种方法不适用于Java 8,如果您确实需要,可以像这样实现一个解决方案(在*nix上工作):

if java --add-opens 2>&1 | grep 'requires modules' >/dev/null; then
  java --add-opens=java.base/java.lang.invoke=ALL-UNNAMED -jar my_jar.jar
else
  java -jar my_jar.jar
fi

如果你想进一步了解这个问题,可以查看 导致此问题的代码
我还发现这篇文章有很好的信息:https://blog.codefx.org/java/five-command-line-options-hack-java-module-system/ 如果你使用Gradle,也可以尝试添加默认的jvm参数:如何在Gradle中添加默认的JVM参数。但是,这仍然不能让你得到一个简单运行的纯jar文件。

3
我已经将这个代码块添加到我的模块 build.gradle 文件中。
Gradle
tasks.withType(Test) {
  /**
   * fix for retrofit https://github.com/square/retrofit/issues/3341
   */
  jvmArgs = ["--add-opens", "java.base/java.lang.invoke=ALL-UNNAMED"]
}

Kotlin DSL

tasks.withType<Test> {
  /**
   * fix for retrofit https://github.com/square/retrofit/issues/3341
   */
  jvmArgs = listOf("--add-opens", "java.base/java.lang.invoke=ALL-UNNAMED")
}

警告不再显示了。我认为这样移除是安全的,因为它只影响测试任务。


3
今天我遇到了同样的错误。我将Retrofit 2.8.1导入到我的项目中,然后它出现了。我尝试了所有方法,但只有一件事情有效 - 我将Retrofit版本更改为2.7.2,现在一切都正常了。祝你好运! 如果您使用Maven:
<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>retrofit</artifactId>
    <version>2.7.2</version>
</dependency>

Gradle:
compile group: 'com.squareup.retrofit2', name: 'retrofit', version: '2.7.2'

这是一个警告,而不是错误。 - rwst

1

在处理版本时要小心。我通过降级到Retrofit 2.7.*来解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接