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

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

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

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

问题内容

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

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

这是代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

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”,并在事件查看器中发现了这一点:

1

2

3

4

5

6

7

8

9

10

11

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中文网其他相关文章!

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