Handling Ownership and Borrowing

Identifying Ownership and Borrowing in Rust

Rust enforces strict ownership rules. When a function in Rust takes ownership of a value (e.g., Box, Vec), it means the caller no longer owns that value and cannot use it again unless ownership is returned. Borrowing (&T or &mut T) allows temporary access to a value without transferring ownership.

Pre-Modified Rust Function:

Here’s an example of two functions that demonstrate ownership and borrowing in Rust before modification for interoperability with Java:

#![allow(unused)]
fn main() {
fn take_ownership(v: Vec<i32>) -> Vec<i32> {
    // Takes ownership of v
    v
}

fn borrow(v: &Vec<i32>) -> i32 {
    // Borrows v temporarily
    v[0]
}
}

Explanation:

take_ownership:

  • Transfers ownership of the Vec to the function.
  • The original owner can no longer use v unless ownership is explicitly returned. borrow:
  • Borrows the Vec temporarily to access its first element without transferring ownership.
  • The caller retains ownership.

Modified Rust Function

#![allow(unused)]
fn main() {
#[no_mangle]
pub extern "C" fn take_ownership(v: *mut Vec<i32>) -> *mut Vec<i32> {
    // Transfers ownership of the vector
    v
}

#[no_mangle]
pub extern "C" fn borrow(v: *mut Vec<i32>) -> i32 {
    unsafe { (*v)[0] } // Borrowing a raw pointer
}
}

Explanation:

Check Chapter 2.2(Setting Up Rust)

Handling Ownership in Java

When Rust functions take ownership of values or borrow them, Java developers must manage memory explicitly to prevent leaks or invalid references.

What You Need to Do:

  • For functions that take ownership: You need to call the appropriate Rust cleanup function (like drop or free) using MethodHandle in Java. is released once the object is no longer needed.
  • For borrowed references: Manage memory using Arena to ensure that memory remains valid for the borrowed duration.

Java Example (Handling Ownership):

// Create a Rust-owned Box and pass ownership MemorySegment rustBox = (MemorySegment) 
RustBindings.createBox.invokeExact(10); 

// Call Rust function to take ownership of the box 
RustBindings.takeOwnership.invokeExact(rustBox); 

// Manually free the Box when done 
RustBindings.freeBox.invokeExact(rustBox); // Ensures no memory leaks

Explanation:

MemorySegment represents the Rust-allocated memory in Java. Java interacts with this using the Foreign Function & Memory API. When takeOwnership is called, the Rust function takes ownership of rustBox. Java then explicitly calls freeBox to release the memory allocated in Rust and prevent leaks.