Skip to content

Commit 38b3987

Browse files
committed
Require pre-parsed JNI signatures
JNI signatures are now expected to be pre-parsed into a MethodSignature or FieldSignature before being used to make method calls or get/set fields. In the common case the `jni_sig!()` macro can be used to parse a JNI signature at compile time and emit the appropriate `*Signature` struct. In the unlikely case that a signature needs to be parsed at runtime then `RuntimeMethodSignature/RuntimeFieldSignature::from_str` can be used and it's then possible to borrow a `MethodSignature` or `FieldSignature` from these runtime structs.
1 parent 33345cd commit 38b3987

21 files changed

+679
-342
lines changed

jni-macros/src/bind_java_type.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,7 +2044,6 @@ fn generate_id_fields_and_inits(
20442044

20452045
// Create CStr literals for both the name and signature
20462046
let name_cstr = lit_cstr_mutf8(java_name);
2047-
let sig_cstr = lit_cstr_mutf8(signature);
20482047

20492048
// Add field to API struct
20502049
fields.push(quote! {
@@ -2053,7 +2052,7 @@ fn generate_id_fields_and_inits(
20532052

20542053
// Add initialization
20552054
inits.push(quote! {
2056-
#field_name: env.#lookup_fn(class, #jni::strings::JNIStr::from_cstr_unchecked(#name_cstr), #jni::strings::JNIStr::from_cstr_unchecked(#sig_cstr))?,
2055+
#field_name: env.#lookup_fn(class, #jni::strings::JNIStr::from_cstr_unchecked(#name_cstr), #jni::jni_sig!(jni=#jni, #signature))?,
20572056
});
20582057
}
20592058

@@ -3918,7 +3917,6 @@ fn generate_native_registration_code(
39183917

39193918
// Create CStr literals for name and signature
39203919
let name_cstr = lit_cstr_mutf8(java_name);
3921-
let sig_cstr = lit_cstr_mutf8(&jni_signature);
39223920

39233921
// Always use the generated wrapper function (even for raw_fn)
39243922
// This ensures type checking and allows exports to work
@@ -3928,7 +3926,7 @@ fn generate_native_registration_code(
39283926
native_method_descriptors.push(quote! {
39293927
#jni::NativeMethod {
39303928
name: #jni::strings::JNIStr::from_cstr_unchecked(#name_cstr),
3931-
sig: #jni::strings::JNIStr::from_cstr_unchecked(#sig_cstr),
3929+
sig: #jni::jni_sig!(jni=#jni, #jni_signature),
39323930
fn_ptr: #fn_ptr,
39333931
}
39343932
});

src/descriptors/exception_desc.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::{
33
env::Env,
44
errors::*,
55
objects::{Auto, IntoAuto as _, JClass, JObject, JString, JThrowable, JValue},
6+
signature::{JavaType, MethodSignature, Primitive},
67
strings::{JNIStr, JNIString},
78
};
89

@@ -17,8 +18,16 @@ where
1718

1819
fn lookup(self, env: &mut Env<'local>) -> Result<Self::Output> {
1920
let jmsg = JString::from_jni_str(env, self.1.as_ref())?.auto();
20-
let obj: JObject =
21-
env.new_object(self.0, c"(Ljava/lang/String;)V", &[JValue::from(&jmsg)])?;
21+
let ctor_args = &[JavaType::Object];
22+
// Safety: We are sure the arguments and return type are consistent with the signature string.
23+
let ctor_sig = unsafe {
24+
MethodSignature::from_raw_parts(
25+
JNIStr::from_cstr(c"(Ljava/lang/String;)V"),
26+
ctor_args,
27+
JavaType::Primitive(Primitive::Void),
28+
)
29+
};
30+
let obj: JObject = env.new_object(self.0, &ctor_sig, &[JValue::from(&jmsg)])?;
2231
let throwable = env.cast_local::<JThrowable>(obj)?;
2332
Ok(throwable.auto())
2433
}

src/descriptors/field_desc.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ use crate::{
33
env::Env,
44
errors::*,
55
objects::{JClass, JFieldID, JStaticFieldID},
6+
signature::FieldSignature,
67
strings::JNIStr,
78
};
89

9-
unsafe impl<'local, 'other_local, T, U, V> Desc<'local, JFieldID> for (T, U, V)
10+
unsafe impl<'local, 'other_local, 'sig, T, U, V> Desc<'local, JFieldID> for (T, U, V)
1011
where
1112
T: Desc<'local, JClass<'other_local>>,
1213
U: AsRef<JNIStr>,
13-
V: AsRef<JNIStr>,
14+
V: AsRef<FieldSignature<'sig>>,
1415
{
1516
type Output = JFieldID;
1617

@@ -19,11 +20,11 @@ where
1920
}
2021
}
2122

22-
unsafe impl<'local, 'other_local, T, U, V> Desc<'local, JStaticFieldID> for (T, U, V)
23+
unsafe impl<'local, 'other_local, 'sig, T, U, V> Desc<'local, JStaticFieldID> for (T, U, V)
2324
where
2425
T: Desc<'local, JClass<'other_local>>,
2526
U: AsRef<JNIStr>,
26-
V: AsRef<JNIStr>,
27+
V: AsRef<FieldSignature<'sig>>,
2728
{
2829
type Output = JStaticFieldID;
2930

src/descriptors/method_desc.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ use crate::{
33
env::Env,
44
errors::*,
55
objects::{JClass, JMethodID, JStaticMethodID},
6+
signature::MethodSignature,
67
strings::JNIStr,
78
};
89

9-
unsafe impl<'local, 'other_local, T, U, V> Desc<'local, JMethodID> for (T, U, V)
10+
unsafe impl<'local, 'other_local, 'sig, 'sig_args, T, U, V> Desc<'local, JMethodID> for (T, U, V)
1011
where
1112
T: Desc<'local, JClass<'other_local>>,
1213
U: AsRef<JNIStr>,
13-
V: AsRef<JNIStr>,
14+
V: AsRef<MethodSignature<'sig, 'sig_args>>,
1415
{
1516
type Output = JMethodID;
1617

@@ -19,10 +20,11 @@ where
1920
}
2021
}
2122

22-
unsafe impl<'local, 'other_local, T, Signature> Desc<'local, JMethodID> for (T, Signature)
23+
unsafe impl<'local, 'other_local, 'sig, 'sig_args, T, Signature> Desc<'local, JMethodID>
24+
for (T, Signature)
2325
where
2426
T: Desc<'local, JClass<'other_local>>,
25-
Signature: AsRef<JNIStr>,
27+
Signature: AsRef<MethodSignature<'sig, 'sig_args>>,
2628
{
2729
type Output = JMethodID;
2830

@@ -31,11 +33,12 @@ where
3133
}
3234
}
3335

34-
unsafe impl<'local, 'other_local, T, U, V> Desc<'local, JStaticMethodID> for (T, U, V)
36+
unsafe impl<'local, 'other_local, 'sig, 'sig_args, T, U, V> Desc<'local, JStaticMethodID>
37+
for (T, U, V)
3538
where
3639
T: Desc<'local, JClass<'other_local>>,
3740
U: AsRef<JNIStr>,
38-
V: AsRef<JNIStr>,
41+
V: AsRef<MethodSignature<'sig, 'sig_args>>,
3942
{
4043
type Output = JStaticMethodID;
4144

0 commit comments

Comments
 (0)