线程“main"中的异常java.lang.NoSuchMethodError: java.nio.ByteBuffer.flip()Ljava/nio/ByteBuffer [英] Exception in thread "main" java.lang.NoSuchMethodError: java.nio.ByteBuffer.flip()Ljava/nio/ByteBuffer

查看:92
本文介绍了线程“main"中的异常java.lang.NoSuchMethodError: java.nio.ByteBuffer.flip()Ljava/nio/ByteBuffer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个方法如下,它已经运行了很长时间:

private String loadFromFile(){RandomAccessFile inFile = null;FileChannel inChannel = null;StringBuilder sb = new StringBuilder();尝试 {inFile = new RandomAccessFile(this.latestImageFile, "r");inChannel = inFile.getChannel();ByteBuffer bb = ByteBuffer.allocate(2046);while( inChannel.read(bb) != -1){bb.flip();而(bb.hasRemaining()){char c = (char) bb.get();//在当前位置读取字符并将指针设置为当前位置 + 1sb.append(c);}bb.clear();}} catch (IOException e) {e.printStackTrace();} 最后 {如果 (inChannel != null) 尝试 {inChannel.close();} catch (IOException e){}if (inFile != null ) try { inFile.close();} catch (IOException e) {}}返回 sb.toString();}

然而,今天我在服务器上编译并运行程序后,启动程序时记录了以下异常.它显示未找到 flip() 方法:

线程main"中的异常 java.lang.NoSuchMethodError: java.nio.ByteBuffer.flip()Ljava/nio/ByteBuffer;在 com.rt.stream.s.exch.OBWorker.loadFromFile(OBWorker.java:271)在 com.rt.stream.s.exch.OBWorker.initAndLoadOBs(OBWorker.java:184)在 com.rt.stream.s.exch.OBWorker.(OBWorker.java:145)在 com.rt.stream.s.exch.OBWorkerMgr.initFromProperties(OBWorkerMgr.java:217)在 com.rt.stream.s.exch.OBWorkerMgr.init(OBWorkerMgr.java:132)在 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(应用以下配置)

 1.8<目标>1.8</目标>

解决方案

搜索了一段时间,通过在 8 和 11 之间切换安装的 JDK 验证,我发现有一些变化 (new overridden methods) 应用于 ByteBuffer 类中的几个方法(例如 flip(), clear() ).

在Java 8中,调用ByteBuffer类的flip()方法时,由于没有实现该方法,所以实际上是从扩展类Buffer调用该方法;返回 Buffer 对象如下:

Buffer 类中:

public final Buffer flip() {限制=位置;位置 = 0;标记 = -1;返回这个;}

但是在Java 11中,ByteBuffer类已经实现了自己的flip()方法,并且返回的对象从Buffer变成了ByteBuffer(这个变化应该从Java 9开始):

ByteBuffer 类中:

ByteBuffer 翻转() {超级翻转();返回这个;}


由于我使用 JDK 11(更高的 JDK 版本)来编译程序以在 Java 8 上运行,因此偶尔会遇到与 javadoc 相应的上述异常:<块引用>

然而,默认情况下,javac 会针对最新版本的平台 API.因此编译后的程序可能会意外使用API 仅在当前版本的平台中可用.这样的程序不能在旧版本的平台上运行,无论传递给 -source 和 -target 选项的值.这是一个长期可用性痛点,因为用户期望通过使用这些选项,他们将获得可以在平台上运行的类文件-target 指定的版本.

该声明可以在这里引用:http://openjdk.java.net/jeps/247



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


方法一

通过使用新引入的命令行选项,可以在编译期间进行处理:

 即javac --release N <源文件>这等于:对于 N <9: -source N -target N -bootclasspath ,对于 N >= 9:-source N -target N --system .


方法 2

或者我们可以在代码中处理它,作为预防方法,通过在调用相应方法之前显式地将 ByteByffer 转换为 Buffer :

<块引用>

((缓冲区) bb).flip();

为了强制它调用扩展类的方法(以防编译过程没有考虑新的命令行选项):

private String loadFromFile(){RandomAccessFile inFile = null;FileChannel inChannel = null;StringBuilder sb = new StringBuilder();尝试 {inFile = new RandomAccessFile(this.latestImageFile, "r");inChannel = inFile.getChannel();ByteBuffer bb = ByteBuffer.allocate(2046);while( inChannel.read(bb) != -1){((缓冲区)bb).翻转();//显式转换而(bb.hasRemaining()){char c = (char) bb.get();sb.append(c);}((缓冲区) bb).clear();//显式转换}} catch (IOException e) {e.printStackTrace();} 最后 {如果 (inChannel != null) 尝试 {inChannel.close();} catch (IOException e){}if (inFile != null ) try { inFile.close();} catch (IOException e) {}}返回 sb.toString();}

I have a method as of below which has been running properly for a long time:

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();
}

However, today after I have compiled and run the program on a server, below exception was logged when starting the program. It shows a flip() method is not found:

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)

Anybody has any idea on it please?

The program running environment specification is like this:

Server:

  1. openjdk version "1.8.0_242"

Development:

  1. IDE: Version: 2019-09 R (4.13.0)

  2. JDK: jdk-11.0.1

  3. maven: apache-maven-3.3.3 (with below configuration applied)

   <source>1.8</source>   
   <target>1.8</target>

解决方案

After searching for a while and verified through switching the installed JDK between 8 and 11, I have found that there are some changes (new overridden methods) applied to several methods (e.g. flip(), clear() ) in ByteBuffer class.

In Java 8, while calling flip() method of ByteBuffer class, since it has no implementation for this method, so it is actually calling the method from extended class, Buffer; which is returning Buffer object as below:

In Buffer class:

public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
}

However, in Java 11, ByteBuffer class has implemented its own flip() method, and the returning object is changed from Buffer to ByteBuffer (This change should be started from Java 9):

In ByteBuffer class:

ByteBuffer flip() {
    super.flip();
    return this;
}


Since I'm using JDK 11 (higher JDK version) to compile the program for running on Java 8, the mentioned exception would occasionally encountered accordingly to javadoc:

By default, however, javac compiles against the most-recent version of the platform APIs. The compiled program can therefore accidentally use APIs only available in the current version of the platform. Such programs cannot run on older versions of the platform, regardless of the values passed to the -source and -target options. This is a long-term usability pain point, since users expect that by using these options they'll get class files that can run on the the platform version specified by -target.

The statement could be referenced here: http://openjdk.java.net/jeps/247



So, for resolving this kind of problems, the are 2 ways to do so:


Approach 1

One can handle in the duration of compilation, by making use of a newly introduced command-line option:

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


Approach 2

Or we can handle it in codes, as precaution methods, by explicitly casting the ByteByffer as Buffer before calling corresponding methods:

((Buffer) bb).flip();

which in order to force it calling extended class's method (in case the compilation process hasn't taken the new command-line options into consideration):

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();
}

这篇关于线程“main"中的异常java.lang.NoSuchMethodError: java.nio.ByteBuffer.flip()Ljava/nio/ByteBuffer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆