// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #![allow(unsafe_code)] use jni::{ descriptors::Desc, objects::JObject, signature::{JavaType, Primitive, ReturnType}, JavaVM, }; use std::error::Error; mod common; use common::foo_class::*; #[test] fn jni_access() -> Result<(), Box> { // Create the environment let vm = JavaVM::new( jni::InitArgsBuilder::new() .version(jni::JNIVersion::V8) .option("-Xcheck:jni") .build()?, )?; let mut env = vm.attach_current_thread()?; // Load `Foo.class` { let foo_class = compile_foo()?; let loaded_foo = env.define_class(CLASS_DESC, &JObject::null(), &foo_class)?; let loaded_foo = env.auto_local(loaded_foo); let found_foo = FOO.lookup(&mut env)?; assert!(env.is_same_object(&loaded_foo, found_foo.as_ref())?); } // Verify we can call the constructor let obj_foo = { let method_id = CONSTRUCTOR.lookup(&mut env)?; let args = &[jni::sys::jvalue { i: 123 }]; // Safety: `args` must match the constructor arg count and types. unsafe { env.new_object_unchecked(CONSTRUCTOR.cls(), method_id, args) }? }; assert!(env.is_instance_of(&obj_foo, &FOO)?); // Verify we can access all of the members let field_value = { env.get_field_unchecked(&obj_foo, &FIELD, ReturnType::Primitive(Primitive::Int))? .i()? }; assert_eq!(123, field_value); let method_value = { let method_id = METHOD.lookup(&mut env)?; let args = &[]; // Safety: `args` must match the method arg count and types. unsafe { env.call_method_unchecked( &obj_foo, method_id, ReturnType::Primitive(Primitive::Boolean), args, ) }? .z()? }; assert!(method_value); env.delete_local_ref(obj_foo)?; let static_field_value = { env.get_static_field_unchecked(&FOO, &STATIC_FIELD, JavaType::Primitive(Primitive::Long))? .j()? }; assert_eq!(321, static_field_value); let static_method_value = { let method_id = STATIC_METHOD.lookup(&mut env)?; let args = &[]; // Safety: `args` must match the method arg count and types. unsafe { env.call_static_method_unchecked( &FOO, method_id, ReturnType::Primitive(Primitive::Int), args, ) }? .i()? }; assert_eq!(3, static_method_value); Ok(()) }