1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #![allow(unsafe_code)]
16
17 use jni::{
18 descriptors::Desc,
19 objects::JObject,
20 signature::{JavaType, Primitive, ReturnType},
21 JavaVM,
22 };
23 use std::error::Error;
24
25 mod common;
26 use common::foo_class::*;
27
28 #[test]
jni_access() -> Result<(), Box<dyn Error>>29 fn jni_access() -> Result<(), Box<dyn Error>> {
30 // Create the environment
31 let vm = JavaVM::new(
32 jni::InitArgsBuilder::new()
33 .version(jni::JNIVersion::V8)
34 .option("-Xcheck:jni")
35 .build()?,
36 )?;
37 let mut env = vm.attach_current_thread()?;
38
39 // Load `Foo.class`
40 {
41 let foo_class = compile_foo()?;
42 let loaded_foo = env.define_class(CLASS_DESC, &JObject::null(), &foo_class)?;
43 let loaded_foo = env.auto_local(loaded_foo);
44
45 let found_foo = FOO.lookup(&mut env)?;
46 assert!(env.is_same_object(&loaded_foo, found_foo.as_ref())?);
47 }
48
49 // Verify we can call the constructor
50 let obj_foo = {
51 let method_id = CONSTRUCTOR.lookup(&mut env)?;
52 let args = &[jni::sys::jvalue { i: 123 }];
53 // Safety: `args` must match the constructor arg count and types.
54 unsafe { env.new_object_unchecked(CONSTRUCTOR.cls(), method_id, args) }?
55 };
56 assert!(env.is_instance_of(&obj_foo, &FOO)?);
57
58 // Verify we can access all of the members
59
60 let field_value = {
61 env.get_field_unchecked(&obj_foo, &FIELD, ReturnType::Primitive(Primitive::Int))?
62 .i()?
63 };
64 assert_eq!(123, field_value);
65
66 let method_value = {
67 let method_id = METHOD.lookup(&mut env)?;
68 let args = &[];
69 // Safety: `args` must match the method arg count and types.
70 unsafe {
71 env.call_method_unchecked(
72 &obj_foo,
73 method_id,
74 ReturnType::Primitive(Primitive::Boolean),
75 args,
76 )
77 }?
78 .z()?
79 };
80 assert!(method_value);
81
82 env.delete_local_ref(obj_foo)?;
83
84 let static_field_value = {
85 env.get_static_field_unchecked(&FOO, &STATIC_FIELD, JavaType::Primitive(Primitive::Long))?
86 .j()?
87 };
88 assert_eq!(321, static_field_value);
89
90 let static_method_value = {
91 let method_id = STATIC_METHOD.lookup(&mut env)?;
92 let args = &[];
93 // Safety: `args` must match the method arg count and types.
94 unsafe {
95 env.call_static_method_unchecked(
96 &FOO,
97 method_id,
98 ReturnType::Primitive(Primitive::Int),
99 args,
100 )
101 }?
102 .i()?
103 };
104 assert_eq!(3, static_method_value);
105
106 Ok(())
107 }
108