diff --git a/exonum-java-binding/core/rust/Cargo.lock b/exonum-java-binding/core/rust/Cargo.lock index 6e91e0b858..8c2892d6dd 100644 --- a/exonum-java-binding/core/rust/Cargo.lock +++ b/exonum-java-binding/core/rust/Cargo.lock @@ -1261,7 +1261,7 @@ dependencies = [ "exonum-testkit 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "exonum-time 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "jni 0.12.3 (git+https://github.com/jni-rs/jni-rs?branch=auto-detach-threads)", + "jni 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1274,8 +1274,8 @@ dependencies = [ [[package]] name = "jni" -version = "0.12.3" -source = "git+https://github.com/jni-rs/jni-rs?branch=auto-detach-threads#49627d30fabc363637ea0cc69e5b324e65c52489" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3300,7 +3300,7 @@ dependencies = [ "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum jni 0.12.3 (git+https://github.com/jni-rs/jni-rs?branch=auto-detach-threads)" = "" +"checksum jni 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2de18a6e18bddad7951b639019d56ebdc1ed75e6f6ee955c0c5085fce13bdfe8" "checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" diff --git a/exonum-java-binding/core/rust/Cargo.toml b/exonum-java-binding/core/rust/Cargo.toml index 500885da50..6cdb05d4ab 100644 --- a/exonum-java-binding/core/rust/Cargo.toml +++ b/exonum-java-binding/core/rust/Cargo.toml @@ -21,7 +21,7 @@ exonum-testkit = "0.11" chrono = "0.4.7" failure = "0.1.1" toml = "0.4.6" -jni = { git = "https://github.com/jni-rs/jni-rs", branch = "auto-detach-threads", version = "0.12.3", features = ["invocation"] } +jni = { version = "0.13.0", features = ["invocation"] } lazy_static = "1.3.0" log = "0.4.1" parking_lot = "0.6" diff --git a/exonum-java-binding/core/rust/integration_tests/src/executor.rs b/exonum-java-binding/core/rust/integration_tests/src/executor.rs deleted file mode 100644 index dca4b8b911..0000000000 --- a/exonum-java-binding/core/rust/integration_tests/src/executor.rs +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2019 The Exonum Team - * - * 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. - */ - -use example_proxy::AtomicIntegerProxy; -use java_bindings::{ - jni::{sys::jint, JavaVM}, - Executor, JniErrorKind, -}; - -use std::{ - sync::{Arc, Barrier}, - thread::spawn, -}; - -/// Checks if nested `with_attached` calls does not detach the thread before the outer-most -/// call is finished. -pub fn check_nested_attach(vm: &JavaVM, executor: Executor) { - check_detached(vm); - executor - .with_attached(|_| { - check_attached(vm); - executor.with_attached(|_| { - check_attached(vm); - Ok(()) - })?; - check_attached(vm); - Ok(()) - }) - .unwrap(); -} - -pub fn check_attached(vm: &JavaVM) { - assert!(is_attached(vm)); -} - -pub fn check_detached(vm: &JavaVM) { - assert!(!is_attached(vm)); -} - -pub fn is_attached(vm: &JavaVM) -> bool { - vm.get_env() - .map(|_| true) - .or_else(|jni_err| match jni_err.0 { - JniErrorKind::ThreadDetached => Ok(false), - _ => Err(jni_err), - }) - .expect("An unexpected JNI error occurred") -} - -pub fn test_single_thread(executor: Executor) { - let mut atomic = AtomicIntegerProxy::new(executor, 0).unwrap(); - assert_eq!(0, atomic.get().unwrap()); - assert_eq!(1, atomic.increment_and_get().unwrap()); - assert_eq!(3, atomic.add_and_get(2).unwrap()); - assert_eq!(3, atomic.get().unwrap()); -} - -pub fn test_serialized_threads(executor: Executor) { - let mut atomic = AtomicIntegerProxy::new(executor, 0).unwrap(); - assert_eq!(0, atomic.get().unwrap()); - let jh = spawn(move || { - assert_eq!(1, atomic.increment_and_get().unwrap()); - assert_eq!(3, atomic.add_and_get(2).unwrap()); - atomic - }); - let mut atomic = jh.join().unwrap(); - assert_eq!(3, atomic.get().unwrap()); -} - -pub fn test_concurrent_threads(executor: Executor, thread_num: usize) { - const ITERS_PER_THREAD: usize = 10_000; - - let mut atomic = AtomicIntegerProxy::new(executor.clone(), 0).unwrap(); - let barrier = Arc::new(Barrier::new(thread_num)); - let mut threads = Vec::new(); - - for _ in 0..thread_num { - let barrier = Arc::clone(&barrier); - let mut atomic = atomic.clone(); - let jh = spawn(move || { - barrier.wait(); - for _ in 0..ITERS_PER_THREAD { - atomic.increment_and_get().unwrap(); - } - }); - threads.push(jh); - } - for jh in threads { - jh.join().unwrap(); - } - let expected = (ITERS_PER_THREAD * thread_num) as jint; - assert_eq!(expected, atomic.get().unwrap()); -} diff --git a/exonum-java-binding/core/rust/integration_tests/src/lib.rs b/exonum-java-binding/core/rust/integration_tests/src/lib.rs index 460e007675..f0d5e32f0c 100644 --- a/exonum-java-binding/core/rust/integration_tests/src/lib.rs +++ b/exonum-java-binding/core/rust/integration_tests/src/lib.rs @@ -18,7 +18,6 @@ extern crate lazy_static; extern crate tempfile; pub mod example_proxy; -pub mod executor; pub mod fake_service; pub mod mock; pub mod test_service; diff --git a/exonum-java-binding/core/rust/integration_tests/tests/executor.rs b/exonum-java-binding/core/rust/integration_tests/tests/executor.rs deleted file mode 100644 index 9e7274f7ab..0000000000 --- a/exonum-java-binding/core/rust/integration_tests/tests/executor.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018 The Exonum Team -// -// 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. - -extern crate integration_tests; -extern crate java_bindings; -#[macro_use] -extern crate lazy_static; - -use integration_tests::executor::{ - test_concurrent_threads, test_serialized_threads, test_single_thread, -}; -use integration_tests::vm::create_vm_for_tests; -use java_bindings::jni::JavaVM; -use java_bindings::Executor; - -use std::sync::Arc; - -lazy_static! { - pub static ref VM: Arc = create_vm_for_tests(); - pub static ref EXECUTOR: Executor = Executor::new(VM.clone()); -} - -#[test] -fn single_thread() { - test_single_thread(EXECUTOR.clone()); -} - -#[test] -fn serialized_threads() { - test_serialized_threads(EXECUTOR.clone()); -} - -#[test] -fn concurrent_threads() { - const THREAD_NUM: usize = 8; - test_concurrent_threads(EXECUTOR.clone(), THREAD_NUM) -} diff --git a/exonum-java-binding/core/rust/integration_tests/tests/executor_nested_attach.rs b/exonum-java-binding/core/rust/integration_tests/tests/executor_nested_attach.rs deleted file mode 100644 index a4e6e5ca9c..0000000000 --- a/exonum-java-binding/core/rust/integration_tests/tests/executor_nested_attach.rs +++ /dev/null @@ -1,31 +0,0 @@ -extern crate integration_tests; -extern crate java_bindings; -#[macro_use] -extern crate lazy_static; - -use integration_tests::executor::check_nested_attach; -use integration_tests::vm::create_vm_for_tests; -use java_bindings::jni::JavaVM; -use java_bindings::Executor; - -use std::sync::Arc; -use std::thread::spawn; - -lazy_static! { - pub static ref VM: Arc = create_vm_for_tests(); - pub static ref EXECUTOR: Executor = Executor::new(VM.clone()); -} - -/// Checks if nested attaches are working properly and threads detach themselves -/// on exit. -#[test] -fn nested_attach() { - assert_eq!(VM.threads_attached(), 0); - let thread = spawn(|| { - assert_eq!(VM.threads_attached(), 0); - check_nested_attach(&VM, EXECUTOR.clone()); - assert_eq!(VM.threads_attached(), 1); - }); - thread.join().unwrap(); - assert_eq!(VM.threads_attached(), 0); -} diff --git a/exonum-java-binding/core/rust/src/lib.rs b/exonum-java-binding/core/rust/src/lib.rs index c8941a760b..e89ca33e98 100644 --- a/exonum-java-binding/core/rust/src/lib.rs +++ b/exonum-java-binding/core/rust/src/lib.rs @@ -59,3 +59,4 @@ pub use storage::*; pub use testkit::*; pub use jni::errors::{Error as JniError, ErrorKind as JniErrorKind, Result as JniResult}; +pub use jni::Executor; diff --git a/exonum-java-binding/core/rust/src/proxy/executor.rs b/exonum-java-binding/core/rust/src/proxy/executor.rs deleted file mode 100644 index 01f49301e3..0000000000 --- a/exonum-java-binding/core/rust/src/proxy/executor.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2018 The Exonum Team -// -// 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. - -use jni::objects::JObject; -use jni::{JNIEnv, JavaVM}; - -use std::sync::Arc; - -use JniResult; - -/// The capacity of local frames, allocated for attached threads by default. Same as the default -/// value Hotspot uses when calling native Java methods. -const DEFAULT_LOCAL_FRAME_CAPACITY: i32 = 32; - -/// Jni thread attachment manager. Attaches threads as daemons, hence they do not block -/// JVM exit. Finished threads detach automatically. -#[derive(Clone)] -pub struct Executor { - vm: Arc, -} - -impl Executor { - /// Creates new Executor with specified JVM. - pub fn new(vm: Arc) -> Self { - Self { vm } - } - - /// Executes a provided closure, making sure that the current thread - /// is attached to the JVM. Additionally ensures that local object references are freed after - /// call. - /// - /// Allocates a local frame with the specified capacity. - pub fn with_attached_capacity(&self, capacity: i32, f: F) -> JniResult - where - F: FnOnce(&JNIEnv) -> JniResult, - { - assert!(capacity > 0, "capacity should be a positive integer"); - - let jni_env = self.vm.attach_current_thread_as_daemon()?; - let mut result = None; - jni_env.with_local_frame(capacity, || { - result = Some(f(&jni_env)); - Ok(JObject::null()) - })?; - - result.expect("The result should be Some or this line shouldn't be reached") - } - - /// Executes a provided closure, making sure that the current thread - /// is attached to the JVM. Additionally ensures that local object references are freed after - /// call. - /// - /// Allocates a local frame with the default capacity. - pub fn with_attached(&self, f: F) -> JniResult - where - F: FnOnce(&JNIEnv) -> JniResult, - { - self.with_attached_capacity(DEFAULT_LOCAL_FRAME_CAPACITY, f) - } -} diff --git a/exonum-java-binding/core/rust/src/proxy/mod.rs b/exonum-java-binding/core/rust/src/proxy/mod.rs index d7b46b9189..0a5746a220 100644 --- a/exonum-java-binding/core/rust/src/proxy/mod.rs +++ b/exonum-java-binding/core/rust/src/proxy/mod.rs @@ -12,12 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod executor; mod node; mod service; mod transaction; -pub use self::executor::*; pub use self::node::*; pub use self::service::*; pub use self::transaction::*; diff --git a/exonum-java-binding/core/rust/src/proxy/node.rs b/exonum-java-binding/core/rust/src/proxy/node.rs index ad2d6c4630..a845437bc0 100644 --- a/exonum-java-binding/core/rust/src/proxy/node.rs +++ b/exonum-java-binding/core/rust/src/proxy/node.rs @@ -24,12 +24,12 @@ use exonum::{ use failure; use jni::objects::JClass; use jni::sys::{jbyteArray, jshort}; +use jni::Executor; use jni::JNIEnv; use std::{panic, ptr}; use handle::{cast_handle, drop_handle, to_handle, Handle}; -use proxy::Executor; use storage::View; use utils::{unwrap_exc_or, unwrap_exc_or_default, unwrap_jni_verbose}; use JniResult; diff --git a/exonum-java-binding/core/rust/src/proxy/service.rs b/exonum-java-binding/core/rust/src/proxy/service.rs index 0c43662594..defd654fd7 100644 --- a/exonum-java-binding/core/rust/src/proxy/service.rs +++ b/exonum-java-binding/core/rust/src/proxy/service.rs @@ -22,6 +22,7 @@ use exonum::storage::{Fork, Snapshot}; use failure; use jni::objects::{GlobalRef, JObject, JValue}; use jni::signature::JavaType; +use jni::Executor; use serde_json; use serde_json::value::Value; use std::fmt; @@ -34,7 +35,7 @@ use utils::{ check_error_on_exception, convert_to_hash, convert_to_string, jni_cache::service_adapter, panic_on_exception, unwrap_jni, }; -use {Executor, TransactionProxy}; +use TransactionProxy; /// A proxy for `Service`s. #[derive(Clone)] diff --git a/exonum-java-binding/core/rust/src/proxy/transaction.rs b/exonum-java-binding/core/rust/src/proxy/transaction.rs index 186ab5e343..f66bbddc5a 100644 --- a/exonum-java-binding/core/rust/src/proxy/transaction.rs +++ b/exonum-java-binding/core/rust/src/proxy/transaction.rs @@ -17,6 +17,7 @@ use exonum::blockchain::{ExecutionError, ExecutionResult, Transaction, TransactionContext}; use jni::objects::{GlobalRef, JObject, JValue}; use jni::signature::{JavaType, Primitive}; +use jni::Executor; use jni::JNIEnv; use serde::{self, ser}; @@ -33,7 +34,7 @@ use utils::{ }, unwrap_jni, }; -use {Executor, JniErrorKind, JniResult}; +use {JniErrorKind, JniResult}; const RETVAL_TYPE_STRING: &str = "java/lang/String"; diff --git a/exonum-java-binding/core/rust/src/runtime/java_service_runtime.rs b/exonum-java-binding/core/rust/src/runtime/java_service_runtime.rs index 4801ab14ce..9ede75f57e 100644 --- a/exonum-java-binding/core/rust/src/runtime/java_service_runtime.rs +++ b/exonum-java-binding/core/rust/src/runtime/java_service_runtime.rs @@ -18,14 +18,13 @@ use jni::{ self, errors::{Error, ErrorKind}, objects::{GlobalRef, JObject}, - InitArgs, InitArgsBuilder, JavaVM, Result as JniResult, + Executor, InitArgs, InitArgsBuilder, JavaVM, Result as JniResult, }; use proxy::ServiceProxy; use runtime::config::{self, Config, InternalConfig, JvmConfig, RuntimeConfig}; use std::{path::Path, sync::Arc}; use utils::{convert_to_string, panic_on_exception, unwrap_jni}; -use Executor; const SERVICE_RUNTIME_BOOTSTRAP_PATH: &str = "com/exonum/binding/app/ServiceRuntimeBootstrap"; const CREATE_RUNTIME_SIGNATURE: &str = "(I)Lcom/exonum/binding/core/runtime/ServiceRuntime;"; diff --git a/exonum-java-binding/core/rust/src/testkit/mod.rs b/exonum-java-binding/core/rust/src/testkit/mod.rs index 2b99b51523..14467a4b04 100644 --- a/exonum-java-binding/core/rust/src/testkit/mod.rs +++ b/exonum-java-binding/core/rust/src/testkit/mod.rs @@ -30,9 +30,9 @@ use handle::{cast_handle, drop_handle, to_handle, Handle}; use jni::{ objects::{JObject, JValue}, sys::{jboolean, jbyteArray, jobjectArray, jshort}, - JNIEnv, + Executor, JNIEnv, }; -use proxy::{Executor, ServiceProxy}; +use proxy::ServiceProxy; use std::{panic, sync::Arc}; use storage::View; use utils::{unwrap_exc_or, unwrap_exc_or_default}; diff --git a/exonum-java-binding/core/rust/src/testkit/time_provider.rs b/exonum-java-binding/core/rust/src/testkit/time_provider.rs index d41da1dff7..06a1af1641 100644 --- a/exonum-java-binding/core/rust/src/testkit/time_provider.rs +++ b/exonum-java-binding/core/rust/src/testkit/time_provider.rs @@ -19,9 +19,8 @@ use exonum::storage::StorageValue; use exonum_time::time_provider::TimeProvider; use jni::{ objects::{GlobalRef, JObject}, - JNIEnv, + Executor, JNIEnv, }; -use proxy::Executor; use utils::unwrap_jni; /// Wrapper around Java interface TimeProvider.