JDK-4863423 : Util buffer cache uses wrong release strategy
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 1.4.2,5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_7,windows_2000
  • CPU: x86,sparc
  • Submitted: 2003-05-13
  • Updated: 2003-10-06
  • Resolved: 2003-05-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
1.4.2_02 02Fixed
Related Reports
Duplicate :  
The Util bytebuffer cache holds three buffers per thread to reuse for IOUtil operations such as read/write for cases where a temporary native buffer is needed. However, the cache fills up with the first three buffers used, and once that occurs, any additional buffers are ignored.

Consider the following case: the three buffers are filled with small buffers, and then a large read operation is initiated in a tight readFully loop. A large buffer is created for the read, and so the three cached buffers are skipped over and a large temp buffer is created. Some small fraction of this large buffer is filled with the read, and the large temp buffer is discarded but since the cache is full it is discarded. Then the next iteration of the readFully loop causes another, slightly smaller buffer to be created, and so on, causing a large number of large temp buffers to be created and discarded, and the cache is no help at all.

This can be rectified by modifying the cache to hold onto the larger buffers rather than the smaller ones.

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.4.2_02 tiger FIXED IN: 1.4.2_02 tiger INTEGRATED IN: 1.4.2_02 tiger tiger-b08 VERIFIED IN: 1.4.2_02

WORK AROUND When doing large reads or writes, allocate your own direct buffers rather than rely upon the NIO code to do that internally.

SUGGESTED FIX static void releaseTemporaryDirectBuffer(ByteBuffer buf) { // Put it in an empty slot if such exists for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { SoftReference ref = (SoftReference)(bufferPool[i].get()); if ((ref == null) || (ref.get() == null)) { bufferPool[i].set(new SoftReference(buf)); return; } } // Otherwise replace a smaller one in the cache if such exists for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { SoftReference ref = (SoftReference)(bufferPool[i].get()); ByteBuffer inCacheBuf = (ByteBuffer)ref.get(); if (buf.capacity() > inCacheBuf.capacity()) { bufferPool[i].set(new SoftReference(buf)); return; } } }

EVALUATION The cache will now hold on to the larger buffers. Those buffers are referenced by a soft reference so that the memory can be reclaimed, although the garbage collector is not aware of how large the direct buffers being held are. ###@###.### 2003-05-16