Skip to content

fix(#4852): resolve OutOfMemoryError for large files in Cache.java#4869

Merged
yegor256 merged 1 commit into
objectionary:masterfrom
volodya-lombrozo:4852-outofmemory-fix
Feb 10, 2026
Merged

fix(#4852): resolve OutOfMemoryError for large files in Cache.java#4869
yegor256 merged 1 commit into
objectionary:masterfrom
volodya-lombrozo:4852-outofmemory-fix

Conversation

@volodya-lombrozo

@volodya-lombrozo volodya-lombrozo commented Feb 9, 2026

Copy link
Copy Markdown
Member

This PR resolves the OutOfMemoryError issue in Cache.java when handling large files.

Fixes #4852

Summary by CodeRabbit

  • Tests
    • Added test cases to verify SHA-256 hash computation correctness for files of varying sizes.

Copilot AI review requested due to automatic review settings February 9, 2026 10:27
@coderabbitai

coderabbitai Bot commented Feb 9, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The Cache.sha() method is refactored to stream files in chunks rather than loading entire files into memory, addressing an OutOfMemoryError issue with large files. Two test cases are added to verify hash correctness for both large and small files.

Changes

Cohort / File(s) Summary
Hash Streaming Optimization
eo-maven-plugin/src/main/java/org/eolang/maven/Cache.java
Replaced in-memory file read with buffered streaming via try-with-resources; digest computed incrementally in chunks before final digest() call to prevent memory exhaustion.
Hash Verification Tests
eo-maven-plugin/src/test/java/org/eolang/maven/CacheTest.java
Added two test methods: generatesCorrectHashForLargeFile() (100,000 lines) and generatesCorrectHashForTinyFile() ("x") to verify Base64-encoded SHA-256 output correctness.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested reviewers

  • yegor256

Poem

🐰 A file too large made memory weep,
With buffers full, no room to keep,
But streaming chunks, we hop with glee,
Through bytes in sequences, wild and free,
No OutOfMemory error we shall see! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main fix: resolving OutOfMemoryError for large files in Cache.java, directly matching the changeset's streaming approach implementation.
Linked Issues check ✅ Passed The PR successfully implements the streaming SHA-256 hash calculation to resolve OutOfMemoryError and includes test cases for both large and small files, meeting issue #4852 requirements.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the OutOfMemoryError in Cache.java through streaming implementation and corresponding tests; no out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
eo-maven-plugin/src/test/java/org/eolang/maven/CacheTest.java (1)

163-193: Test validates correctness but doesn't exercise the OOM scenario.

The content string (~1.3 MB) is held entirely in memory both in the test and in the p -> content lambda. This test confirms hash correctness for a multi-line file but won't catch an OOM regression since the file is far too small to trigger one. Consider adding a comment clarifying the intent is correctness validation, or (if feasible in CI) testing with a file large enough to exceed a constrained -Xmx.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

🚀 Performance Analysis

All benchmarks are within the acceptable range. No critical degradation detected (threshold is 100%). Please refer to the detailed report for more information.

Click to see the detailed report
Test Base Score PR Score Change % Change Unit Mode
benchmarks.XmirBench.xmirToEO 205.086 170.512 -34.574 -16.86% ms/op Average Time

✅ Performance gain: benchmarks.XmirBench.xmirToEO is faster by 34.574 ms/op (16.86%)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses OutOfMemoryError risk in Cache hashing by switching SHA-256 computation from loading full file bytes into memory to a streaming approach, and updates tests around SHA generation.

Changes:

  • Replace Files.readAllBytes(...) hashing with buffered streaming hashing in Cache.sha(...).
  • Remove the related puzzle/todo from Cache.java.
  • Add new tests that assert SHA-256 hash file contents for “large” and tiny inputs.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
eo-maven-plugin/src/main/java/org/eolang/maven/Cache.java Streams file content into MessageDigest to avoid hashing large files via readAllBytes.
eo-maven-plugin/src/test/java/org/eolang/maven/CacheTest.java Adds additional SHA-256 verification tests for larger and tiny content sizes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +170 to +176
final int lines = 100_000;
final StringBuilder builder = new StringBuilder(lines * 10);
IntStream.range(0, lines).forEach(
i -> builder.append("Line ").append(i).append('\n')
);
final String content = builder.toString();
Files.writeString(source, content, StandardCharsets.UTF_8);

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "large file" test still builds the entire file content in memory (StringBuilder + content String + content.getBytes for expected digest). That makes the test itself memory-heavy and it won’t catch a regression back to Files.readAllBytes (the old implementation would still pass at this size). Consider generating/writing the file incrementally and computing the expected SHA-256 via a streaming digest as well, so the test stays low-memory and can be scaled without holding the full content in RAM.

Copilot uses AI. Check for mistakes.
Comment on lines +195 to +219
@Test
void generatesCorrectHashForTinyFile(
@Mktmp final Path temp
) throws IOException, NoSuchAlgorithmException {
final var cache = temp.resolve("cache");
Files.createDirectories(cache);
final var source = temp.resolve("tiny.txt");
final String content = "x";
Files.writeString(source, content, StandardCharsets.UTF_8);
final var target = temp.resolve("out.txt");
final var tail = source.getFileName();
new Cache(cache, p -> content).apply(source, target, tail);
MatcherAssert.assertThat(
"SHA-256 hash file has incorrect content for tiny file",
Files.readString(
cache.resolve(String.format("%s.sha256", tail)),
StandardCharsets.UTF_8
),
Matchers.equalTo(
Base64.getEncoder().encodeToString(
MessageDigest.getInstance("SHA-256")
.digest(content.getBytes(StandardCharsets.UTF_8))
)
)
);

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new tiny-file hash test largely overlaps with the existing writesCorrectShaHash() coverage (both validate SHA-256 file contents for a small input). Unless it’s guarding a specific edge case, consider removing it or turning these into a single parameterized test to avoid duplicated setup/logic.

Copilot uses AI. Check for mistakes.
@volodya-lombrozo

Copy link
Copy Markdown
Member Author

@yegor256 could you have a look, please?

@volodya-lombrozo

Copy link
Copy Markdown
Member Author

@yegor256 friendly reminder

@yegor256 yegor256 merged commit b77bf49 into objectionary:master Feb 10, 2026
31 of 32 checks passed
@0crat

0crat commented Feb 10, 2026

Copy link
Copy Markdown

@volodya-lombrozo Thanks for the contribution! You've earned +16 points for your code submission. This reward follows our team policy which awards 16 points for reviews provided, plus additional points based on your hits-of-code contribution. Please keep them coming! Your running score is +446; don't forget to check your Zerocracy account too.

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.

OutOfMemoryError Occurs with Large Files in Cache.java

4 participants