• 【Java学习】调用ByteBuffer.getInt()方法得到808464432


    调用ByteBuffer.getInt()方法遇到的奇怪错误

    最近在参加阿里的中间件比赛,中间用到了RocketMQ的思想,并且主要集中在使用NIO来读写文件。其中遇到了一个很蛋疼的问题,想了半天想不出来为什么,现已解决并来记录一下。

    先上代码:

    @Test
    public void test() throws IOException {
        FileChannel fc = new RandomAccessFile(STORE_PATH, "rw").getChannel();
        ByteBuffer byteBuffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
        int a = byteBuffer.getInt();
        System.out.println(a);
    }
    

    代码主要使用了Java NIO中的FileChannel和ByteBuffer,目的是读取文件中的四个字节,并将其转为int类型的数字,对于这个文件我手动输入了四个'0',按照我的想法,读出来应该还是会为0。然而结果却如下:

    808464432
    

    这是个什么鬼?试了几次都是一样的数字,觉得很奇怪,为什么不是0呢。看了下ByteBuffer.getInt()的源码,发现ByteBuffer是一个抽象类,该方法有两种实现方式,分别是DirectByteBuffer和HeapByteBuffer,其中NIO使用的DirectByteBuffer,所以看下源码:

    private int getInt(long a) {
        if (unaligned) {
            int x = unsafe.getInt(a);
            return (nativeByteOrder ? x : Bits.swap(x));
        }
        return Bits.getInt(a, bigEndian);
    }
    
    public int getInt() {
        return getInt(ix(nextGetIndex((1 << 2))));
    }
    

    其中调用的是Unsafe包下的getInt()的native方法,好像又遇到死胡同了。

    最后没招了,突发奇想搜了一下808464432这个数字,搜到
    int变量的值为808464432 是为什么?内存越界?被赋错值?这篇博客,其中的一段话很明确的解释了原因:

    808464432,是10进制数,转换为16进制是0x30303030,0x30是字符'0'的ASCII码的16进制表示,也就是说,808464432这个数字,对应字符串“0000”,一个int变量,占4个字节,如果每个字节都写入一个字符'0',那么就会是这个数。

    原来是因为我输入的时候是以字符形式输入到文件,稍微修改一下代码,果然就好了,代码和结果如下:

    @Test
    public void test() throws IOException {
        FileChannel fc = new RandomAccessFile(STORE_PATH, "rw").getChannel();
        ByteBuffer byteBuffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
        byteBuffer.putInt(0,1);
        int a = byteBuffer.getInt();
        System.out.println(a);
    }
    

  • 相关阅读:
    RavenScheme简介
    我终于理解了LISP『代码即数据|数据即代码』的含义
    汉编随想(一)
    SICP的一些练习题
    linux下Script小计
    vscode小计
    软硬连接区别
    find过滤大小执行操作
    pyqt5和qt designer安装
    pyenv和virtualenv结合使用管理多python环境
  • 原文地址:https://www.cnblogs.com/puyangsky/p/6818171.html
Copyright © 2020-2023  润新知