使用来自Java 7的okhttp 3.12.x?

huangapple go评论116阅读模式
英文:

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 &quot;1.7.0_251&quot;
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.

huangapple
  • 本文由 发表于 2020年8月14日 18:09:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/63410786.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定