Skip to content

Commit 4e20c12

Browse files
jun0claude
andcommitted
[rustjava-zipfile-close-not-registered] feat(zip): ZipFile.close() 등재 — 명시 close 와 try-with-resources 를 ZipClose 픽스처로 잠금
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent bc18487 commit 4e20c12

8 files changed

Lines changed: 64 additions & 1 deletion

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"schema": 1,
3+
"date": "2026-10-01",
4+
"title": "ZipFile.close() 등재",
5+
"taskId": "rustjava-zipfile-close-not-registered",
6+
"summary": "ZipFile.close()V 를 no-op 으로 등재하고 ZipClose 픽스처로 명시 close 와 try-with-resources 를 잠갔다. 착지한 카드 3건을 근거 커밋과 함께 닫았다.",
7+
"proposals": [],
8+
"adoptedProposals": [
9+
"2026-09-12-zip-getinputstream-guard-lock#p0",
10+
"2026-08-27-upstream-sync-s3#p1",
11+
"2026-09-17-lambda-capture-order-and-host-abort#p0",
12+
"2026-09-16-cp-tags-15-18-parse#p1"
13+
],
14+
"declinedProposals": [],
15+
"closedBy": {
16+
"2026-08-27-upstream-sync-s3#p1": "f19acf77 (#67)",
17+
"2026-09-17-lambda-capture-order-and-host-abort#p0": "f19acf77 (#67)",
18+
"2026-09-16-cp-tags-15-18-parse#p1": "dc035936 (#44)"
19+
}
20+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## [2026-10-01] ZipFile.close() 등재 (rustjava-zipfile-close-not-registered)
2+
3+
- 무엇을: `java/util/zip/ZipFile.close()V` 를 no-op 으로 등재했다. 픽스처 `ZipClose` 가 명시 `close()` 와 try-with-resources 를 둘 다 잠근다.
4+
- 왜: `ZipFile` 을 닫는 평범한 게스트가 `NoSuchMethodError: java/util/zip/ZipFile.close:()V` 로 죽었다(픽스처로 재현).
5+
javac 는 try-with-resources 를 자원의 정적 타입에 대한 `invokevirtual ZipFile.close` 로 컴파일하므로(javap 확인) `Closeable` 인터페이스 없이 이 한 메서드로 두 경로가 다 산다.
6+
- 사용자 영향: zip/jar 을 읽고 닫는 게스트가 정상 종료한다. no-op 인 이유는 `<init>` 이 아카이브 전체를 `zipData` 로 복사해 해제할 핸들이 없어서다. 그래서 close 뒤 읽기도 계속 되며, JDK 처럼 `IllegalStateException` 을 던지지는 않는다.
7+
8+
양방향: 수정 전 `cargo test --test test_class` → `Test ZipClose failed … NoSuchMethodError: java/util/zip/ZipFile.close:()V` · 수정 후 ok.
9+
10+
카드 정리: `2026-09-12-zip-getinputstream-guard-lock#p0` 채택(이 회차). 이미 착지한 것을 재측해 닫았다:
11+
- `2026-08-27-upstream-sync-s3#p1` · `2026-09-17-lambda-capture-order-and-host-abort#p0` → PR #67 `f19acf77`(거부 사유가 `ClassFormatError` 메시지까지 간다)
12+
- `2026-09-16-cp-tags-15-18-parse#p1` → PR #44 `dc035936`(ldc 15/16/17 이 「파손」이 아니라 「미지원」으로 보고됨 · javac 는 그 ldc 를 내지 않음을 실측)

‎rustjava-runtime/src/classes/java/util/zip/zip_file.rs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ impl ZipFile {
4444
MethodAccessFlags::PUBLIC,
4545
),
4646
JavaMethodProto::new("entries", "()Ljava/util/Enumeration;", Self::entries, MethodAccessFlags::PUBLIC),
47+
JavaMethodProto::new("close", "()V", Self::close, MethodAccessFlags::PUBLIC),
4748
],
4849
fields: vec![JavaFieldProto::new("zipData", "[B", FieldAccessFlags::PRIVATE)],
4950
access_flags: ClassAccessFlags::PUBLIC,
@@ -133,6 +134,15 @@ impl ZipFile {
133134
Ok(entries.into())
134135
}
135136

137+
// No-op: <init> copies the whole archive into `zipData` and every read reparses that array,
138+
// so there is no file handle to release. Reads after close() keep working rather than
139+
// throwing IllegalStateException as the JDK does.
140+
async fn close(_: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
141+
tracing::debug!("java.util.zip.ZipFile::close({this:?})");
142+
143+
Ok(())
144+
}
145+
136146
async fn get_input_stream(
137147
jvm: &Jvm,
138148
_: &mut RuntimeContext,

‎test-data/ZipClose.class‎

1.23 KB
Binary file not shown.

‎test-data/ZipClose.txt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
close ok
2+
entry true
3+
try-with-resources ok

‎test-data/class-file-versions.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
65.0 UnsupportedCharset.class
138138
52.0 VirtualDispatchSemantics.class
139139
65.0 WideLocals.class
140+
52.0 ZipClose.class
140141
65.0 ZipCorrupt.class
141142
52.0 ZipGuards.class
142143
52.0 attr/DuplicateInnerClasses.class

‎test-data/src/ZipClose.java‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import java.io.File;
2+
import java.util.zip.ZipFile;
3+
4+
// Locks ZipFile.close(): both the explicit call and the try-with-resources path, which javac
5+
// compiles to the same invokevirtual. Reuses test-data/test.jar (a jar is a zip).
6+
class ZipClose {
7+
public static void main(String[] args) throws Exception {
8+
ZipFile zf = new ZipFile(new File("test-data/test.jar"));
9+
zf.close();
10+
System.out.println("close ok");
11+
12+
try (ZipFile twr = new ZipFile(new File("test-data/test.jar"))) {
13+
System.out.println("entry " + (twr.getEntry("test.txt") != null));
14+
}
15+
System.out.println("try-with-resources ok");
16+
}
17+
}

‎test-data/src/ZipGuards.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ public static void main(String[] args) throws Exception {
1515
} catch (NullPointerException e) {
1616
System.out.println("caught NPE");
1717
}
18-
// ZipFile.close() is not registered in this runtime, so there is nothing to release.
18+
// ZipFile.close() is locked separately by ZipClose.
1919
}
2020
}

0 commit comments

Comments
 (0)