diff --git a/src/java.base/share/classes/sun/nio/ch/IOUtil.java b/src/java.base/share/classes/sun/nio/ch/IOUtil.java index 55522fd717d..d86d6decb14 100644 --- a/src/java.base/share/classes/sun/nio/ch/IOUtil.java +++ b/src/java.base/share/classes/sun/nio/ch/IOUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -259,6 +259,7 @@ public final class IOUtil { vec.clearRefs(j); } } + vec.release(); } } @@ -470,6 +471,7 @@ public final class IOUtil { vec.clearRefs(j); } } + vec.release(); } } diff --git a/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java b/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java index d33d7f55d0b..1c78e45a2d8 100644 --- a/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java +++ b/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,7 @@ package sun.nio.ch; import java.nio.ByteBuffer; - -import jdk.internal.misc.CarrierThreadLocal; -import jdk.internal.ref.CleanerFactory; +import jdk.internal.misc.TerminatingThreadLocal; /** * Manipulates a native array of iovec structs on Solaris: @@ -71,18 +69,20 @@ class IOVecWrapper { // Address size in bytes static final int addressSize; - private static class Deallocator implements Runnable { - private final AllocatedNativeObject obj; - Deallocator(AllocatedNativeObject obj) { - this.obj = obj; - } - public void run() { - obj.free(); - } - } - // per carrier-thread IOVecWrapper - private static final CarrierThreadLocal cached = new CarrierThreadLocal<>(); + private static final TerminatingThreadLocal IOV_CACHE = new TerminatingThreadLocal<>() { + @Override + protected IOVecWrapper[] initialValue() { + return new IOVecWrapper[1]; // one slot cache + } + @Override + protected void threadTerminated(IOVecWrapper[] cache) { + IOVecWrapper wrapper = cache[0]; + if (wrapper != null) { + wrapper.vecArray.free(); + } + } + }; private IOVecWrapper(int size) { this.size = size; @@ -95,18 +95,28 @@ class IOVecWrapper { } static IOVecWrapper get(int size) { - IOVecWrapper wrapper = cached.get(); - if (wrapper != null && wrapper.size < size) { - // not big enough; eagerly release memory - wrapper.vecArray.free(); - wrapper = null; + IOVecWrapper[] cache = IOV_CACHE.get(); + IOVecWrapper wrapper = cache[0]; + if (wrapper != null) { + cache[0] = null; + if (wrapper.size < size) { + // not big enough; eagerly release memory + wrapper.vecArray.free(); + wrapper = null; + } } + return (wrapper != null) ? wrapper : new IOVecWrapper(size); + } + + void release() { + IOVecWrapper[] cache = IOV_CACHE.get(); + IOVecWrapper wrapper = cache[0]; if (wrapper == null) { - wrapper = new IOVecWrapper(size); - CleanerFactory.cleaner().register(wrapper, new Deallocator(wrapper.vecArray)); - cached.set(wrapper); + cache[0] = this; + } else { + // slot already used + vecArray.free(); } - return wrapper; } void setBuffer(int i, ByteBuffer buf, int pos, int rem) {