Skip to content

Refactor FastPiped and Proxy streams to use java.lang.ref.Cleaner instead of finalize()#1522

Open
aniruddhkorde9-dot wants to merge 5 commits into
jenkinsci:masterfrom
aniruddhkorde9-dot:master
Open

Refactor FastPiped and Proxy streams to use java.lang.ref.Cleaner instead of finalize()#1522
aniruddhkorde9-dot wants to merge 5 commits into
jenkinsci:masterfrom
aniruddhkorde9-dot:master

Conversation

@aniruddhkorde9-dot

Copy link
Copy Markdown

This PR modernizes resource cleanup in several remoting streams by replacing the deprecated finalize() method with java.lang.ref.Cleaner.

Classes updated:

  • FastPipedInputStream
  • FastPipedOutputStream
  • ProxyOutputStream
    (plus related stream cleanup logic)

Changes made:

  • Removed protected void finalize() overrides.
  • Implemented a static Cleaner instance.
  • Created static CleanupTask classes (implementing Runnable) to handle the shutdown logic.
  • Used WeakReference inside the cleanup tasks where necessary to ensure the target objects remain eligible for garbage collection and to prevent memory leaks.

Testing done

  • Ran the standard Jenkins remoting test suite locally using mvn test.
  • Verified that all tests (2,103 tests) completed with BUILD SUCCESS and 0 failures.

@aniruddhkorde9-dot

Copy link
Copy Markdown
Author

Hi team, I have updated the PR to resolve the Spotless formatting violations and the SpotBugs warnings in ProxyWriter.java. All CI checks are now passing and this is ready for review. Thank you!

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 modernizes cleanup for several remoting stream implementations by replacing deprecated finalize()-based cleanup with java.lang.ref.Cleaner, aiming to ensure remote exports/unexports and wakeups still occur when streams are abandoned.

Changes:

  • Replaced finalize() overrides with Cleaner registrations and Runnable cleanup tasks across proxy and fast-pipe stream implementations.
  • Adjusted remote cleanup signaling/unexport logic for ProxyWriter/ProxyOutputStream.
  • Added GC-time wakeup/closure behavior for FastPipedInputStream/FastPipedOutputStream using cleaner tasks and weak references.

Reviewed changes

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

File Description
src/main/java/hudson/remoting/ProxyWriter.java Removes finalizer and adds Cleaner registration + cleanup task for abandoned remote writers.
src/main/java/hudson/remoting/ProxyOutputStream.java Removes finalizer and adds Cleaner registration + cleanup task intended to unexport abandoned remote streams.
src/main/java/hudson/remoting/FastPipedOutputStream.java Replaces finalizer-close with a cleaner task that marks the connected input side as closed and notifies waiters.
src/main/java/hudson/remoting/FastPipedInputStream.java Replaces finalizer-close with a cleaner task that notifies waiters on the buffer monitor and stores a Cleanable.

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

@@ -412,11 +395,6 @@ protected void execute(final Channel channel) {
}
channel.pipeWriter.submit(ioId, () -> {
channel.unexport(oid, createdAt, false);
Comment on lines +483 to +484
// Sends the dead signal using all THREE required arguments
channel.send(new NotifyDeadWriter(channel, null, oid));
Comment on lines 90 to 93
this.channel = channel;
this.oid = oid;

CLEANER.register(this, new CleanupTask(channel, oid));
window = channel.getPipeWindow(oid);
Comment on lines +65 to +67
public ProxyOutputStream() {
this.cleanable = CLEANER.register(this, new CleanupTask(null, -1));
}
Comment on lines +40 to +42
private static final Cleaner CLEANER = Cleaner.create();
private final Cleaner.Cleanable cleanable;

Comment on lines +465 to +479
private static class CleanupTask implements Runnable {
private final Channel channel;
private final int oid;

CleanupTask(Channel channel, int oid) {
this.channel = channel;
this.oid = oid;
}

@Override
public void run() {
if (channel != null && oid != -1) {
try {
channel.send(new Unexport(channel.newIoId(), oid));
} catch (Exception e) {
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.

2 participants