英文:
Using okhttp 3.12.x from java 7?
问题
引用 okhttp 的 GitHub 页面:
> OkHttp 3.12.x 分支支持 Android 2.3+(API 级别 9+)和 Java 7+
但是查看 com.squareup.okhttp3:okhttp:3.12.12
(在撰写本文时似乎是最新的 3.12.x 版本),我们发现以下内容:
import java.time.Duration; // OkHttpClient.java 的第 23 行
以及对 Duration 的各种使用,这是 Java 8 的特性。这使得我的代码在运行时出现错误:
java.lang.ClassNotFoundException: java.time.Duration
在以下环境中运行时会出现这个问题:
java version "1.7.0_251"
Java(TM) SE Runtime Environment (build 1.7.0_251-b08)
Java HotSpot(TM) 64-Bit Server VM (build 24.251-b08, mixed mode)
这在我的目标环境中是一个硬性要求。
事实上,是否存在适用于 Java 7 的相当新版本的 okhttp 呢?根据我的理解(不是根据文档),3.12.x 分支主要是为了支持 Android,我认为在某些条件下,像 java.time
这样的包在 Java 7 中实际上是可用的。
假设实际上不能在 Java 7(普通的,不是 Android)中使用 okhttp 3.12.x,也许更新文档以反映这一点会很好,以节省其他人可能会经历的探索之旅。
< 编辑 - 在 yuri 的回答后添加的评论 >
我创建了一个带有堆栈跟踪的 Gist,链接在这里。在第 53 行的破坏性语句是:
client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
(删除 addInterceptor
调用并不能解决问题)
还应该注意,这是一个只有两个类的小项目,我是使用 Java 11 构建的,然后使用后续版本的 Gradle(以及 Java)的机制来针对 Java 7,最后使用上述的 Java 7 版本来执行这个 fat jar。引用 Gradle 的描述:
> 从 9 版本开始,可以配置 Java 编译器以为较旧的 Java 版本生成字节码,同时确保代码不使用较新版本的任何 API。
因此,我是使用以下配置进行构建的:
------------------------------------------------------------
Gradle 6.6
------------------------------------------------------------
Build time: 2020-08-10 22:06:19 UTC
Revision: d119144684a0c301aea027b79857815659e431b9
Kotlin: 1.3.72
Groovy: 2.5.12
Ant: Apache Ant(TM) version 1.10.8 compiled on May 10 2020
JVM: 11.0.7 (Amazon.com Inc. 11.0.7+10-LTS)
OS: Mac OS X 10.15.5 x86_64
并且使用上述提到的 Oracle Java 7 进行运行。
我之所以使用 Java 11 进行构建是因为使用 Java 7 强制我降级 Gradle 和许多插件到古老的版本,整体变得混乱。虽然可行,但最好不要这样做。
英文:
Quoting the okhttp github page:
> The OkHttp 3.12.x branch supports Android 2.3+ (API level 9+) and Java 7+
But looking at com.squareup.okhttp3:okhttp:3.12.12
(seems to be the latest 3.12.x release at the time of writing), we find the following:
import java.time.Duration; // OkHttpClient.java line 23
and various uses of Duration which is a java 8 feature. This makes my code break at runtime with a:
java.lang.ClassNotFoundException: java.time.Duration
when running with:
java version "1.7.0_251"
Java(TM) SE Runtime Environment (build 1.7.0_251-b08)
Java HotSpot(TM) 64-Bit Server VM (build 24.251-b08, mixed mode)
which is a hard requirement in my target environment.
Is there in fact a java 7 compatible decently recent version of okhttp?
The way I read the tea leaves (as in not the docs) is that the 3.12.x branch is mostly there to support android where I assume things might be slightly different and packages like java.time
are actually available in java 7 under certain conditions.
Assuming it is actually not possible to use okhttp 3.12.x from java 7 (normal, not android), it might be good to update the docs to reflect this to save somebody else the explorative journey I just went through.
< edit - comment added after response by yuri >
I created a gist with a stack trace here. The breaking statement on line 53 is:
client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
(removing the addInterceptor
call does not fix the problem)
Also it should be noted that this is a small, two-class project which I'm building with java 11, then using the mechanics in later versions of gradle (and java) to target java 7 and finally executing the fat jar with the above java 7 version. Quoting the gradle description:
> Since version 9, the Java compiler can be configured to produce bytecode for an older Java version while making sure the code does not use any APIs from a more recent version.
So I'm building with:
------------------------------------------------------------
Gradle 6.6
------------------------------------------------------------
Build time: 2020-08-10 22:06:19 UTC
Revision: d119144684a0c301aea027b79857815659e431b9
Kotlin: 1.3.72
Groovy: 2.5.12
Ant: Apache Ant(TM) version 1.10.8 compiled on May 10 2020
JVM: 11.0.7 (Amazon.com Inc. 11.0.7+10-LTS)
OS: Mac OS X 10.15.5 x86_64
and running with the above mentioned oracle java 7.
The reason I'm building with java 11 is that building with java 7 forces me to downgrade gradle and a number of plugins to ancient versions and just generally becomes a mess. Possible, but would be nice not to.
答案1
得分: 2
回答自己的问题。在此问题上,经过okhttp开发人员的一些反馈后,似乎这个问题是由于Groovy对反射访问/内省的使用所导致的。
我在显示出问题的方法上添加了CompileStatic
注解:
https://docs.groovy-lang.org/latest/html/gapi/groovy/transform/CompileStatic.html
问题现在已经消失了。
英文:
Answering my own question. After some feedback from the okhttp devs on an issue created for this at:
https://github.com/square/okhttp/issues/6221
it seems that this issue is caused by groovy's use of reflective access / introspection.
I added the CompileStatic
annotation:
https://docs.groovy-lang.org/latest/html/gapi/groovy/transform/CompileStatic.html
to the method exhibiting the issue and the issue is now gone.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论