From 091d49fc75336df88e34b95cb0cbad9b4a1a0f55 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 7 Oct 2024 12:02:10 -0700 Subject: [PATCH 1/2] Improve and document the JavaVirtualMachine initializer Add options for the class path (so clients don't need to re-learn how to spell it) and for telling the JVM whether to ignore unrecognized arguments. --- Sources/JavaKitVM/JavaVirtualMachine.swift | 30 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index d1cc97ec..117cca2b 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -23,19 +23,41 @@ public final class JavaVirtualMachine: @unchecked Sendable { /// The JNI environment for the JVM. public let environment: JNIEnvironment - public init(vmOptions: [String] = []) throws { + /// Initialize a new Java virtual machine instance. + /// + /// - Parameters: + /// - classPath: The directories, JAR files, and ZIP files in which the JVM + /// should look to find classes. This maps to the VM option + /// `-Djava.class.path=`. + /// - vmOptions: Options that should be passed along to the JVM, which will + /// be prefixed by the class-path argument described above. + /// - ignoreUnrecognized: Whether the JVM should ignore any VM options it + /// does not recognize. + public init( + classPath: [String] = [], + vmOptions: [String] = [], + ignoreUnrecognized: Bool = true + ) throws { var jvm: JavaVMPointer? = nil var environment: UnsafeMutableRawPointer? = nil var vmArgs = JavaVMInitArgs() vmArgs.version = JNI_VERSION_21 - vmArgs.ignoreUnrecognized = jboolean(JNI_TRUE) + vmArgs.ignoreUnrecognized = jboolean(ignoreUnrecognized ? JNI_TRUE : JNI_FALSE) + + // Construct the complete list of VM options. + var allVMOptions: [String] = [] + if !classPath.isEmpty { + let colonSeparatedClassPath = classPath.joined(separator: ":") + allVMOptions.append("-Djava.class.path=\(colonSeparatedClassPath)") + } + allVMOptions.append(contentsOf: vmOptions) // Convert the options - let optionsBuffer = UnsafeMutableBufferPointer.allocate(capacity: vmOptions.count) + let optionsBuffer = UnsafeMutableBufferPointer.allocate(capacity: allVMOptions.count) defer { optionsBuffer.deallocate() } - for (index, vmOption) in vmOptions.enumerated() { + for (index, vmOption) in allVMOptions.enumerated() { let optionString = vmOption.utf8CString.withUnsafeBufferPointer { buffer in let cString = UnsafeMutableBufferPointer.allocate(capacity: buffer.count + 1) _ = cString.initialize(from: buffer) From 7e7ad2a15b35e9ba1d74d88d3309e74519220b8d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 7 Oct 2024 12:03:55 -0700 Subject: [PATCH 2/2] Require only JNI version 1.6 Based on our uses of the JNI APIs, the JavaKit path (Swift wrapping Java classes) only requires JNI as of Java 1.6, far earlier than the JDK 21 we had previously required. --- Sources/JavaKitVM/JavaVirtualMachine.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index 117cca2b..5fc26940 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -41,7 +41,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { var jvm: JavaVMPointer? = nil var environment: UnsafeMutableRawPointer? = nil var vmArgs = JavaVMInitArgs() - vmArgs.version = JNI_VERSION_21 + vmArgs.version = JNI_VERSION_1_6 vmArgs.ignoreUnrecognized = jboolean(ignoreUnrecognized ? JNI_TRUE : JNI_FALSE) // Construct the complete list of VM options.