From 05f2143793b287b2957a61cd623f1a14c5fc39f4 Mon Sep 17 00:00:00 2001 From: jun0 Date: Wed, 22 Jul 2026 18:37:31 +0900 Subject: [PATCH 1/2] fix: remove tracing-attributes upper-bound pin by dropping #[instrument] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit java_runtime carried a direct tracing-attributes = "<0.1.29" dependency to dodge the no_std compile error in tokio-rs/tracing#3388, which froze the whole tracing family at 0.1.41 and made dependabot PRs unresolvable (tracing 0.1.44 requires tracing-attributes 0.1.31, conflicting with the pin). The only code forcing this was a single #[tracing::instrument] in Thread's spawn callback. - thread.rs: replace #[tracing::instrument(name = "java thread", fields(id = self.thread_id), skip_all)] with a manual tracing::info_span! + Instrument combinator (no_std-safe; identical span name, field, level, and target — verified by comparing RUST_LOG output before/after) - java_runtime/Cargo.toml: drop the tracing-attributes direct dep + pin - workspace Cargo.toml: drop tracing's now-unused "attributes" feature - Cargo.lock: tracing family only — tracing 0.1.41 -> 0.1.44 (the previously impossible resolution), tracing-subscriber 0.3.20 -> 0.3.23, tracing-attributes removed from the graph; zero unrelated crates - rust.yml: wasm32 clippy was missing workspace coverage; now --workspace --exclude test_utils (test_utils requires tokio rt-multi-thread, which has a compile_error! on wasm) Verified: cargo test --all green (140 passed), clippy -D warnings clean natively and on wasm32-unknown-unknown (the no_std target the pin existed to protect). Co-Authored-By: Claude Fable 5 --- .github/workflows/rust.yml | 3 +- Cargo.lock | 21 +---- Cargo.toml | 2 +- java_runtime/Cargo.toml | 1 - java_runtime/src/classes/java/lang/thread.rs | 92 +++++++++++--------- 5 files changed, 57 insertions(+), 62 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d90a7a94..74dff429 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -50,5 +50,6 @@ jobs: - run: cargo fmt --all -- --check - run: cargo clippy --all -- -D warnings - - run: cargo clippy --target wasm32-unknown-unknown -- -D warnings + # test_utils requires tokio rt-multi-thread, which does not compile on wasm + - run: cargo clippy --workspace --exclude test_utils --target wasm32-unknown-unknown -- -D warnings - run: cargo test --all diff --git a/Cargo.lock b/Cargo.lock index 8fa03237..5d8ef91a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -346,7 +346,6 @@ dependencies = [ "test_utils", "tokio", "tracing", - "tracing-attributes", "url", "zip", ] @@ -690,26 +689,14 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tracing-core" version = "0.1.36" @@ -733,9 +720,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", diff --git a/Cargo.toml b/Cargo.toml index 53459dc6..d743a1c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ dyn-hash = { version = "^1.0", default-features = false } hashbrown = { version = "^0.17", features = ["default-hasher"], default-features = false } nom = { version = "^8.0", default-features = false, features = ["alloc"] } parking_lot = { version = "^0.12", default-features = false } -tracing = { version = "^0.1", default-features = false, features = ["attributes"] } +tracing = { version = "^0.1", default-features = false } tokio = { version = "^1.52", features = ["macros"] } diff --git a/java_runtime/Cargo.toml b/java_runtime/Cargo.toml index f003fbd7..a50d3027 100644 --- a/java_runtime/Cargo.toml +++ b/java_runtime/Cargo.toml @@ -14,7 +14,6 @@ tracing = { workspace = true } chrono = { version = "^0.4", default-features = false } encoding_rs = { version = "^0.8", features = ["alloc"], default-features = false } -tracing-attributes = { version = "<0.1.29" } # Pin this to avoid compile error with no-std https://github.com/tokio-rs/tracing/issues/3388 url = { version = "^2.5", default-features = false } zip = { version = "^8.6", features = ["deflate"], default-features = false } diff --git a/java_runtime/src/classes/java/lang/thread.rs b/java_runtime/src/classes/java/lang/thread.rs index d40447d0..bde4cde5 100644 --- a/java_runtime/src/classes/java/lang/thread.rs +++ b/java_runtime/src/classes/java/lang/thread.rs @@ -4,6 +4,7 @@ use core::time::Duration; use java_class_proto::{JavaFieldProto, JavaMethodProto}; use java_constants::MethodAccessFlags; use jvm::{ClassInstanceRef, Jvm, Result, runtime::JavaLangString}; +use tracing::Instrument; use crate::{RuntimeClassProto, RuntimeContext, SpawnCallback, classes::java::lang::Runnable}; @@ -87,50 +88,57 @@ impl Thread { #[async_trait::async_trait] impl SpawnCallback for ThreadStartProxy { - #[tracing::instrument(name = "java thread", fields(id = self.thread_id), skip_all)] async fn call(&self) -> Result<()> { - tracing::trace!("Thread start"); - - self.jvm.attach_thread()?; - - let result: Result<()> = self.jvm.invoke_virtual(&self.this, "run", "()V", []).await; - - if let Err(jvm::JavaError::JavaException(x)) = result { - let string_writer = self.jvm.new_class("java/io/StringWriter", "()V", ()).await.unwrap(); - let print_writer = self - .jvm - .new_class("java/io/PrintWriter", "(Ljava/io/Writer;)V", (string_writer.clone(),)) - .await - .unwrap(); - - let _: () = self - .jvm - .invoke_virtual(&x, "printStackTrace", "(Ljava/io/PrintWriter;)V", (print_writer,)) - .await - .unwrap(); - - let trace = self - .jvm - .invoke_virtual(&string_writer, "toString", "()Ljava/lang/String;", []) - .await - .unwrap(); - - tracing::error!( - "Uncaught exception in thread {}:\n{}", - self.thread_id, - JavaLangString::to_rust_string(&self.jvm, &trace).await.unwrap() - ); - } else { - result?; + // manual span instead of #[tracing::instrument]: tracing-attributes breaks no_std + // builds (tokio-rs/tracing#3388), and this was the only use in the workspace + let span = tracing::info_span!("java thread", id = self.thread_id); + + async { + tracing::trace!("Thread start"); + + self.jvm.attach_thread()?; + + let result: Result<()> = self.jvm.invoke_virtual(&self.this, "run", "()V", []).await; + + if let Err(jvm::JavaError::JavaException(x)) = result { + let string_writer = self.jvm.new_class("java/io/StringWriter", "()V", ()).await.unwrap(); + let print_writer = self + .jvm + .new_class("java/io/PrintWriter", "(Ljava/io/Writer;)V", (string_writer.clone(),)) + .await + .unwrap(); + + let _: () = self + .jvm + .invoke_virtual(&x, "printStackTrace", "(Ljava/io/PrintWriter;)V", (print_writer,)) + .await + .unwrap(); + + let trace = self + .jvm + .invoke_virtual(&string_writer, "toString", "()Ljava/lang/String;", []) + .await + .unwrap(); + + tracing::error!( + "Uncaught exception in thread {}:\n{}", + self.thread_id, + JavaLangString::to_rust_string(&self.jvm, &trace).await.unwrap() + ); + } else { + result?; + } + + self.jvm.detach_thread()?; + + let mut this = self.this.clone(); + self.jvm.put_field(&mut this, "alive", "Z", false).await.unwrap(); + self.jvm.object_notify(&self.this, usize::MAX); + + Ok(()) } - - self.jvm.detach_thread()?; - - let mut this = self.this.clone(); - self.jvm.put_field(&mut this, "alive", "Z", false).await.unwrap(); - self.jvm.object_notify(&self.this, usize::MAX); - - Ok(()) + .instrument(span) + .await } } From 0a19f38e7682c6449df01bbadc8e63e2eb0c8059 Mon Sep 17 00:00:00 2001 From: jun0 Date: Wed, 22 Jul 2026 18:37:31 +0900 Subject: [PATCH 2/2] docs: update STATE.md/REPORT.md per autonomous-ops SOP Superset content covering all three in-flight PRs so later add/add merges resolve by taking the newest branch's version. Co-Authored-By: Claude Fable 5 --- REPORT.md | 42 ++++++++++++++++++++++++++++++++++++++++++ STATE.md | 23 +++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 REPORT.md create mode 100644 STATE.md diff --git a/REPORT.md b/REPORT.md new file mode 100644 index 00000000..9c2b77fa --- /dev/null +++ b/REPORT.md @@ -0,0 +1,42 @@ +# REPORT + +## [2026-07-22] tracing-attributes 상한 핀 제거 (rustjava-tracing-attributes-pin-removal) +- 무엇을: 워크스페이스 유일의 `#[tracing::instrument]`(thread.rs, "java thread" span)를 + `tracing::info_span!` + `Instrument` 수동 span 으로 대체하고, `java_runtime` 의 + `tracing-attributes <0.1.29` 직접 의존 핀과 workspace `tracing` 의 `attributes` 피처를 제거. + Cargo.lock 은 tracing 계열만 국소 갱신(tracing 0.1.41→0.1.44, subscriber 0.3.20→0.3.23, + tracing-attributes 그래프에서 소멸). wasm32 clippy CI 의 누락 커버리지도 교정 + (`--workspace --exclude test_utils` — test_utils 는 tokio rt-multi-thread 라 wasm 불가). +- 왜: 한 줄의 attribute macro 가 no_std 빌드를 깨는 탓(tokio-rs/tracing#3388)에 tracing 계열 + 전체가 동결됐고 dependabot PR 이 해석 불가로 계속 죽었음. +- 사용자 영향: tracing 계열 업데이트 재개 가능(보안 패치 포함). span 출력("java thread{id=N}" + 이름·필드·레벨·타깃)은 실행 대조로 동일함을 확인 — 관측 회귀 0. +- 후속 추천: ① dependabot 재시도 유도(다음 주기에 자동), ② javac 21 익명 내부 클래스 파싱 + 실패(Malformed) 원인 조사 별건, ③ wasm32 에서 test_utils 대체 테스트 전략 검토. + +## [2026-07-22] 클래스파일 파싱 실패 → ClassFormatError 전파 (rustjava-classfile-parse-error-propagation) +- 무엇을: `ClassInfo::parse` 를 `Option` → `Result<_, ParseError>` 로 바꿔 실패 원인(절단/매직 + 불일치/미지원 상수풀 태그 N/기타 손상)을 담고, `from_classfile` 의 `unwrap()`/`assert_eq!` 를 + 제거해 `define_class` 에서 기존 예외 관례(`jvm.exception`)대로 `java.lang.ClassFormatError` 로 + 올림. `java/lang/ClassFormatError` 런타임 클래스(부모 LinkageError) 신설. +- 왜: 손상되거나 미지원 항목(javac 9+ 가 기본으로 심는 invokedynamic 계열 태그 15~18)을 가진 + class 파일을 여는 순간 Rust 패닉으로 프로세스(임베딩 호스트 포함)가 즉사했음. "클래스 못 찾음" + 은 예외인데 "못 읽음"만 패닉인 비대칭. +- 사용자 영향: 잘못된 class 파일이 진단 가능한 자바 예외(원인 메시지 포함)로 보고되고 프로세스는 + 살아남음. 미지원 태그는 명확히 거절(구현 아님). `tests/test_class_format.rs` 4케이스(절단/태그 + 18/매직/못찾음 대조군)가 회귀 잠금. +- 후속 추천: ① invokedynamic/MethodHandle 실제 지원(별건 대형), ② 상수풀 인덱스 참조 + (`.get().unwrap()` 계열) 손상 대응(별건), ③ UnsupportedClassVersionError 도입 검토(major + version 기반). + +## [2026-07-22] 시간 API 패닉 제거 + 회귀 잠금 (rustjava-runtime-time-todo-impl) +- 무엇을: `src/runtime.rs`의 `RuntimeImpl` 에서 `now()`/`sleep()`/`r#yield()` 의 `todo!()` 를 실제 + 구현(UNIX epoch ms·`tokio::time::sleep`·`tokio::task::yield_now`)으로 교체하고, `test_utils` + `TestRuntime::r#yield` 의 `todo!()` 도 동형으로 구현. 루트 `Cargo.toml` tokio 에 `time` 피처 추가. +- 왜: 배포 바이너리가 `System.currentTimeMillis()`·`Thread.sleep()`·`new Date()` 등 시간 API 를 + 부르는 순간 Rust 패닉으로 즉사했으나, 테스트 코퍼스가 해당 API 를 0건 사용해 CI 가 초록이었음. +- 사용자 영향: 시간 API 를 쓰는 모든 자바 프로그램이 이제 정상 동작. `test_data/TimeApi` + 픽스처(currentTimeMillis/yield/sleep/Date, 결정론적 단언)가 `RuntimeImpl` 경로 통합 테스트로 + 상시 회귀 감시. +- 후속 추천: ① `jvm_rust/src/interpreter.rs:629` 의 잔여 `todo!()` 제거(별건), ② Timer/Object.wait + 경로도 픽스처 확장, ③ 픽스처 .java 소스 보관 체계(현재 .class+.txt 만 커밋하는 관례). diff --git a/STATE.md b/STATE.md new file mode 100644 index 00000000..9ccc3f43 --- /dev/null +++ b/STATE.md @@ -0,0 +1,23 @@ +# STATE + +## 진행중 +- (없음) + +## 완료 +- [rustjava-runtime-time-todo-impl] RuntimeImpl 시간 API `todo!()` 3건 제거(now/sleep/yield) + + test_utils `r#yield` 구현 + tokio `time` 피처 추가 + 회귀 잠금 픽스처(`test_data/TimeApi`). + 브랜치 `runtime-time-impl`, PR #2 게이트② 대기. +- [rustjava-classfile-parse-error-propagation] 클래스파일 파싱 실패를 패닉 대신 + `java.lang.ClassFormatError` 로 전파(절단/매직 불일치/미지원 상수풀 태그 구분). + 브랜치 `classfile-parse-error-propagation`, PR #3 게이트② 대기. +- [rustjava-tracing-attributes-pin-removal] `#[tracing::instrument]` 1건을 수동 span 으로 대체, + `tracing-attributes` 상한 핀 제거(tracing 0.1.41→0.1.44 언프리즈), wasm32 clippy CI 커버리지 + 교정. 브랜치 `tracing-attributes-pin-removal`, PR 게이트② 대기. + +## 다음 +- PR approve 후 머지, 브랜치 정리(`gh pr merge --delete-branch` → `git branch -D` → `git fetch --prune`) +- ★세 PR 모두 STATE.md/REPORT.md 를 추가하므로 나중에 머지되는 쪽마다 add/add 충돌 예상 — + 선행 PR 머지 후 후행 브랜치에 `git merge main` 하고 최신(superset) 내용 채택으로 해소. +- (범위 밖 잔여) `jvm_rust/src/interpreter.rs:629` `todo!()` — 별건 티켓 필요 +- (신규 발견) javac 21 산출 익명 내부 클래스(.class)가 "Malformed class file" 로 파싱 실패 — + 원인 미조사(태그 15~18 아님). 별건 티켓 필요.