Skip to content

[rustjava-jvm-exception-throws-instead-of-unwrap] fix(jvm): 일으키려던 예외를 못 만들면 «보고»한다 — 죽지 않는다 - #76

Merged
Jun025 merged 2 commits into
mainfrom
feat/rustjava-exception-reports-instead-of-aborting
Sep 18, 2026
Merged

Jun025 merged 2 commits into
mainfrom
feat/rustjava-exception-reports-instead-of-aborting

Conversation

@Jun025

@Jun025 Jun025 commented Sep 18, 2026

Copy link
Copy Markdown
Owner

채택 제안 2026-09-18-named-exception-classes-are-loadable#p1
"When the runtime cannot build the exception it wants to raise, it crashes the process; it should report the failure the Java way instead."

급소 — 실패가 «이미» JavaError 다

Jvm::exception 은 846 호출부가 끝나는 자리인데 이렇게 돌았다:

let message_str = JavaLangString::from_rust_string(self, message).await.unwrap();
let instance = self.new_class(r#type, "(Ljava/lang/String;)V", (message_str,)).await.unwrap();

둘 다 jvm::Result<T> = Result<T, JavaError> 를 돌려준다 ⇒ ★그 실패는 그 자체가 자바 예외다.
unwrap 이 그것을 버리고 프로세스를 죽였다. ★실측 패닉 문면이 «버려진 보고»를 그대로 싣고 있다:

panicked at jvm/src/jvm.rs:948:94:
called `Result::unwrap()` on an `Err` value: JavaException(ClassInstance(java/lang/NoClassDefFoundError))

load_class이미 올바른 NoClassDefFoundError 를 만들어 건넸다. ⇒ 그대로 돌려준다.

도달성 — 「이론상」과 「실측」을 섞지 않는다

실측
이 트리 자기 호출부 0 — named 43 전건 loadable(PR #72 검사기) 그리고 43 전건이 <init>(Ljava/lang/String;)V 자기 proto 보유(이 회차 실측 · 누락 0 · 조상 의존 0)
공개 API 도달한다pub async fn exception 이고 wie 가 이 크레이트를 싣는다. 로더가 못 주는 이름 ⇒ 호스트 프로세스 사망

축 (★제품 함수 · 픽스처 사본 아님)

jvm/tests/test_exception_construction.rs

jvm/src/jvm.rs 형상 결과
전(.unwrap() 둘) FAILED — 위 패닉
ok (1 passed)

jvm.rs 를 되돌리면 red 가 된다.

호출부 파급 0 — 「조용히 통과하는 경로」를 «구조로» 없앴다

.exception( 846 → 846(편집 0) · JavaError:: 527자리 편집 0.
대안이던 「JavaError 에 variant 추가」를 버린 이유: let …else/if let 460자리가 조용히 else 로 새고,
jvm.rs:1073반증불가 let(변형이 하나라서 컴파일되는 자리)이 깨진다. 이 형상은 그 함정을 애초에 만들지 않는다.

★대가 (숨기지 않는다)

실패 시 호출자는 요청한 것과 다른 예외 클래스를 받는다 ⇒ 잡은 예외를 클래스로 분기하는 제품 12자리
(print_stream·print_writer·filter_output_stream·formatter 의 IOException · integer·long 의 NumberFormatException)는
그 경우 못 잡고 전파한다. 죽는 것보다 낫지만 무해한 변경이 아니다.

자기 diff 밖 파급 둘 (둘 다 선택이 아니었다)

⑴★검사기 문면 3자리가 «거짓»이 됐다 — 「unwraps … aborts the process」·「DELIBERATELY NOT DONE HERE: turning the .unwrap() into a thrown exception」·실패 메시지 「panics instead of throwing」.
문면만 고쳤다(술어 무접촉). 잠금의 «이유»가 「죽는다」 → ★**「틀린 예외가 온다」**(IOException 을 물었는데 NoClassDefFoundError 가 와서 catch 가 안 걸린다)로 바뀌고, 더 조용하므로 잠금 가치는 커졌다.
★그 축 양방향 재검증: 등재 1줄 제거 → rc=1 · 원복 → rc=0.

⑵★★형제 회차의 «비리터럴 0» 이 «1» 이 된다 — 이 테스트는 못 싣는 이름을 불러야 하고, 리터럴로 쓰면 loadable 검사기가 실제로 red 였다(실측 · :13 지목) ⇒ 이름을 변수로 든다.
그 회차가 «0 을 관문으로 올리지 않은» 판단이 하루 만에 값을 했다 — 걸었으면 이 테스트가 막혔다.
※그 술어가 주석 안의 토큰도 센다는 것도 이때 드러났다(주석 때문에 2로 읽힘 → 문구 교체).

안 고친 것

  • 퇴화 경우는 불변이고 «패닉이 아니라 무한 재귀»다: NoClassDefFoundError 자신이 안 실리면 load_class → exception → new_class → load_class 가 돈다. ★옛 unwrap 도 못 막았다(안쪽 new_class 가 돌아오지 않아 unwrap 에 닿지 않는다). ★호출그래프에서 읽은 것이고 실측이 아니다 — 커스텀 로더 하네스가 필요해 범위 밖(후속 카드).
  • from_rust_string 쪽도 같은 방식으로 고쳤지만 ★재현 경로를 못 찾았다주장하지 않는다.

DoD (9명령 전건 rc=0)

fmt 0 · clippy stable 0 · clippy +beta 0 · clippy wasm32 0 · cargo test --all 585 passed / 0 failed / 1 ignored(내 테스트 ok) · check-worklog-json 0 · check-dod-ci-parity 0 · check-named-exception-classes-are-loadable 0(846/43/268) · check-merge-dropped-symbols 0

jun0 added 2 commits September 19, 2026 01:51
… 못 만들면 «보고»한다 — 죽지 않는다

채택 제안 2026-09-18-named-exception-classes-are-loadable#p1.

급소: from_rust_string·new_class 는 jvm::Result<T> = Result<T, JavaError> 를 돌려주므로
그 실패는 «이미 자바 예외»다. unwrap 이 그 보고를 버리고 프로세스를 죽였다 — 실측 패닉 문면이
바로 그 보고를 싣고 있었다:
  called `Result::unwrap()` on an `Err` value: JavaException(java/lang/NoClassDefFoundError)
⇒ 그대로 돌려준다. 시그니처 불변 · 새 enum variant 0 · 호출부 편집 0
(.exception( 846→846 · JavaError:: 527자리 무접촉).

variant 추가안을 버린 이유: let …else / if let 460자리가 조용히 else 로 새고,
jvm.rs 의 반증불가 let(변형이 하나라서 컴파일되는 자리)이 깨진다.

대가(숨기지 않는다): 실패 시 «다른 클래스»의 예외가 온다 ⇒ 잡은 예외를 클래스로 분기하는
제품 12자리는 못 잡고 전파한다. 죽는 것보다 낫지만 무해하지 않다.

축(제품 함수 · 양방향): jvm/tests/test_exception_construction.rs
  전 FAILED(위 패닉) ↔ 후 ok. jvm.rs 를 되돌리면 red.

검사기 문면 3자리도 고쳤다 — 이 변경이 그것을 «거짓»으로 만들었다(술어 무접촉 · 축 재검증 rc=1/rc=0).
잠금의 이유가 「죽는다」에서 「틀린 예외가 온다」로 바뀐다.
… 승인된 원장 2파일 합집합

형제 착지(#75 ddc6c4c · #78 97d2258)로 생긴 원장 재충돌. 게이트③ 2-c⒜ 승인 범위(원장 파일 한정).
양쪽 항목 전건 보존·시간순(최신 상단) · 한쪽 통째 채택(--ours/--theirs) 0.
보존 증명: ours추가 REPORT 18 / STATE 9 · theirs추가 37 / 15 — 소실 0/0 · 충돌 마커 0.
계약 12: 해소면 밖 변경 0 — jvm/src/jvm.rs · jvm/tests/test_exception_construction.rs ·
scripts/check-named-exception-classes-are-loadable.py · worklog 쌍이 핀(394184b) 대비 바이트 동일.
@Jun025
Jun025 merged commit e9910a7 into main Sep 18, 2026
12 checks passed
@Jun025
Jun025 deleted the feat/rustjava-exception-reports-instead-of-aborting branch September 18, 2026 19:51
Jun025 pushed a commit that referenced this pull request Sep 18, 2026
…/main — 승인된 원장 2파일 합집합

형제 착지(#76 e9910a7)로 생긴 원장 재충돌. 게이트③ 2-c⒜ 승인 범위(원장 파일 한정 · 코드 충돌 0).
양쪽 항목 전건 보존·시간순 · 한쪽 통째 채택(--ours/--theirs) 0.
보존 증명: ours추가 REPORT 11 / STATE 7 · theirs추가 17 / 9 — 소실 0/0 · 마커 0 · 엔트리 단위 온전(82엔트리).
계약 12: 해소면 밖 변경 0 — 결정 문서·worklog 쌍이 핀(e175bac) 대비 바이트 동일.
Jun025 pushed a commit that referenced this pull request Sep 19, 2026
… — 원장 2파일 합집합(충돌 PR 은 pull_request CI 가 돌지 않는다)

형제 착지(#76 e9910a7 · #77 ad9eb1a)로 생긴 원장 재충돌. 코드 충돌 0.
★당긴 이유: 충돌 상태에서는 pull_request 워크플로가 «돌지 못해» 이 head 의 검사가 12건 → 1건으로
줄었다(coverage 만). ★그중 named_exception_classes 는 «내가 고친 바로 그 스크립트»를 돌리는 잡이라,
그대로 두면 CI 가 이 회차의 변경을 한 번도 검증하지 못한 채 검수로 간다.
보존: 소실 0/0 · 마커 0 · 해소면 밖 변경 0(검사기 바이트 동일).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant