字节码是否知道 Java 版本

Is bytecode aware of Java Version

抱歉,如果这是一个愚蠢的问题,我还没有找到直接的答案。

我编译了一个用 Java 9 个特性编写的程序并生成了一个 .jar。

程序的本质是我需要同时在两台机器上运行ning,一台是运行ning java 8,一台是运行ning Java 9. 我的程序不工作,特别是 jdk.incubator.httpclient 模块无法将 HttpRequest 从一台机器发送到另一台机器。

将 JDK8 机器更新到 9 不是一个选项。

我的问题是,一旦全部变成字节码,这有关系吗? Java 9 生成的 jar 中是否存在 Java 8 JVM 无法理解的字节码?

可能值得注意的是,我必须 运行 带有 java -jar --add-modules=jdk.incubator.httpclient 的 jar 才能使用新的 java 9 孵化器模块 httpclient

我知道一个聪明的解决方案是确保双方的防火墙都允许这两个人交谈,但是我也想知道上述问题的答案!

提前致谢。

这是堆栈跟踪:

2018-01-09 01:15:57.410  INFO 4656 --- [nio-8080-exec-2] c.e.s.controller.MessageController       : [TO http://192.168.1.64:8080/send] Hello Bob it is Jim!
2018-01-09 01:18:08.551 ERROR 4656 --- [nio-8080-exec-2] c.e.s.service.MessagingService           : send: unable to send request 

java.net.ConnectException: Connection timed out
    at java.base/sun.nio.ch.Net.connect0(Native Method) ~[na:na]
    at java.base/sun.nio.ch.Net.connect(Net.java:454) ~[na:na]
    at java.base/sun.nio.ch.Net.connect(Net.java:446) ~[na:na]
    at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:648) ~[na:na]
    at jdk.incubator.httpclient/jdk.incubator.http.PlainHttpConnection.connect(PlainHttpConnection.java:142) ~[jdk.incubator.httpclient:na]
    at jdk.incubator.httpclient/jdk.incubator.http.Http1Exchange.sendHeadersOnly(Http1Exchange.java:136) ~[jdk.incubator.httpclient:na]
    at jdk.incubator.httpclient/jdk.incubator.http.Exchange.responseImpl0(Exchange.java:298) ~[jdk.incubator.httpclient:na]
    at jdk.incubator.httpclient/jdk.incubator.http.Exchange.responseImpl(Exchange.java:245) ~[jdk.incubator.httpclient:na]
    at jdk.incubator.httpclient/jdk.incubator.http.Exchange.response(Exchange.java:121) ~[jdk.incubator.httpclient:na]
    at jdk.incubator.httpclient/jdk.incubator.http.MultiExchange.response(MultiExchange.java:154) ~[jdk.incubator.httpclient:na]
    at jdk.incubator.httpclient/jdk.incubator.http.HttpClientImpl.send(HttpClientImpl.java:234) ~[jdk.incubator.httpclient:na]
    at com.example.simplemessenger/com.example.simplemessenger.service.MessagingService.send(MessagingService.java:30) ~[classes/:na]
    at com.example.simplemessenger/com.example.simplemessenger.controller.MessageController.sendMessage(MessageController.java:71) [classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) [spring-web-4.3.13.RELEASE.jar:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) [spring-web-4.3.13.RELEASE.jar:na]
    at spring.webmvc@4.3.13.RELEASE/org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) [spring-webmvc-4.3.13.RELEASE.jar:na]
    at spring.webmvc@4.3.13.RELEASE/org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.13.RELEASE.jar:na]
    at spring.webmvc@4.3.13.RELEASE/org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) [spring-webmvc-4.3.13.RELEASE.jar:na]
    at spring.webmvc@4.3.13.RELEASE/org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.3.13.RELEASE.jar:na]
    at spring.webmvc@4.3.13.RELEASE/org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) [spring-webmvc-4.3.13.RELEASE.jar:na]
    at spring.webmvc@4.3.13.RELEASE/org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) [spring-webmvc-4.3.13.RELEASE.jar:na]
    at spring.webmvc@4.3.13.RELEASE/org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.13.RELEASE.jar:na]
    at spring.webmvc@4.3.13.RELEASE/org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.3.13.RELEASE.jar:na]
    at tomcat.embed.core@8.5.23/javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.23.jar:na]
    at spring.webmvc@4.3.13.RELEASE/org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.13.RELEASE.jar:na]
    at tomcat.embed.core@8.5.23/javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.websocket@8.5.23/org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.13.RELEASE.jar:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.13.RELEASE.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) [spring-web-4.3.13.RELEASE.jar:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.13.RELEASE.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.13.RELEASE.jar:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.13.RELEASE.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.13.RELEASE.jar:na]
    at spring.web@4.3.13.RELEASE/org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.13.RELEASE.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar:na]
    at tomcat.embed.core@8.5.23/org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) [na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) [na:na]
    at tomcat.embed.core@8.5.23/org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar:na]
    at java.base/java.lang.Thread.run(Thread.java:844) [na:na]

2018-01-09 01:18:08.552  INFO 4656 --- [nio-8080-exec-2] c.e.s.controller.MessageController       : failed to send

My questions is, once it all becomes bytecode does it matter? Will there be bytecode in the Java 9 produced jar that the Java 8 JVM can't understand?

是的,JVM 运行ning Java 8 将无法 运行 Java 9 代码。否则你需要用 Java 8 编译它。

答案是肯定的。可以使用工具 javap 来查看,在 Java 8

$ javap -v Hello.class | grep "version"
  minor version: 0
  major version: 52

在 Java 9,你会看到

  minor version: 0
  major version: 53

但是,您可以使用编译器标志 -target-source 使 Java 9 编译器生成 Java 8 兼容代码。

$ javac -source 1.8 -target 1.8 Hello.java

但是,新的 incubator 可能还没有 backported 到 Java 1.8;在这种情况下,我建议最好的选择是使用 apache HttpComponents - 这对两者都有效。

这个问题有两个不同的组成部分。第一个问题是,正如其他人已经提到的,类文件包含版本标记,JVM 将拒绝 运行 任何版本号过高的类文件,这意味着 Java 8 个 JVM 将拒绝类文件包含 Java 9 版本代码(但是反过来完全没问题)。

更有趣的问题是,如果您手动将版本代码编辑为 Java8,您的代码是否会工作。在这种情况下,这取决于。在字节码级别,Java 9 中唯一显着的变化与模块和包有关。如果你不使用模块,你的代码应该仍然可以在 Java 8 上运行,假设它依赖的所有库在 Java 8 中也可用。

Java 9 还为模块添加了一些属性,但是这些对于 运行time 行为并不重要,除非使用反射并且 JVM 将忽略它无法识别的属性,所以这不会阻止您的代码从 运行ning under Java 8.

所以 tl;博士;如果您不使用模块,假设您修复了版本字节,那么您的代码应该在 Java 8 下工作。但是,当您可以将 -source-target 标志传递给 javac 来完成相同的事情时,这会带来很多麻烦。