Skip to content
Closed
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
4 changes: 3 additions & 1 deletion src/java.base/share/classes/sun/nio/ch/IOUtil.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -259,6 +259,7 @@ static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
vec.clearRefs(j);
}
}
vec.release();
}
}

Expand Down Expand Up @@ -470,6 +471,7 @@ static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
vec.clearRefs(j);
}
}
vec.release();
}
}

Expand Down
56 changes: 33 additions & 23 deletions src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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;
// per carrier-thread IOVecWrapper
private static final TerminatingThreadLocal<IOVecWrapper[]> IOV_CACHE = new TerminatingThreadLocal<>() {
@Override
protected IOVecWrapper[] initialValue() {
return new IOVecWrapper[1]; // one slot cache
}
public void run() {
obj.free();
@Override
protected void threadTerminated(IOVecWrapper[] cache) {
IOVecWrapper wrapper = cache[0];
if (wrapper != null) {
wrapper.vecArray.free();
}
}
}

// per carrier-thread IOVecWrapper
private static final CarrierThreadLocal<IOVecWrapper> cached = new CarrierThreadLocal<>();
};

private IOVecWrapper(int size) {
this.size = size;
Expand All @@ -95,18 +95,28 @@ private IOVecWrapper(int size) {
}

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) {
Expand Down