Skip to content

Commit c85371f

Browse files
committed
Improve lookup of JavaClass instances in an environment
Teach the low-level getJNIClass API to properly check for Java exceptions and turn them into Swift errors. Then add a higher-level API `JavaClass.init(in:)` to look up a specific imported Java class within the given environment.
1 parent 39d76f8 commit c85371f

File tree

7 files changed

+34
-16
lines changed

7 files changed

+34
-16
lines changed

Sources/JavaKit/AnyJavaObject.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,12 @@ extension AnyJavaObject {
8181
}
8282

8383
/// Retrieve the Java class for this type.
84-
public static func getJNIClass(in environment: JNIEnvironment) -> jclass? {
85-
return environment.interface.FindClass(
86-
environment,
87-
fullJavaClassNameWithSlashes
88-
)
84+
public static func getJNIClass(in environment: JNIEnvironment) throws -> jclass {
85+
try environment.translatingJNIExceptions {
86+
environment.interface.FindClass(
87+
environment,
88+
fullJavaClassNameWithSlashes
89+
)
90+
}!
8991
}
9092
}

Sources/JavaKit/Exceptions/ExceptionHandling.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ extension JNIEnvironment {
4242
// Otherwise, create a exception with a message.
4343
_ = interface.ThrowNew(
4444
self,
45-
JavaClass<Exception>.getJNIClass(in: self),
45+
try! JavaClass<Exception>.getJNIClass(in: self),
4646
String(describing: error)
4747
)
4848
}

Sources/JavaKit/JavaClass.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,12 @@ import JavaRuntime
1717
/// Wrapper around a Java class that provides access to the static members of
1818
/// the class.
1919
@JavaClass("java.lang.Class")
20-
public struct JavaClass<ObjectType: AnyJavaObject> { }
20+
public struct JavaClass<ObjectType: AnyJavaObject> {
21+
/// Lookup this Java class within the given environment.
22+
public init(in environment: JNIEnvironment) throws {
23+
self.init(
24+
javaThis: try ObjectType.getJNIClass(in: environment),
25+
environment: environment
26+
)
27+
}
28+
}

Sources/JavaKit/JavaObject+Inheritance.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ extension AnyJavaObject {
2727
private func isInstanceOf<OtherClass: AnyJavaObject>(
2828
_ otherClass: OtherClass.Type
2929
) -> jclass? {
30-
guard let otherJavaClass = otherClass.getJNIClass(in: javaEnvironment) else {
30+
guard let otherJavaClass = try? otherClass.getJNIClass(in: javaEnvironment) else {
3131
return nil
3232
}
3333

Sources/JavaKit/JavaObject+MethodCalls.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ extension AnyJavaObject {
247247
in environment: JNIEnvironment,
248248
arguments: repeat each Param
249249
) throws -> Self {
250-
let thisClass = Self.getJNIClass(in: environment)!
250+
let thisClass = try Self.getJNIClass(in: environment)
251251

252252
// Compute the method signature so we can find the right method, then look up the
253253
// method within the class.

Sources/JavaKit/Optional+JavaObject.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ extension Optional: JavaValue where Wrapped: AnyJavaObject {
7070

7171
public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray {
7272
return { environment, size in
73-
let jniClass = Wrapped.getJNIClass(in: environment)
73+
let jniClass = try! Wrapped.getJNIClass(in: environment)
7474
return environment.interface.NewObjectArray(environment, size, jniClass, nil)
7575
}
7676
}

Tests/JavaKitTests/BasicRuntimeTests.swift

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,24 @@ struct BasicRuntimeTests {
5959
}
6060

6161
@Test("Static methods")
62-
func staticMethods() {
63-
let urlConnectionClass = JavaClass<URLConnection>(
64-
javaThis: URLConnection.getJNIClass(in: jvm.environment)!,
65-
environment: jvm.environment
66-
)
67-
62+
func staticMethods() throws {
63+
let urlConnectionClass = try JavaClass<URLConnection>(in: jvm.environment)
6864
#expect(urlConnectionClass.getDefaultAllowUserInteraction() == false)
6965
}
66+
67+
@Test("Class instance lookup")
68+
func classInstanceLookup() throws {
69+
do {
70+
_ = try JavaClass<Nonexistent>(in: jvm.environment)
71+
} catch {
72+
#expect(String(describing: error) == "org/swift/javakit/Nonexistent")
73+
}
74+
}
7075
}
7176

77+
@JavaClass("org.swift.javakit.Nonexistent")
78+
struct Nonexistent { }
79+
7280
/// Whether we're running on Linux.
7381
var isLinux: Bool {
7482
#if os(Linux)

0 commit comments

Comments
 (0)