From 4954cff2ea43a1e4c632534ec2391c5291424b9c Mon Sep 17 00:00:00 2001 From: jun0 Date: Wed, 22 Jul 2026 18:14:21 +0900 Subject: [PATCH 1/2] fix: implement time APIs in RuntimeImpl (now/sleep/yield were todo!) System.currentTimeMillis(), Thread.sleep(), Thread.yield(), new Date() and everything else routed through Runtime::now/sleep/yield crashed the deployed binary with a Rust panic because the only production Runtime implementation left them as todo!(). Tests stayed green because the integration corpus never exercised these APIs and TestRuntime had its own (partial) implementations. - RuntimeImpl::now -> SystemTime since UNIX_EPOCH in ms - RuntimeImpl::sleep -> tokio::time::sleep - RuntimeImpl::yield -> tokio::task::yield_now (also fills the todo!() in TestRuntime so test and binary behavior match) - root Cargo.toml: add tokio "time" feature (both target sections) - test_data/TimeApi: fixture calling currentTimeMillis/yield/sleep/Date with deterministic assertions (positivity/monotonicity/min-elapsed), locking the regression through the RuntimeImpl integration path Co-Authored-By: Claude Fable 5 --- Cargo.toml | 4 ++-- src/runtime.rs | 9 +++++---- test_data/TimeApi.class | Bin 0 -> 1171 bytes test_data/TimeApi.txt | 5 +++++ test_utils/src/lib.rs | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 test_data/TimeApi.class create mode 100644 test_data/TimeApi.txt diff --git a/Cargo.toml b/Cargo.toml index 53459dc6..5b8be404 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ java_runtime = { workspace = true } test_utils = { workspace = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -tokio = { workspace = true, features = ["rt-multi-thread"] } +tokio = { workspace = true, features = ["rt-multi-thread", "time"] } [target.'cfg(target_arch = "wasm32")'.dependencies] -tokio = { workspace = true, features = ["rt"] } +tokio = { workspace = true, features = ["rt", "time"] } diff --git a/src/runtime.rs b/src/runtime.rs index 649fd6e7..2b9e5e7e 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -9,6 +9,7 @@ use std::{ fs, io::{Write, stderr, stdin}, sync::Mutex, + time::{SystemTime, UNIX_EPOCH}, }; use java_runtime::{File, FileDescriptorId, FileStat, FileType, IOError, IOResult, RT_RUSTJAR, Runtime, SpawnCallback, get_runtime_class_proto}; @@ -87,12 +88,12 @@ impl Runtime for RuntimeImpl where T: Sync + Send + Write + 'static, { - async fn sleep(&self, _duration: Duration) { - todo!() + async fn sleep(&self, duration: Duration) { + tokio::time::sleep(duration).await; } async fn r#yield(&self) { - todo!() + tokio::task::yield_now().await; } fn spawn(&self, _jvm: &Jvm, callback: Box) { @@ -107,7 +108,7 @@ where } fn now(&self) -> u64 { - todo!() + SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or(Duration::from_secs(0)).as_millis() as u64 } fn current_task_id(&self) -> u64 { diff --git a/test_data/TimeApi.class b/test_data/TimeApi.class new file mode 100644 index 0000000000000000000000000000000000000000..5a394ad6699a0de9ad8259f4f477a7f9f7b8c880 GIT binary patch literal 1171 zcmZuxT~8B16g|@qW?Pr90!2`y5Yd8!Dt-eZ-wGBrX+vUsFiSh);C6SjouWMXCwMdQ z)n|PGqKQAiA7#BW6tKc3ot-)N+%xCineFdCKYjt2M?Q%Nq8u?BakMaWY&$zn&UL)4 z+>6a^QBn*oGt!f4mLZxQ-AKYhf+K0;0_-MwVYjM8g`u-l3q#?lqO6E@>AJFNGS?E6 z*=D019kljqB;1oXn@K1|Ex5-($bdHwPV}lPM8FWsu8nS37^RIXzUM37lckLFR*5iU7#41j zpsDO6ek?d?A;-{acp2e3K~<1}TMQ|~Z^Ailla8sqrlgx&a+FA75>Y+evvFUa9N!Y= zh%7uL-7-=B>F_i|!su$8;}OyIan1*ls#x^Pf}uSxJ@LF&*%V>X*>nksRUAo8O=n-9 z*Hzl2pq$eCbtf=fKKC81gNeN_uu`305l?mPqvsHp2u)>Z+Ku5uTqWKDAwz?EpNW^%yfF$I zNOWV|z!Mt2N$^ihzB<62sW`>^;`_LJB>zCirzoz?MU1%#`Vz@8Vq~+IzOjC?IZRj< zHpbCPoHlHr18>lY9i*^8>`$=jG>vd9#=tnzb*k`aMPr&{xsDP2x3CyHjW?DJLa~w6 fjMk}zF_XsWt{p3%B8_A`ArqvGr}SGhr9Ar!5wiIt literal 0 HcmV?d00001 diff --git a/test_data/TimeApi.txt b/test_data/TimeApi.txt new file mode 100644 index 00000000..b10f2546 --- /dev/null +++ b/test_data/TimeApi.txt @@ -0,0 +1,5 @@ +currentTimeMillis positive +yield returned +monotonic after sleep +sleep elapsed +date positive diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs index 6b0ca6bc..f556408d 100644 --- a/test_utils/src/lib.rs +++ b/test_utils/src/lib.rs @@ -64,7 +64,7 @@ impl Runtime for TestRuntime { } async fn r#yield(&self) { - todo!() + tokio::task::yield_now().await; } fn spawn(&self, _jvm: &Jvm, callback: Box) { From 3afb6cc29895ec4af9d0844b02edbe7a0d6f062f Mon Sep 17 00:00:00 2001 From: jun0 Date: Wed, 22 Jul 2026 18:14:21 +0900 Subject: [PATCH 2/2] docs: add STATE.md/REPORT.md per autonomous-ops SOP Co-Authored-By: Claude Fable 5 --- REPORT.md | 13 +++++++++++++ STATE.md | 13 +++++++++++++ 2 files changed, 26 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..7204fa66 --- /dev/null +++ b/REPORT.md @@ -0,0 +1,13 @@ +# REPORT + +## [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..a98b93fa --- /dev/null +++ b/STATE.md @@ -0,0 +1,13 @@ +# 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 게이트② 대기. + +## 다음 +- PR approve 후 머지, 브랜치 정리(`gh pr merge --delete-branch` → `git branch -D` → `git fetch --prune`) +- (범위 밖 잔여) `jvm_rust/src/interpreter.rs:629` `todo!()` — 별건 티켓 필요