Skip to content

Fix stack trace rendering for exceptions with identity malfunction#4133

Merged
ramanathan1504 merged 10 commits into
2.xfrom
issue-3933
Jun 11, 2026
Merged

Fix stack trace rendering for exceptions with identity malfunction#4133
ramanathan1504 merged 10 commits into
2.xfrom
issue-3933

Conversation

@ramanathan1504

Copy link
Copy Markdown
Contributor

Fixes #3933

Fix circular reference detection for exceptions with colliding equals/hashCode implementations

  • Use IdentityHashMap-based sets to track visited throwables by identity, preventing false positives in circular reference detection when exceptions override equals/hashCode.
  • Update ThrowableProxy and ThrowableStackTraceRenderer to use identity-based tracking.
  • Add ThrowableCollisionTest to verify correct handling of both colliding and genuinely cyclic exception chains.

@github-project-automation github-project-automation Bot moved this to Changes requested in Log4j pull request tracker Jun 1, 2026
@ramanathan1504

Copy link
Copy Markdown
Contributor Author

@vy

I wasn't able to download the TestFriendlyException-identity-malfunction.patch file directly due to an expired S3 link error on the GitHub attachment. However, I understood the intent of the identity malfunction and have updated the PR with your remarks in mind.

1. Comments Added

I have added your requested comment above all IdentityHashMap instantiations in both ThrowableStackTraceRenderer.java and ThrowableProxy.java:
// IdentityHashMapis needed to deal with customequals()andhashCode() implementations causing collisions

2. Regression Test

Instead of modifying the shared TestFriendlyException class (whose pre-existing cyclic setups and assertions make it difficult to isolate the failure), I have extended ThrowablePatternConverterTest.java with a dedicated, clean regression test: testThrowableProxySerializationCollision().

3. How it Verifies the Bug

This test serializes and deserializes a 3-level exception chain (outer -> middle -> inner) using a local CollidingException class that overrides equals() and hashCode() to compare messages rather than object identity.

  • The test fails. During new ThrowableProxy(outer), the standard HashMap inside the constructor treats the colliding exceptions as circular, setting causeProxy to null and swallowing the inner cause during serialization. The deserialized output only prints 1 Caused by: line instead of 2 (failing the assertion).
  • The test passes successfully. The identity-based collections correctly use reference equality (==), resolving the collision and rendering the full 3-level chain accurately.

If you can share a fresh link or re-upload the TestFriendlyException-identity-malfunction.patch file, I am more than happy to test with your exact patch approach as well and update the code accordingly.

@vy vy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@ramanathan1504, the latest state (2b93e18) LGTM. You can merge this at your convenience.

@github-project-automation github-project-automation Bot moved this from Changes requested to Approved in Log4j pull request tracker Jun 11, 2026
@vy vy changed the title Fix circular reference detection for exceptions with colliding equals… Fix stack trace rendering for exceptions with identity malfunction Jun 11, 2026
@ramanathan1504 ramanathan1504 enabled auto-merge (squash) June 11, 2026 12:14
@ramanathan1504 ramanathan1504 merged commit 019a928 into 2.x Jun 11, 2026
10 checks passed
@ramanathan1504 ramanathan1504 deleted the issue-3933 branch June 11, 2026 12:15
@github-project-automation github-project-automation Bot moved this from Approved to Merged in Log4j pull request tracker Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

ThrowableStackTraceRenderer HashMap key collision causes ArrayIndexOutOfBoundsException with custom exception equals() methods

2 participants