Итак, я пытаюсь разработать приложение JLWGL в Scala и собрать его с помощью sbt. Проблема, с которой я сталкиваюсь, заключается в том, что мой каркасный проект работает на Linux, но не на macOS (происходит сбой с фатальной ошибкой JVM).
Единственное отличие между Linux и macOS-версией ссылка на нативные библиотеки (из lwjgl) в файле build.sbt. И на macOS, и на Linux я использую openjdk 13 (на Ma c уже пытался запустить его на 11 и 8 безуспешно).
Мой вопрос: как правильно отладить эту проблему? Это проблема в моем коде, jlwgl или JVM?
Для справки приведу некоторые исходящие и входные данные.
Неустранимая ошибка JVM
[info] Hello LWJGL 3.2.3 build 13!
[info] #
[info] # A fatal error has been detected by the Java Runtime Environment:
[info] #
[info] # SIGSEGV (0xb) at pc=0x00007fff2caab4a0, pid=11896, tid=775
[info] #
[info] # JRE version: OpenJDK Runtime Environment (13.0.2+8) (build 13.0.2+8)
[info] # Java VM: OpenJDK 64-Bit Server VM (13.0.2+8, mixed mode, sharing, tiered, compressed oops, g1 gc, bsd-amd64)
[info] # Problematic frame:
[info] # C [HIToolbox+0x274a0] THIThemeTextInfoFinder::GetOptions() const+0x8
[info] #
[info] # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
[info] #
[info] # An error report file with more information is saved as:
[info] # /<path to my project>/hs_err_pid11896.log
[info] #
[info] # If you would like to submit a bug report, please visit:
[info] # http://bugreport.java.com/bugreport/crash.jsp
Мой build.sbt
ThisBuild / scalaVersion := "2.13.1"
ThisBuild / version := "0.0.1"
fork := true
lazy val testlwjgl = (project in file("."))
.settings(
name := "TestLWJGL",
libraryDependencies ++= {
val version = "3.2.3"
val os = "macos" // TODO: Change to "windows", "linux" or "macos" if necessary
Seq(
"lwjgl",
"lwjgl-glfw",
"lwjgl-opengl"
// TODO: Add more modules here
).flatMap {
module => {
Seq(
"org.lwjgl" % module % version,
"org.lwjgl" % module % version classifier s"natives-$os"
)
}
}
}
)
Мой исходный код (scala файл)
package mypackagename
import org.lwjgl._
import org.lwjgl.glfw._
import org.lwjgl.opengl._
import org.lwjgl.system._
import java.nio._
import org.lwjgl.glfw.Callbacks._
import org.lwjgl.glfw.GLFW._
import org.lwjgl.opengl.GL11._
import org.lwjgl.system.MemoryStack._
import org.lwjgl.system.MemoryUtil._
object HelloWorld {
def main(args: Array[String]): Unit = {
new HelloWorld().run()
}
}
class HelloWorld { // The window handle
private var window = 0L
def run(): Unit = {
System.out.println("Hello LWJGL " + Version.getVersion + "!")
init()
loop()
// Free the window callbacks and destroy the window
glfwFreeCallbacks(window)
glfwDestroyWindow(window)
// Terminate GLFW and free the error callback
glfwTerminate
glfwSetErrorCallback(null).free
}
private def init(): Unit = { // Setup an error callback. The default implementation
// will print the error message in System.err.
GLFWErrorCallback.createPrint(System.err).set
// Initialize GLFW. Most GLFW functions will not work before doing this.
if (!glfwInit) throw new IllegalStateException("Unable to initialize GLFW")
// Configure GLFW
glfwDefaultWindowHints // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE) // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE) // the window will be resizable
// Create the window
window = glfwCreateWindow(300, 300, "Hello World!", NULL, NULL)
if (window == NULL) throw new RuntimeException("Failed to create the GLFW window")
// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, (window: Long, key: Int, scancode: Int, action: Int, mods: Int) => {
if ((key == GLFW_KEY_ESCAPE) && (action == GLFW_RELEASE)) {
glfwSetWindowShouldClose(window, true)
}
})
// Get the thread stack and push a new frame
try {
val stack = stackPush
try {
val pWidth = stack.mallocInt(1) // int*
val pHeight = stack.mallocInt(1)
// Get the window size passed to glfwCreateWindow
glfwGetWindowSize(window, pWidth, pHeight)
// Get the resolution of the primary monitor
val vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor)
// Center the window
glfwSetWindowPos(window, (vidmode.width - pWidth.get(0)) / 2, (vidmode.height - pHeight.get(0)) / 2)
} finally if (stack != null) stack.close()
} // the stack frame is popped automatically
// Make the OpenGL context current
glfwMakeContextCurrent(window)
// Enable v-sync
glfwSwapInterval(1)
// Make the window visible
glfwShowWindow(window)
}
private def loop(): Unit = { // This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities
// Set the clear color
glClearColor(1.0f, 0.0f, 0.0f, 0.0f)
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while ( {
!glfwWindowShouldClose(window)
}) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) // clear the framebuffer
glfwSwapBuffers(window) // swap the color buffers
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents
}
}
}