jvm崩溃

isr3a4wc  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(336)

我和我的一个朋友正在用lwjgl制作一个3d引擎,在尝试将一个浮点数组作为统一的片段着色器传递给我之后,jvm开始崩溃。以下是jvm崩溃日志的相关部分:

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  org.lwjgl.opengl.GL20C.nglUniform1fv(IIJ)V+0
j  org.lwjgl.opengl.GL20C.glUniform1fv(ILjava/nio/FloatBuffer;)V+9
j  org.lwjgl.opengl.GL20.glUniform1fv(ILjava/nio/FloatBuffer;)V+2
j  com.alyxferrari.neo3d.obj.Environment3D.rebuildLights()V+118
j  com.alyxferrari.neo3d.gfx.NEOEngine.startRender()V+69
j  com.alyxferrari.neo3d.example.NEOExample.main([Ljava/lang/String;)V+65
v  ~StubRoutines::call_stub

由此,我明显地认为问题源于在这个方法中分配float[]值:

public void rebuildLights() {
        float[] xs = new float[DirectionalLight.MAX_IN_SHADER];
        float[] ys = new float[DirectionalLight.MAX_IN_SHADER];
        float[] zs = new float[DirectionalLight.MAX_IN_SHADER];
        float[] strengths = new float[DirectionalLight.MAX_IN_SHADER];
        for (int i = 0; i < lights.length; i++) {
            xs[i] = lights[i].getDirection().x;
            ys[i] = lights[i].getDirection().y;
            zs[i] = lights[i].getDirection().z;
            strengths[i] = lights[i].getStrength();
        }
        glUniform1fv(glGetUniformLocation(NEOEngine.getShader(), "lightXs"), FloatBuffer.wrap(xs));
        glUniform1fv(glGetUniformLocation(NEOEngine.getShader(), "lightYs"), FloatBuffer.wrap(ys));
        glUniform1fv(glGetUniformLocation(NEOEngine.getShader(), "lightZs"), FloatBuffer.wrap(zs));
        glUniform1fv(glGetUniformLocation(NEOEngine.getShader(), "strengths"), FloatBuffer.wrap(strengths));
        glUniform1f(glGetUniformLocation(NEOEngine.getShader(), "ambience"), ambience);
        glUniform1i(glGetUniformLocation(NEOEngine.getShader(), "count"), lights.length);
    }

如您所见,我正在基于灯光对象中的数据填充一些数组,并将它们 Package 在floatbuffer中以传递给gluniform1fv()。我唯一能想到的是,这也许不是我应该做的。当我在lwjgl中看到gluniform1fv()采用floatbuffer而不是float[]时,我查看了java的floatbuffer类文档,发现floatbuffer.wrap(float[])似乎是从float[]生成floatbuffer的好方法。对于lwjgl的opengl绑定,有没有一种特定的方法来实现它?还是我的代码有什么问题?提前感谢:)

ekqde3dh

ekqde3dh1#

lwjgl只适用于直接nio缓冲区,即不受堆内java数组支持的bytebuffers,而是由jvm进程中分配的堆外虚拟内存支持的bytebuffers,但在jvm管理的垃圾收集堆之外。这是为了有效地将本机虚拟内存与低级库(如opengl)进行通信,而不必在将指向它的指针交给本机库之前“固定”潜在的垃圾可回收/可移动内存。
请参阅中的“直接缓冲区与非直接缓冲区”一节https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/nio/bytebuffer.html
崩溃的原因是您提供的非直接bytebuffer(由.wrap(array)创建的bytebuffer)的内部地址字段值为0。这就是lwjgl在实际调用本机opengl函数时所看到的。它读取地址字段值,并期望这是要上载到uniform的客户机内存的虚拟内存地址,opengl会将其视为uniform。
因此,在本质上:当您使用lwjgl时,您必须始终只使用直接nio缓冲区,而不是数组的 Package 器!
您应该首先阅读lwjgl 3的这篇关于lwjgl 3中高效内存管理的博文:https://blog.lwjgl.org/memory-management-in-lwjgl-3/

相关问题