线程“主”中的异常java.lang.NoSuchMethodError:java.nio.ByteBuffer.flip()Ljava / nio / ByteBuffer

问题描述 投票:2回答:1

我有一种下面的方法已经运行了很长时间:

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)

有人有什么想法吗?程序运行环境规范如下:

服务器:

  1. openjdk版本“ 1.8.0_242”

发展:

  1. IDE:版本:2019-09 R(4.13.0)

  2. JDK:jdk-11.0.1

  3. maven:apache-maven-3.3.3(应用以下配置)

   <source>1.8</source>   
   <target>1.8</target>
java java-8 java-11 bytebuffer
1个回答
3
投票

经过一段时间搜索并通过在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


因此,为解决此类问题,有两种解决方法:

方法1

一个人可以通过使用新引入的命令行选项来处理编译期间:

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>.  

方法2

或者我们可以在代码中作为预防措施来处理它,方法是在调用相应方法之前将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();
}
© www.soinside.com 2019 - 2024. All rights reserved.