From owner-freebsd-java@FreeBSD.ORG Tue Oct 25 23:17:04 2005 Return-Path: X-Original-To: freebsd-java@freebsd.org Delivered-To: freebsd-java@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5DE5C16A41F for ; Tue, 25 Oct 2005 23:17:04 +0000 (GMT) (envelope-from landonf@threerings.net) Received: from mail.earth.threerings.net (mail.earth.threerings.net [64.81.51.57]) by mx1.FreeBSD.org (Postfix) with ESMTP id 599CF43D48 for ; Tue, 25 Oct 2005 23:17:03 +0000 (GMT) (envelope-from landonf@threerings.net) Received: from [192.168.50.11] (timor.sea.earth.threerings.net [192.168.50.11]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client certificate requested) by mail.earth.threerings.net (Postfix) with ESMTP id C0C20650E for ; Tue, 25 Oct 2005 16:17:02 -0700 (PDT) Mime-Version: 1.0 (Apple Message framework v623) To: freebsd-java@freebsd.org Message-Id: Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg=pgp-sha1; boundary="Apple-Mail-11--496316617" From: Landon Fuller Date: Tue, 25 Oct 2005 16:17:02 -0700 Content-Transfer-Encoding: 7bit X-Pgp-Agent: GPGMail 1.0.2 X-Mailer: Apple Mail (2.623) Subject: [PATCH] Sun Bug #4879883: Allocating direct buffers causes OutOfMemoryError X-BeenThere: freebsd-java@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Porting Java to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Oct 2005 23:17:04 -0000 --Apple-Mail-11--496316617 Content-Type: multipart/mixed; boundary=Apple-Mail-10--496316627 --Apple-Mail-10--496316627 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed From http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4879883 A DESCRIPTION OF THE PROBLEM : Allocating a direct byte buffer may give an OutOfMemoryError, even when plenty of memory is available. Although not used in the test case below, in my application this occurs when reading a socket channel ---- We ran into this bug with jdk1.4.2; A simple reproduction case is included in the referenced Sun bug report. This bug was fixed in 1.5.0 and 1.4.2_05. I've back-ported Sun's changes from the 1.5.0 source. The patch (for 1.4.2-p7) is attached below. Please let me know if you have any questions, -landonf --Apple-Mail-10--496316627 Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name="reserveMemory-2.diff" Content-Disposition: attachment; filename=reserveMemory-2.diff Only in reserveMemory: cscope.out diff -ru bsdjdk/j2se/src/share/classes/java/nio/Bits.java reserveMemory/j2se/src/share/classes/java/nio/Bits.java --- j2se/src/share/classes/java/nio/Bits.java Fri May 13 18:04:07 2005 +++ j2se/src/share/classes/java/nio/Bits.java Mon Oct 24 11:41:10 2005 @@ -600,24 +600,39 @@ // A user-settable upper limit on the maximum amount of allocatable // direct buffer memory. This value may be changed during VM // initialization if it is launched with "-XX:MaxDirectMemorySize=". - private static long maxMemory = VM.maxDirectMemory(); - private static long reservedMemory = 0; + private static volatile long maxMemory = VM.maxDirectMemory(); + private static volatile long reservedMemory = 0; private static boolean memoryLimitSet = false; // These methods should be called whenever direct memory is allocated or // freed. They allow the user to control the amount of direct memory // which a process may access. All sizes are specified in bytes. - static synchronized void reserveMemory(long size) { - if (!memoryLimitSet && VM.isBooted()) { - maxMemory = VM.maxDirectMemory(); - memoryLimitSet = true; + static void reserveMemory(long size) { + + synchronized (Bits.class) { + if (!memoryLimitSet && VM.isBooted()) { + maxMemory = VM.maxDirectMemory(); + memoryLimitSet = true; + } + if (size <= maxMemory - reservedMemory) { + reservedMemory += size; + return; + } + } + + System.gc(); + try { + Thread.sleep(100); + } catch (InterruptedException x) { + // Restore interrupt status + Thread.currentThread().interrupt(); } - if (reservedMemory + size > maxMemory) { - System.gc(); + synchronized (Bits.class) { if (reservedMemory + size > maxMemory) - throw new OutOfMemoryError(); + throw new OutOfMemoryError("Direct buffer memory"); + reservedMemory += size; } - reservedMemory += size; + } static synchronized void unreserveMemory(long size) { diff -ru bsdjdk/j2se/src/share/classes/sun/misc/VM.java reserveMemory/j2se/src/share/classes/sun/misc/VM.java --- j2se/src/share/classes/sun/misc/VM.java Fri May 13 18:04:16 2005 +++ j2se/src/share/classes/sun/misc/VM.java Tue Oct 25 15:04:28 2005 @@ -128,9 +128,14 @@ return booted; } - // A user-settable upper limit on the maximum amount of allocatable - // direct buffer memory. This value may be changed during VM - // initialization if "java" is launched with "-XX:MaxDirectMemorySize=". + // A user-settable upper limit on the maximum amount of allocatable direct + // buffer memory. This value may be changed during VM initialization if + // "java" is launched with "-XX:MaxDirectMemorySize=". + // + // The initial value of this field is arbitrary; during JRE initialization + // it will be reset to the value specified on the command line, if any, + // otherwise to Runtime.getRuntime.maxDirectMemory(). + // private static long directMemory = 64 * 1024 * 1024; // If this method is invoked during VM initialization, it initializes the @@ -140,6 +145,7 @@ // // If this method is invoked after the VM is booted, it returns the // maximum amount of allocatable direct buffer memory. + // public static long maxDirectMemory() { if (booted) return directMemory; @@ -148,9 +154,16 @@ String s = (String)p.remove("sun.nio.MaxDirectMemorySize"); System.setProperties(p); - long l = (s != null ? Long.parseLong(s) : -1); - if (l > -1) - directMemory = l; + if (s != null) { + if (s.equals("-1")) { + // -XX:MaxDirectMemorySize not given, take default + directMemory = Runtime.getRuntime().maxMemory(); + } else { + long l = Long.parseLong(s); + if (l > -1) + directMemory = l; + } + } return directMemory; } --Apple-Mail-10--496316627-- --Apple-Mail-11--496316617 content-type: application/pgp-signature; x-mac-type=70674453; name=PGP.sig content-description: This is a digitally signed message part content-disposition: inline; filename=PGP.sig content-transfer-encoding: 7bit -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (Darwin) iD8DBQFDXrzulplZCE/15mMRAiW0AJ45tPPjwbB7mGpcMWTxbuRKvisM8QCdG0Em BzchWS4vPPVMb12PRSYaZlw= =2OaH -----END PGP SIGNATURE----- --Apple-Mail-11--496316617--