首页 > Java > 使用 JNR-FFI 将字符表输出到 CMD 屏幕缓冲区崩溃

使用 JNR-FFI 将字符表输出到 CMD 屏幕缓冲区崩溃

PHPz
发布: 2024-02-22 12:50:16
转载
880 人浏览过

php小编西瓜为您带来关于使用JNR-FFI在Java中将字符表输出到CMD屏幕缓冲区导致崩溃的问题。JNR-FFI是一个用于Java和本地代码交互的工具,但在处理字符表输出时可能会导致CMD屏幕缓冲区崩溃的情况。本文将为您解析这一问题的原因并提供解决方案,让您轻松解决这一技术难题。

问题内容

我正在尝试用 java 编写一个库,它将使用 c++ 代码来直接访问 cmd 中控制台屏幕缓冲区的写入。我已经成功打印了一次,但之后崩溃了,退出代码为 0xc0000005

我使用了 jnr-ffi 库。此代码现在打印出动画的第一帧,在 if 上暂停一秒钟并崩溃。

这是代码:

import jnr.ffi.libraryloader;
import jnr.ffi.pointer;

public class main {

    public interface kernel32 {
        kernel32 instance = libraryloader.create(kernel32.class).load("kernel32");

        int generic_read = 0x80000000;
        int generic_write = 0x40000000;
        int file_share_read = 0x00000001;
        int file_share_write = 0x00000002;
        int console_textmode_buffer = 1;

        pointer createconsolescreenbuffer(int dwdesiredaccess, int dwsharemode, pointer lpsecurityattributes, int dwflags, pointer lpscreenbufferdata);
        void setconsoleactivescreenbuffer(pointer hconsoleoutput);
        int writeconsoleoutputcharacterw(pointer hconsoleoutput, char[] lpcharacter, int nlength, int dwwritecoord, int lpnumberofcharswritten);
    }

    private static final int nscreenwidth = 240;
    private static final int nscreenheight = 135;

    static kernel32 kernel32 = kernel32.instance;

    private static pointer hconsole = kernel32.createconsolescreenbuffer(
            kernel32.generic_write | kernel32.generic_read,
            kernel32.file_share_read | kernel32.file_share_write,
            null,
            kernel32.console_textmode_buffer,
            null
    );

    public static void writecmd(char[] screen){
        try {
            if (screen.length == (nscreenwidth * nscreenheight) + 1) {
                int lpnumberofcharswritten = 0;
                system.out.println(kernel32.writeconsoleoutputcharacterw(hconsole, screen, (nscreenwidth * nscreenheight) + 1, 0, lpnumberofcharswritten));
            }
        } catch (exception t) {
            t.printstacktrace();
        }
    }

    public static void main(string[] args) {
        kernel32.setconsoleactivescreenbuffer(hconsole);

        char[] screen = new char[(nscreenwidth * nscreenheight) + 1];
        for (int i = 0; i < screen.length - 1; i++) {
            screen[i] = '-';
        }
        screen[screen.length - 1] = '\0';

        int position = 0;
        while(true){
            screen[position] = '#';
            writecmd(screen);
            screen[position] = '-';
            position++;
        }
    }
}
登录后复制

如上所述,在 cmd 中运行它会打印第一帧,冻结一秒钟并且毫无例外地崩溃,但在 intellij 控制台中运行它给了我退出代码“0xc0000005”,并在事件查看器中发现了这一点:

Faulting application name: java.exe, version: 20.0.2.0, time stamp: 0x75f7bb13
Faulting module name: KERNELBASE.dll, version: 10.0.22621.2715, time stamp: 0x10f6a783
Exception code: 0xc0000005
Fault offset: 0x00000000000b5bdc
Faulting process id: 0x0x5B98
Faulting application start time: 0x0x1DA1CB1377C8871
Faulting application path: C:\Program Files\Java\jdk-20\bin\java.exe
Faulting module path: C:\Windows\System32\KERNELBASE.dll
Report Id: 97a532d2-82fd-4b33-a399-ee74ea9e606d
Faulting package full name: 
Faulting package-relative application ID:
登录后复制

尝试用谷歌搜索,但没有找到任何我能理解的东西。有什么帮助吗?

解决方法

有人指出 WriteConsoleOutputCharacterW() 中的最后一个参数应该是指向 long var 而不是 int 的指针。

改变这个: int lpNumberOfCharsWritten = 0;“WroteCMD()”中的

对此: Pointer lpNumberOfCharsWritten = Runtime.getSystemRuntime().getMemoryManager().allocate( Runtime.getSystemRuntime().findType( TypeAlias.int32_t ).size() );

解决了这个问题。我使用 int 作为内存地址,在本例中尝试写入地址 0。

以上是使用 JNR-FFI 将字符表输出到 CMD 屏幕缓冲区崩溃的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:stackoverflow.com
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板