Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5046110

(bf) Direct memory cannot be unreserved while reserving thread sleeps

XMLWordPrintable

    • 06
    • x86
    • windows_xp
    • Verified



        Name: jl125535 Date: 05/12/2004


        FULL PRODUCT VERSION :
        J2SE v1.5beta, 1.4.2_04

        ADDITIONAL OS VERSION INFORMATION :
        Windows, Linux, Solaris

        A DESCRIPTION OF THE PROBLEM :
        I think the implemetation of java.nio.Bits#reserveMemory is not good.
        Here is a part of java.nio.Bits.java source code for v1.5beta.

         1. static synchronized void reserveMemory(long size) {
             ...
         6. if (reservedMemory + size > maxMemory) {
         7. System.gc();
         8. try {
         9. Thread.sleep(100);
        10. } catch (InterruptedException x) {
        11. // Restore interrupt status
        12. Thread.currentThread().interrupt();
        13. }
        14. if (reservedMemory + size > maxMemory)
        15. throw new OutOfMemoryError("Direct buffer memory");
        16. }
        17. reservedMemory += size;
        18. }

        I propose changing sleep(100) into Object.wait(100) or Object.wait() at line 9.

        [Reason]

        The reserveMemory method is "static synchronized".

        It seems like the "sleep(100)" at line 9 is called so that that the
        reservedMemory field used at line 14 can wait for the ReferenceHandler
        thread to call java.nio.Bits#unreserveMemory(long).

        1. static synchronized void unreserveMemory(long size) {
        2. if (reservedMemory > 0) {
        3. reservedMemory -= size;
        4. assert (reservedMemory > -1);
        5. }
        6. }

        However, because the sleep does not lock a Bits.class object,
        and java.nio.Bits#unreserveMemory is also "static synchronied",
        java.nio.Bits#unreserveMemory can not run while the
        java.nio.Bits#reserveMemory is sleeping.

        Here is a proposed implementaion of these methods.
         - change sleep(100) into wait(100) in reserveMemory, and
         - add notifyAll() as last statement in unreserveMemory

         1. static synchronized void reserveMemory(long size) {
            ...
         6. if (reservedMemory + size > maxMemory) {
         7. System.gc();
         8. try {
         9. Bits.class.wait(100);
        10. } catch (InterruptedException x) {
        11. // Restore interrupt status
        12. Thread.currentThread().interrupt();
        13. }
        14. if (reservedMemory + size > maxMemory)
        15. throw new OutOfMemoryError("Direct buffer memory");
        16. }
        17. reservedMemory += size;
        18. }

        1. static synchronized void unreserveMemory(long size) {
        2. if (reservedMemory > 0) {
        3. reservedMemory -= size;
        4. assert (reservedMemory > -1);
        5. }
        6. Bits.class.notifyAll();
        7. }

        I evaluate these implementations by using the same sample
        source code as those of 4879883.
        Even with -XX:MexDirectMemorySize=8k, new implementation work fine.

        ----
        import java.nio.ByteBuffer;
        public class ByteBufferTest {

          public static void main(String[] args) {
            for (;;) {
              ByteBuffer buf = ByteBuffer.allocateDirect(8192);
            }
          }
        }
        ----

        I hope both of v1.4.2_05 and v1.5 release has these implementations,
        or more good implemetations.


        REPRODUCIBILITY :
        This bug can be reproduced always.
        (Incident Review ID: 265100)
        ======================================================================

              mr Mark Reinhold
              jleesunw Jon Lee (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: