Skip to content
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
20 changes: 20 additions & 0 deletions docs/worklog/2026-10-01-zipfile-close.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"schema": 1,
"date": "2026-10-01",
"title": "ZipFile.close() 등재",
"taskId": "rustjava-zipfile-close-not-registered",
"summary": "ZipFile.close()V 를 no-op 으로 등재하고 ZipClose 픽스처로 명시 close 와 try-with-resources 를 잠갔다. 착지한 카드 3건을 근거 커밋과 함께 닫았다.",
"proposals": [],
"adoptedProposals": [
"2026-09-12-zip-getinputstream-guard-lock#p0",
"2026-08-27-upstream-sync-s3#p1",
"2026-09-17-lambda-capture-order-and-host-abort#p0",
"2026-09-16-cp-tags-15-18-parse#p1"
],
"declinedProposals": [],
"closedBy": {
"2026-08-27-upstream-sync-s3#p1": "f19acf77 (#67)",
"2026-09-17-lambda-capture-order-and-host-abort#p0": "f19acf77 (#67)",
"2026-09-16-cp-tags-15-18-parse#p1": "dc035936 (#44)"
}
}
12 changes: 12 additions & 0 deletions docs/worklog/2026-10-01-zipfile-close.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## [2026-10-01] ZipFile.close() 등재 (rustjava-zipfile-close-not-registered)

- 무엇을: `java/util/zip/ZipFile.close()V` 를 no-op 으로 등재했다. 픽스처 `ZipClose` 가 명시 `close()` 와 try-with-resources 를 둘 다 잠근다.
- 왜: `ZipFile` 을 닫는 평범한 게스트가 `NoSuchMethodError: java/util/zip/ZipFile.close:()V` 로 죽었다(픽스처로 재현).
javac 는 try-with-resources 를 자원의 정적 타입에 대한 `invokevirtual ZipFile.close` 로 컴파일하므로(javap 확인) `Closeable` 인터페이스 없이 이 한 메서드로 두 경로가 다 산다.
- 사용자 영향: zip/jar 을 읽고 닫는 게스트가 정상 종료한다. no-op 인 이유는 `<init>` 이 아카이브 전체를 `zipData` 로 복사해 해제할 핸들이 없어서다. 그래서 close 뒤 읽기도 계속 되며, JDK 처럼 `IllegalStateException` 을 던지지는 않는다.

양방향: 수정 전 `cargo test --test test_class` → `Test ZipClose failed … NoSuchMethodError: java/util/zip/ZipFile.close:()V` · 수정 후 ok.

카드 정리: `2026-09-12-zip-getinputstream-guard-lock#p0` 채택(이 회차). 이미 착지한 것을 재측해 닫았다:
- `2026-08-27-upstream-sync-s3#p1` · `2026-09-17-lambda-capture-order-and-host-abort#p0` → PR #67 `f19acf77`(거부 사유가 `ClassFormatError` 메시지까지 간다)
- `2026-09-16-cp-tags-15-18-parse#p1` → PR #44 `dc035936`(ldc 15/16/17 이 「파손」이 아니라 「미지원」으로 보고됨 · javac 는 그 ldc 를 내지 않음을 실측)
10 changes: 10 additions & 0 deletions rustjava-runtime/src/classes/java/util/zip/zip_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ impl ZipFile {
MethodAccessFlags::PUBLIC,
),
JavaMethodProto::new("entries", "()Ljava/util/Enumeration;", Self::entries, MethodAccessFlags::PUBLIC),
JavaMethodProto::new("close", "()V", Self::close, MethodAccessFlags::PUBLIC),
],
fields: vec![JavaFieldProto::new("zipData", "[B", FieldAccessFlags::PRIVATE)],
access_flags: ClassAccessFlags::PUBLIC,
Expand Down Expand Up @@ -133,6 +134,15 @@ impl ZipFile {
Ok(entries.into())
}

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

Ok(())
}

async fn get_input_stream(
jvm: &Jvm,
_: &mut RuntimeContext,
Expand Down
Binary file added test-data/ZipClose.class
Binary file not shown.
3 changes: 3 additions & 0 deletions test-data/ZipClose.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
close ok
entry true
try-with-resources ok
1 change: 1 addition & 0 deletions test-data/class-file-versions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
65.0 UnsupportedCharset.class
52.0 VirtualDispatchSemantics.class
65.0 WideLocals.class
52.0 ZipClose.class
65.0 ZipCorrupt.class
52.0 ZipGuards.class
52.0 attr/DuplicateInnerClasses.class
Expand Down
17 changes: 17 additions & 0 deletions test-data/src/ZipClose.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import java.io.File;
import java.util.zip.ZipFile;

// Locks ZipFile.close(): both the explicit call and the try-with-resources path, which javac
// compiles to the same invokevirtual. Reuses test-data/test.jar (a jar is a zip).
class ZipClose {
public static void main(String[] args) throws Exception {
ZipFile zf = new ZipFile(new File("test-data/test.jar"));
zf.close();
System.out.println("close ok");

try (ZipFile twr = new ZipFile(new File("test-data/test.jar"))) {
System.out.println("entry " + (twr.getEntry("test.txt") != null));
}
System.out.println("try-with-resources ok");
}
}
2 changes: 1 addition & 1 deletion test-data/src/ZipGuards.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public static void main(String[] args) throws Exception {
} catch (NullPointerException e) {
System.out.println("caught NPE");
}
// ZipFile.close() is not registered in this runtime, so there is nothing to release.
// ZipFile.close() is locked separately by ZipClose.
}
}
Loading