Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port java-spaghetti-gen to cafebabe; cache method/field IDs; fix jclass memory leaks #5

Merged
merged 6 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Rust
name: Rust - Nightly

on:
push:
Expand All @@ -11,10 +11,12 @@ env:
CARGO_TERM_COLOR: always

jobs:
build:
build_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- run: rustup update nightly && rustup default nightly
- run: rustup component add rustfmt
- name: Check fmt
run: cargo fmt -- --check
- name: Test
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The full list of differences are:
- You can filter which classes are generated in the TOML config.
- Generated code uses relative paths (`super::...`) instead of absolute paths (`crate::...`), so it works if you place it in a submodule not at the crate root.
- Generated code is a single `.rs` file, there's no support for spltting it in one file per class. You can still run the output through [form](https://github.com/djmcgill/form), if you want.
- Generated code uses cached method IDs and field IDs stored in `OnceLock` to speed up invocations by several times. Used classes are also stored as JNI global references in order to keep the validity of cached IDs. This may not ensure memory safety when class redefinition features (e.g. `java.lang.instrument` which is unavailable on Android) of the JVM is being used.
- Generated code doesn't use macros.
- No support for generating Cargo features per class.
- Modernized rust, updated dependencies.
Expand Down
16 changes: 8 additions & 8 deletions java-spaghetti-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ categories = ["development-tools::ffi"]
license = "MIT OR Apache-2.0"

[dependencies]
jreflection = "0.0.11"
clap = { version = "4", features = ["derive"] }
bitflags = "2.4.2"
serde = "1.0.197"
serde_derive = "1.0.197"
toml = "0.8.10"
zip = "0.6.6"
cafebabe = "0.8.0"
clap = { version = "4", features = ["derive"] }
bitflags = "2.8.0"
serde = "1.0.197"
serde_derive = "1.0.197"
toml = "0.8.10"
zip = "2.2.2"

[dev-dependencies]
jni-sys = "0.4.0"
jni-sys = "0.4.0"
19 changes: 9 additions & 10 deletions java-spaghetti-gen/src/emit_rust/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ use std::rc::Rc;
use std::sync::Mutex;
use std::time::Duration;

use jreflection::class;

use super::modules::Module;
use super::preamble::write_preamble;
use super::structs::Struct;
use crate::{config, util};
use crate::{config, parser_util, util};

pub struct Context<'a> {
pub(crate) config: &'a config::runtime::Config,
Expand All @@ -32,10 +30,11 @@ impl<'a> Context<'a> {
}

pub(crate) fn throwable_rust_path(&self, mod_: &str) -> String {
self.java_to_rust_path(class::Id("java/lang/Throwable"), mod_).unwrap()
self.java_to_rust_path(parser_util::Id("java/lang/Throwable"), mod_)
.unwrap()
}

pub fn java_to_rust_path(&self, java_class: class::Id, mod_: &str) -> Result<String, Box<dyn Error>> {
pub fn java_to_rust_path(&self, java_class: parser_util::Id, mod_: &str) -> Result<String, Box<dyn Error>> {
let m = Struct::mod_for(self, java_class)?;
let s = Struct::name_for(self, java_class)?;
let fqn = format!("{}::{}", m, s);
Expand Down Expand Up @@ -92,18 +91,18 @@ impl<'a> Context<'a> {
pat.pop();
}

return false;
false
}

pub fn add_struct(&mut self, class: jreflection::Class) -> Result<(), Box<dyn Error>> {
if self.config.ignore_classes.contains(class.path.as_str()) {
pub fn add_struct(&mut self, class: parser_util::Class) -> Result<(), Box<dyn Error>> {
if self.config.ignore_classes.contains(class.path().as_str()) {
return Ok(());
}
if !self.struct_included(class.path.as_str()) {
if !self.struct_included(class.path().as_str()) {
return Ok(());
}

let java_path = class.path.as_str().to_string();
let java_path = class.path().as_str().to_string();
let s = Rc::new(Struct::new(self, class)?);

self.all_classes.insert(java_path, s.clone());
Expand Down
Loading