假设我使用的是Java 11javac
,但是我使用的--source
和--target
选项设置为1.8
,这样我的源代码将被视为Java 8,输出的.class
文件将与Java 8兼容。我的目标是生成能够在Java8 JVM上运行的.class
文件。
假设我正在编译的Java8代码如下:
import java.nio.ByteBuffer;
…
ByteBuffer byteBuffer = …; //init somehow
byteBuffer.flip(); //what ends up in the `.class` file?
问题是:Java11javac
应该在.class
文件中放入什么来链接ByteBuffer.flip()
方法调用?在回答之前,请考虑以下内容:
ByteBuffer
nor Java 11 ByteBuffer
declare the flip()
method at the ByteBuffer
level.ByteBuffer
is a direct subclass of Buffer
. There is both a Java 8 Buffer.flip()
and a Java 11 Buffer.flip()
declared in the Buffer
API for both versions.ByteBuffer.flip()
method.ByteBuffer
overrides the Buffer.flip()
method like the following. The purpose apparently was to use covariance so that in Java 11 ByteBuffer.flip()
would conveniently return a ByteBuffer
instead of a Buffer
. @Override
public ByteBuffer flip() {
super.flip();
return this;
}
因此,为了重申这个问题:将--source
和--target
选项设置为1.8
的Java11javac
是否应该生成一个链接到buffer.flip()
或bytebuffer.flip()
的.class
文件?如果是前者,那么它怎么知道不包含ByteBuffer.Flip()
,因为(Java8)代码清楚地引用了ByteBuffer.Flip()
,而(Java11)编译器看到运行库中有一个ByteBuffer.Flip()
方法呢?但如果是后者,那么我如何知道,即使我使用--source
和--target
选项指示Java8,在使用Java11编译时,100%正确的兼容Java8的源代码将在Java8 JRE上运行?(请注意,OpenJDK11.0.5似乎选择了后一个选项。但哪一个是正确的呢?)
(请注意,我使用的“链接”这个词很松散;我目前对字节码的生成还不是很熟悉。我所知道的是,类文件以某种方式引用了buffer.flip()
或bytebuffer.flip()
;如果在运行时找不到这个方法,JVM将抛出一个异常,例如:java.lang.NoSuchMethoderRor:java.nio.bytebuffer.flip()Ljava/nio/bytebuffer;
。)
作为一个额外的问题,我想知道使用为Java8设置的--release
选项是否会改变答案。但是请注意,我不能使用--release
选项(相当于Maven
编译器插件选项),因为我希望Maven项目能够同时使用Java8和Java11构建。
如果我们使用下面的代码并使用Java8和Java11进行编译,就会得到以下字节码,正如运行javap-c myclass.class
时看到的那样。
Java源代码
ByteBuffer byteBuffer = ByteBuffer.allocate(64);
byteBuffer.flip();
Java 8字节码
0: bipush 64
2: invokestatic #19 // Method java/nio/ByteBuffer.allocate:(I)Ljava/nio/ByteBuffer;
5: astore_1
6: aload_1
7: invokevirtual #25 // Method java/nio/ByteBuffer.flip:()Ljava/nio/Buffer;
10: pop
0: bipush 64
2: invokestatic #19 // Method java/nio/ByteBuffer.allocate:(I)Ljava/nio/ByteBuffer;
5: astore_1
6: aload_1
7: invokevirtual #25 // Method java/nio/ByteBuffer.flip:()Ljava/nio/ByteBuffer;
10: pop
但是,在字节码级别,方法签名包括返回类型。这意味着JVM支持可以重载仅在返回类型上不同的方法的语言,尽管Java不支持这一点。
Java11版本的方法具有不同的返回类型,这可以在“链接”方法中看到,位于()
之后,其中Java8将返回类型显示为LJava/NIO/Buffer;
,Java11将返回类型显示为LJava/NIO/ByteBuffer;
。
当您使用针对Java11运行时库编译的代码,并尝试在Java8上运行它时,线程“main”Java.lang.NoSuchMethoderRror中出现异常:Java.nio.byteBuffer.flip()ljava/nio/byteBuffer;
这就是为什么您应该始终指定引导类路径以指向与目标Java版本匹配的Java运行时库的原因。当您使用Java11的javac
和选项-source8-target8
进行编译时,它实际上会警告您这一点:
warning: [options] bootstrap class path not set in conjunction with -source 8
1 warning
这就是为什么他们实现了较新的--release
选项来替换-source
和-target
。如果您使用--release8
进行编译,则生成的.class
文件将在Java 8上运行,不会出错。
更新
--release
选项是在Java9中实现的,这是JEP 247:Compile for Older Platform版本的结果,它说:
对于JDK N和--release
M,M
ct.sym
文件是一个ZIP文件,包含与目标平台版本中的类文件相对应的剥离类文件。
我找到了这本在线图书本体http://www.ebusiness-unibw.org/ontologies/opdm/Book.html# RDF转储可以在这里找到 http://eelst.cs.unibo.it/apps/lode/source?url=http://www.ebusiness-unibw.org/ontologies/opdm/book_example.owl 我试图通过RD
我正在尝试将后端项目myonlinebackend与前端项目myonlineshopping链接起来,在添加“private session factory session factory;”之前,它工作得很好去CategoryDAOImpl.java。但是在声明了sessionFactory变量之后,我得到了下面这个错误。 这是我的课程: 类别.java CategoryDAOImpl.java
问题内容: 下一行将从指定的变量下载图像文件: 这些行将获取该图像并将其保存到MongoDB GridFS: 像这样的链接将引发 错误:500 Cannot Pipe。 不可管道。 发生这种情况是因为尚未准备好读取图像文件,对吗?我该怎么办才能解决此问题?错误:500无法管道。不可管道。 使用下面的: Node.js的0.10.10 , 猫鼬 , 要求 和 GridFS的流 库。 问题答案: 与此
本文向大家介绍如何更改HTML中的链接目标?,包括了如何更改HTML中的链接目标?的使用技巧和注意事项,需要的朋友参考一下 要更改HTML中链接的目标,请使用<a>…</a>标记的target属性。target属性可用于打开新选项卡或相同选项卡等中的任何链接。 以下是target属性的值: 属性 描述 _空白 在新选项卡中打开链接的页面。 自 在当前选项卡中打开链接的页面。 父母 在父框架中打开链
我目前的设置是这样的。
为什么上面的代码有编译错误“java:default method equals in interface Table重写java.lang.Object的一个成员”?难道我们不能使用接口默认方法重写hashCode和equals方法吗?假设我在同一个接口中有方法来确定实现这个接口的对象的相等性?