我有一种下面的方法已经运行了很长时间:
private String loadFromFile(){
RandomAccessFile inFile = null;
FileChannel inChannel = null;
StringBuilder sb = new StringBuilder();
try {
inFile = new RandomAccessFile(this.latestImageFile, "r");
inChannel = inFile.getChannel();
ByteBuffer bb = ByteBuffer.allocate(2046);
while( inChannel.read(bb) != -1){
bb.flip();
while(bb.hasRemaining()){
char c = (char) bb.get(); // read character at current position and set the pointer to current position + 1
sb.append(c);
}
bb.clear();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inChannel != null) try {inChannel.close(); } catch (IOException e){}
if (inFile != null ) try { inFile.close(); } catch (IOException e) {}
}
return sb.toString();
}
但是,今天,我已经在服务器上编译并运行了程序,启动程序时记录了以下异常。它显示未找到flip()方法:
Exception in thread "main" java.lang.NoSuchMethodError: java.nio.ByteBuffer.flip()Ljava/nio/ByteBuffer;
at com.rt.stream.s.exch.OBWorker.loadFromFile(OBWorker.java:271)
at com.rt.stream.s.exch.OBWorker.initAndLoadOBs(OBWorker.java:184)
at com.rt.stream.s.exch.OBWorker.<init>(OBWorker.java:145)
at com.rt.stream.s.exch.OBWorkerMgr.initFromProperties(OBWorkerMgr.java:217)
at com.rt.stream.s.exch.OBWorkerMgr.init(OBWorkerMgr.java:132)
at com.rt.stream.s.exch.OBWorkerMgr.main(OBWorkerMgr.java:511)
有人有什么想法吗?程序运行环境规范如下:
服务器:
发展:
IDE:版本:2019-09 R(4.13.0)
JDK:jdk-11.0.1
maven:apache-maven-3.3.3(应用以下配置)
<source>1.8</source>
<target>1.8</target>
经过一段时间搜索并通过在8和11之间切换已安装的JDK进行验证后,我发现ByteBuffer中的某些方法(例如flip(),clear())有一些更改(new overridden methods)
类。
在Java 8中,在调用ByteBuffer类的filp()
方法时,由于该方法没有实现,因此它实际上是从扩展类Buffer中调用该方法;正在返回Buffer
对象,如下所示:
在Buffer类中:
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
但是,在Java 11中,ByteBuffer类已经实现了自己的flip()方法,并且返回的对象从Buffer更改为ByteBuffer(此更改应从Java 9开始:]]
在ByteBuffer
类中:ByteBuffer flip() { super.flip(); return this; }
由于我使用的是JDK 11(更高的JDK版本)来编译要在Java 8上运行的程序,因此javadoc有时会遇到相应的异常:
但是,默认情况下,javac会针对最新版本的平台API。因此,编译后的程序可能会意外使用仅在平台的当前版本中可用的API。这样程序不能在平台的旧版本上运行,无论传递给-source和-target选项的值。这是一个长期可用性的痛点,因为用户期望通过使用这些选项,他们将获得可以在平台上运行的类文件-target指定的版本。
该语句可以在这里引用:http://openjdk.java.net/jeps/247
因此,为解决此类问题,有两种解决方法:
一个人可以通过使用新引入的命令行选项来处理编译期间:
i.e.
javac --release N <source files>
which is equals to:
for N < 9: -source N -target N -bootclasspath <documented-APIs-from-N>,
for N >= 9: -source N -target N --system <documented-APIs-from-N>.
或者我们可以在代码中作为预防措施来处理它,方法是在调用相应方法之前将ByteByffer显式转换为Buffer:
(((缓冲区)bb).flip();
为了强制它调用扩展类的方法(以防编译过程未考虑新的命令行选项):
private String loadFromFile(){
RandomAccessFile inFile = null;
FileChannel inChannel = null;
StringBuilder sb = new StringBuilder();
try {
inFile = new RandomAccessFile(this.latestImageFile, "r");
inChannel = inFile.getChannel();
ByteBuffer bb = ByteBuffer.allocate(2046);
while( inChannel.read(bb) != -1){
((Buffer)bb).flip(); // explicitly casting
while(bb.hasRemaining()){
char c = (char) bb.get();
sb.append(c);
}
((Buffer) bb).clear(); // explicitly casting
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inChannel != null) try {inChannel.close(); } catch (IOException e){}
if (inFile != null ) try { inFile.close(); } catch (IOException e) {}
}
return sb.toString();
}