JDK-4932826 : assert(minimum_desired_capacity <= maximum_desired_capacity,"sanity check")
  • Type: Bug
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: 5.0
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2003-10-06
  • Updated: 2006-02-02
  • Resolved: 2006-02-02
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.
Other
5.0 b36Fixed
Related Reports
Relates :  
Description
The following assertion occurs when building the J2SE workspace with a fastdebug
version of libjvm.so. It occurs with both Solaris x86 and Linux. The issue 
originally arose with a build of service_hs_baseline but changes in 
service_hs_baseline eliminated by grabbing a fastdebug build from PRT. The
older in /net/prt-web is 20031004095511.ovrskeek.


#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  Internal Error (/net/prt-solx86-q1-2/PrtBuildDir/workspace/src/share/vm/memory/tenuredGeneration.cpp, 139), pid=13741, tid=4
#
# Java VM: Java HotSpot(TM) Client VM (20031004095511.ovrskeek.main_baseline-debug mixed mode)
#
# Error: assert(minimum_desired_capacity <= maximum_desired_capacity,"sanity check")

---------------  T H R E A D  ---------------

Current thread (0x080e64e0):  VMThread [id=4]

Stack: [0xddf01000,0xddf41000),  sp=0xddf4050c,  free space=253k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x5e0413]
V  [libjvm.so+0x1eb15d]
V  [libjvm.so+0x58b62e]
V  [libjvm.so+0x21029a]
V  [libjvm.so+0x1a9f4a]
V  [libjvm.so+0x210671]
V  [libjvm.so+0x5f423c]
V  [libjvm.so+0x5f3daf]
V  [libjvm.so+0x5f2b41]
V  [libjvm.so+0x5f31ae]
V  [libjvm.so+0x5f282f]
V  [libjvm.so+0x4f8eca]

VM_Operation (0x0803fd60): generation collection for allocation, mode: safepoint, requested by thread 0x0808de90


---------------  P R O C E S S  ---------------

Java Threads: ( => current thread )
  0x08124ff0 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=9]
  0x08123220 JavaThread "CompilerThread0" daemon [_thread_blocked, id=8]
  0x08121df0 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=7]
  0x080ec118 JavaThread "Finalizer" daemon [_thread_blocked, id=6]
  0x080e9b60 JavaThread "Reference Handler" daemon [_thread_blocked, id=5]
  0x0808de90 JavaThread "main" [_thread_blocked, id=1]

Other Threads:
=>0x080e64e0 VMThread [id=4]
  0x08126cd8 WatcherThread [id=10]

VM state:at safepoint (normal execution)

VM Mutex/Monitor currently owned by a thread:  ([mutex/lock_event])
[0x0808c680/0x0808c6e8] Threads_lock - owner thread: 0x080e64e0
[0x0808cf08/0x0808cf60] Heap_lock - owner thread: 0x0808de90

Heap
 def new generation   total 4864K, used 0K [0xc7800000, 0xc7ce0000, 0xc8bb0000)
  eden space 4736K,   0% used [0xc7800000, 0xc7800000, 0xc7ca0000)
  from space 128K,   0% used [0xc7cc0000, 0xc7cc0000, 0xc7ce0000)
  to   space 128K,   0% used [0xc7ca0000, 0xc7ca0000, 0xc7cc0000)
 tenured generation   total 60928K, used 44774K [0xc8bb0000, 0xcc730000, 0xd7800000)
   the space 60928K,  73% used [0xc8bb0000, 0xcb769948, 0xcb769a00, 0xcc730000)
 compacting perm gen  total 4096K, used 2592K [0xd7800000, 0xd7c00000, 0xdb800000)
   the space 4096K,  63% used [0xd7800000, 0xd7a88078, 0xd7a88200, 0xd7c00000)

Dynamic libraries:
0x08050000 	../../../build/solaris-i586/bin/javac
0xdfb70000 	/usr/lib/libthread.so.1
0xdfbb0000 	/usr/lib/libdl.so.1
0xdfac0000 	/usr/lib/libc.so.1
0xde000000 	/export/Scratch/alanb/builds/service_sdk_baseline/build/solaris-i586/lib/i386/client/libjvm.so
0xdfa50000 	/usr/lib/libsocket.so.1
0xdfa30000 	/usr/lib/libsched.so.1
0xdfa00000 	/usr/lib/libCrun.so.1
0xdf9e0000 	/usr/lib/libm.so.1
0xdf940000 	/usr/lib/libnsl.so.1
0xdfa70000 	/usr/lib/libw.so.1
0xdf910000 	/usr/lib/libmp.so.2
0xdf8d0000 	/export/Scratch/alanb/builds/service_sdk_baseline/build/solaris-i586/lib/i386/native_threads/libhpi.so
0xdf880000 	/export/Scratch/alanb/builds/service_sdk_baseline/build/solaris-i586/lib/i386/libverify.so
0xdf850000 	/export/Scratch/alanb/builds/service_sdk_baseline/build/solaris-i586/lib/i386/libjava.so
0xdf810000 	/export/Scratch/alanb/builds/service_sdk_baseline/build/solaris-i586/lib/i386/libzip.so

VM Arguments:
jvm_args: -Dapplication.home=/export/Scratch/alanb/builds/service_sdk_baseline/build/solaris-i586 -Xms8m -XX:ThreadStackSize=768 -Xms64m -Xmx256m -Xmaxf1
java_command: com.sun.tools.javac.Main -classpath ../../../build/solaris-i586/classes -bootclasspath ../../../build/solaris-i586/lib/jce.jar:../../../build/solaris-i586/lib/jsse.jar -sourcepath ../../../build/solaris-i586/gensrc:../../../src/solaris/classes:../../../src/share/classes -d ../../../build/solaris-i586/classes -encoding ascii -source 1.5 ../../../src/share/classes/java/awt/PointerInfo.java ../../../src/share/classes/java/awt/MouseInfo.java ../../../src/share/classes/java/awt/geom/Point2D.java ../../../src/share/classes/java/awt/Event.java ../../../src/share/classes/java/awt/EventQueue.java ../../../src/share/classes/java/awt/EventDispatchThread.java ../../../src/share/classes/java/awt/Graphics.java ../../../src/share/classes/java/awt/FontMetrics.java ../../../src/share/classes/java/awt/SystemColor.java ../../../src/share/classes/java/awt/Dimension.java ../../../src/share/classes/java/awt/Point.java ../../../src/share/classes/java/awt/Rectangle.java ../../../src/share/classes/java/awt/Polygon.java ../../../src/share/classes/java/awt/Shape.java ../../../src/share/classes/sun/awt/ConstrainableGraphics.java ../../../src/share/classes/sun/awt/SunHints.java ../../../src/share/classes/java/awt/Robot.java ../../../src/share/classes/java/awt/Toolkit.java ../../../src/share/classes/java/awt/Component.java ../../../src/share/classes/java/awt/ComponentOrientation.java ../../../src/share/classes/java/awt/Conditional.java ../../../src/share/classes/java/awt/Container.java ../../../src/share/classes/java/awt/Button.java ../../../src/share/classes/java/awt/Scrollbar.java ../../../src/share/classes/java/awt/ScrollPane.java ../../../src/share/classes/java/awt/ScrollPaneAdjustable.java ../../../src/share/classes/sun/awt/ScrollPaneWheelScroller.java ../../../src/share/classes/java/awt/MenuContainer.java ../../../src/share/classes/java/awt/MenuComponent.java ../../../src/share/classes/java/awt/MenuBar.java ../../../src/share/classes/java/awt/Menu.java ../../../src/share/cl

Environment Variables:
PATH=/usr/ccs/bin:/java/devtools/i586/SUNWspro/SOS8/bin:/java/devtools/i586/bin:/home/ab23780/bin:/usr/openwin/bin:/usr/dt/bin:/usr/bin:/usr/sbin:/sbin:/usr/ucb:/usr/dist/local/exe:/usr/dist/exe:/usr/lib/lp/postscript:.
LD_LIBRARY_PATH=/export/Scratch/alanb/builds/service_sdk_baseline/build/solaris-i586/lib/i386/client:/export/Scratch/alanb/builds/service_sdk_baseline/build/solaris-i586/lib/i386:/export/Scratch/alanb/builds/service_sdk_baseline/build/solaris-i586/../lib/i386
SHELL=/bin/sh
DISPLAY=mrbean:0.0


---------------  S Y S T E M  ---------------

OS:                        Solaris 8 1/01 s28x_u3wos_08 INTEL
           Copyright 2000 Sun Microsystems, Inc.  All Rights Reserved.
                           Assembled 28 November 2000

uname:SunOS 5.8 Generic_108529-05 i86pc  (T1 libthread)
rlimit: STACK 8480k, CORE infinity, NOFILE 1024, AS infinity
load average:0.79 0.76 0.64

CPU:total 1(active 1) family 6, cmov, cx8, fxsr, mmx

Memory: 4k page, physical 261748k(96988k free)


--

$ dbx $JAVA_HOME/bin/javac core
For information about new features see `help changes'
To remove this message, put `dbxenv suppress_startup_message 7.1' in your .dbxrc
Reading javac
dbx: internal warning: writable memory segment 0xdf8b0000[16384] of size 0 in core
core file header read successfully
Reading ld.so.1
Reading libthread.so.1
Reading libdl.so.1
Reading libc.so.1
Reading libjvm.so
Reading libsocket.so.1
Reading libsched.so.1
Reading libCrun.so.1
Reading libm.so.1
Reading libnsl.so.1
Reading libw.so.1
Reading libmp.so.2
Reading libhpi.so
Reading libverify.so
Reading libjava.so
Reading libzip.so
detected a multithreaded program
t@null (l@5) terminated by signal ABRT (Abort)
0xdfb86971: __sigprocmask+0x000c:	jae    __sigprocmask+0x21 <0xdfb86986>
dbx: warning: can't find file "/PrtBuildDir/workspace/build/solaris/solaris_i486_compiler1/fastdebug/vmError.o"
dbx: warning: see `help finding-files'
dbx: warning: can't find file "/PrtBuildDir/workspace/build/solaris/solaris_i486_compiler1/fastdebug/debug.o"
dbx: warning: can't find file "/PrtBuildDir/workspace/build/solaris/solaris_i486_compiler1/fastdebug/tenuredGeneration.o"
dbx: warning: can't find file "/PrtBuildDir/workspace/build/solaris/solaris_i486_compiler1/fastdebug/genCollectedHeap.o"
dbx: warning: can't find file "/PrtBuildDir/workspace/build/solaris/solaris_i486_compiler1/fastdebug/collectorPolicy.o"
dbx: warning: can't find file "/PrtBuildDir/workspace/build/solaris/solaris_i486_compiler1/fastdebug/vm_operations.o"
dbx: warning: can't find file "/PrtBuildDir/workspace/build/solaris/solaris_i486_compiler1/fastdebug/vmThread.o"
dbx: warning: can't find file "/PrtBuildDir/workspace/build/solaris/solaris_i486_compiler1/fastdebug/os_solaris.o"
(dbx) where
  [1] __sigprocmask(0x0, 0x4, 0xdfb99000), at 0xdfb86971 
  [2] _resetsig(), at 0xdfb7d4b5 
  [3] _sigon(), at 0xdfb7cdbe 
  [4] _lmutex_unlock(0xdfba0310), at 0xdfb7a7d0 
  [5] _thrp_kill(), at 0xdfb7f477 
  [6] _ti_thr_kill(0x4, 0x6), at 0xdfb7f368 
  [7] raise(0x6), at 0xdfafb6ff 
  [8] abort(), at 0xdfaebb30 
  [9] os::abort(0x1), at 0xde4fa24d 
  [10] VMError::report_and_die(0xddf405b4), at 0xde5e0555 
  [11] report_assertion_failure(0xdecd3512, 0x8b, 0xdecd34c6), at 0xde1eb15d 
=>[12] TenuredGeneration::compute_new_size(0x80becf8), at 0xde58b62e 
  [13] GenCollectedHeap::do_collection(0x80bbcc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x803fd7c), at 0xde21029a 
  [14] TwoGenerationCollectorPolicy::satisfy_failed_allocation(), at 0xde1a9f4a 
  [15] GenCollectedHeap::satisfy_failed_allocation(0x80bbcc0, 0x4, 0x0, 0x0, 0x803fd7c), at 0xde210671 
  [16] VM_GenCollectForAllocation::doit(0x803fd60), at 0xde5f423c 
  [17] VM_Operation::evaluate(), at 0xde5f3daf 
  [18] VMThread::evaluate_operation(0x80e64e0, 0x803fd60), at 0xde5f2b41 
  [19] VMThread::loop(0x80e64e0), at 0xde5f31ae 
  [20] VMThread::run(0x80e64e0), at 0xde5f282f 
  [21] _start(0x80e64e0, 0xde4f8df0), at 0xde4f8eca

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger-beta2 FIXED IN: tiger-beta2 INTEGRATED IN: tiger-b36 tiger-beta2
14-06-2004

EVALUATION ###@###.### 2003-10-14 Email indicates this also happens on amd64: From: Dmitri Trembovetski <###@###.###> To: ###@###.### Subject: HS crash during build on linux-amd64 Date: Tue, 14 Oct 2003 08:36:11 -0700 Hello, has anyone seen this build failure on linux-amd64 due to HS crash? I've built the workspace successfully just a couple of days ago, but it failed today. The full build log file: http://javaweb.sfbay/~tdv/logs/build.linux-amd64.tiger.29480.log HS log file: http://javaweb.sfbay/~tdv/logs/hs_err_pid23727.log Here's the crash: ../../../../../src/share/classes/java/util/zip/ZipInputStream.java ../../../../../src/share/classes/java/util/zip/ZipOutputStrea java ../../../../../src/solaris/classes/java/io/UnixFileSystem.java ; fi # To suppress the following error report, specify this argument # after -XX: or in .hotspotrc: SuppressErrorAt=/tenuredGeneration.cpp:139] # # An unexpected error has been detected by HotSpot Virtual Machine: # # Internal Error (/BUILD_AREA/jdk1.5.0/hotspot/src/share/vm/memory/tenuredGeneration.cpp, 139), pid=23727, tid=1026 # # Java VM: Java HotSpot(TM) 64-Bit Server VM (1.5.0-beta-b23-debug interpreted mode) # # Error: assert(minimum_desired_capacity <= maximum_desired_capacity,"sanity check") # An error report file with more information is saved as hs_err_pid23727.log # # If you would like to submit a bug report, please visit: # http://java.sun.com/cgi-bin/bugreport.cgi # ###@###.### 2003-10-16: The following email from Paul might well be the root cause of the bugs seen above: ------------------------------------------ Subject: bug in tenuredGenerator.cpp Date: Tue, 14 Oct 2003 16:52:02 -0400 (EDT) From: Paul Hohensee - Java Technology Group <###@###.###> Reply-To: Paul Hohensee - Java Technology Group <###@###.###> There's this code in compute_new_size. const double minimum_free_percentage = (double) MinHeapFreeRatio / 100; const double maximum_used_percentage = 1.0 - minimum_free_percentage; const double maximum_free_percentage = (double) MaxHeapFreeRatio / 100; const double minimum_used_percentage = 1.0 - maximum_free_percentage; Max/MinHeapFreeRatio can be set to 100 via -Xmaxf and -Xminf, which can make maximum/minimum_used_percentage == 0.0. Next we do size_t minimum_desired_capacity = used_after_gc / maximum_used_percentage; size_t maximum_desired_capacity = used_after_gc / minimum_used_percentage; which can divide-by-zero. We've got exceptions masked, so we get trash. Then // Don't shrink less than the initial generation size minimum_desired_capacity = MAX2(minimum_desired_capacity, spec()->init_size()); maximum_desired_capacity = MAX2(maximum_desired_capacity, spec()->init_size()); assert(used_after_gc <= minimum_desired_capacity, "sanity check"); assert(minimum_desired_capacity <= maximum_desired_capacity, "sanity check"); The assert can fire. We're seeing this during a linux-amd64 jdk build, which for some reason is using -Xmaxf1, along with -Xms64m -Xmx256m. I've advised them to get rid of the switch. I suppose you can set Min/MaxHeapFreeRatio directly as well and provoke the problem. Paul ---------------------------------------- Since the fix is simple, and would be useful as far as "usability" goes (as well as reducing customer calls), i am raising this to a P2, with the request that the fix be made in Tiger-beta. ###@###.### 2003-10-22 Easy way to reproduce this is to run the attached allocalot.java: java_g -XX:MinHeapFreeRatio=100 allocalot or java_g -XX:MaxHeapFreeRatio=0 allocalot This bug has been there a while; it happens as far back as 1.4.0. ###@###.### 2004-01-09 The bug is due to division by 0 in TenuredGeneration::compute_new_size() when -Xmaxf1 (aka -XX:MaxHeapFreeRatio=100) is used on the command line. Turns out 3 things can cause NaNs or bogus numbers to enter into the calculation and trigger the assert: Division by 0 if either MinHeapFreeRatio or MaxHeapFreeRatio == 100 Setting MinHeapFreeRatio > MaxHeapFreeRatio Assigning double to size_t without checking for overflow
11-06-2004

SUGGESTED FIX expansion_for_promotion); ! assert(shrink_bytes >= 0 && shrink_bytes <= max_shrink_bytes, "invalid shrink size"); ! if (PrintGC && Verbose) { ! gclog_or_tty->print_cr(" " ! " aggressive shrinking:" ! " _capacity_at_prologue: %.1fK" ! " capacity_after_gc: %.1fK" ! " expansion_for_promotion: %.1fK" ! " shrink_bytes: %.1fK", ! capacity_after_gc / (double) K, ! _capacity_at_prologue / (double) K, ! expansion_for_promotion / (double) K, ! shrink_bytes / (double) K); ! } } - // Don't shrink unless it's significant - if (shrink_bytes >= _min_heap_delta_bytes) { - shrink(shrink_bytes); - } } ! assert(_shrink_factor <= 100, "invalid shrink factor"); ! assert(used() == used_after_gc && used_after_gc <= capacity(), "sanity check"); } void TenuredGeneration::gc_prologue(bool full) { --- 243,278 ---- _min_heap_delta_bytes / (double) K); } } + } ! if (capacity_after_gc > _capacity_at_prologue) { ! // We might have expanded for promotions, in which case we might want to ! // take back that expansion if there's room after GC. That keeps us from ! // stretching the heap with promotions when there's plenty of room. ! size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; ! expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); ! // We have two shrinking computations, take the largest ! shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion); ! assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); ! if (PrintGC && Verbose) { ! gclog_or_tty->print_cr(" " ! " aggressive shrinking:" ! " _capacity_at_prologue: %.1fK" ! " capacity_after_gc: %.1fK" ! " expansion_for_promotion: %.1fK" ! " shrink_bytes: %.1fK", ! capacity_after_gc / (double) K, ! _capacity_at_prologue / (double) K, ! expansion_for_promotion / (double) K, ! shrink_bytes / (double) K); } } ! // Don't shrink unless it's significant ! if (shrink_bytes >= _min_heap_delta_bytes) { ! shrink(shrink_bytes); ! } ! assert(used() == used_after_gc && used_after_gc <= capacity(), ! "sanity check"); } void TenuredGeneration::gc_prologue(bool full) { *** src/share/vm/runtime/globals.hpp-1.803 Fri Jan 9 16:46:43 2004 --- src/share/vm/runtime/globals.hpp Fri Jan 9 16:46:44 2004 *************** *** 2120,2129 **** product_pd(uintx, MaxPermSize, "Maximum size of permanent generation (in bytes)") ! product(intx, MinHeapFreeRatio, 40, "Min percentage of heap free after GC to avoid expansion") ! product(intx, MaxHeapFreeRatio, 70, "Max percentage of heap free after GC to avoid shrinking") product(intx, SoftRefLRUPolicyMSPerMB, 1000, --- 2120,2129 ---- product_pd(uintx, MaxPermSize, "Maximum size of permanent generation (in bytes)") ! product(uintx, MinHeapFreeRatio, 40, "Min percentage of heap free after GC to avoid expansion") ! product(uintx, MaxHeapFreeRatio, 70, "Max percentage of heap free after GC to avoid shrinking") product(intx, SoftRefLRUPolicyMSPerMB, 1000,
11-06-2004

SUGGESTED FIX ###@###.### 2004-01-09 Verify that both {Min,Max}HeapFreeRatio are valid integer percentages, that MinHeapFreeRatio <= MaxHeapFreeRatio, and silently limit MinHeapFreeRatio to at most 99 (since keeping the heap 100% free is "hard"). compute_new_size() must avoid division by 0 and check for overflow when computing sizes. *** src/share/vm/runtime/arguments.hpp-1.73 Fri Jan 9 16:46:39 2004 --- src/share/vm/runtime/arguments.hpp Fri Jan 9 16:46:39 2004 *************** *** 272,277 **** --- 272,278 ---- static bool is_bad_option(const JavaVMOption* option, jboolean ignore) { return is_bad_option(option, ignore, NULL); } + static bool verify_percentage(uintx value, const char* name); // methods to build strings from individual args static void build_string(char** bldstr, const char* arg); *** src/share/vm/runtime/arguments.cpp-1.248 Fri Jan 9 16:46:40 2004 --- src/share/vm/runtime/arguments.cpp Fri Jan 9 16:46:40 2004 *************** *** 1040,1045 **** --- 1040,1055 ---- } } + bool Arguments::verify_percentage(uintx value, const char* name) { + if (value <= 100) { + return true; + } + jio_fprintf(defaultStream::error_stream(), + "%s of " UINTX_FORMAT " is invalid; must be between 0 and 100\n", + name, value); + return false; + } + // Check the consistency of vm_init_args bool Arguments::check_vm_args_consistency() { // Method for adding checks for flag consistency. *************** *** 1086,1099 **** } #endif - if (MaxLiveObjectEvacuationRatio > 100) { - jio_fprintf(defaultStream::error_stream(), - "MaxLiveObjectEvacuationRatio should be a percentage " - "between 0 and 100, " - "not " SIZE_FORMAT "\n", - MaxLiveObjectEvacuationRatio); - status = false; - } if (TLABRefillWasteFraction == 0) { jio_fprintf(defaultStream::error_stream(), "TLABRefillWasteFraction should be a denominator, " --- 1096,1101 ---- *************** *** 1102,1128 **** status = false; } ! if (AdaptiveSizePolicyWeight > 100) { jio_fprintf(defaultStream::error_stream(), ! "AdaptiveSizePolicyWeight should be between 0 and 100, " ! "not " SIZE_FORMAT "\n", ! AdaptiveSizePolicyWeight); status = false; } ! if (AdaptivePermSizeWeight > 100) { ! jio_fprintf(defaultStream::error_stream(), ! "AdaptivePermSizeWeight should be between 0 and 100, " ! "not " SIZE_FORMAT "\n", ! AdaptivePermSizeWeight); ! status = false; } - if (ThresholdTolerance > 100) { - jio_fprintf(defaultStream::error_stream(), - "ThresholdTolerance should be between 0 and 100, " - "not " SIZE_FORMAT "\n", - ThresholdTolerance); - status = false; - } // Check user specified sharing option conflict with Parallel GC bool cannot_share = (UseConcMarkSweepGC || UseTrainGC || UseParallelGC --- 1104,1131 ---- status = false; } ! status &= verify_percentage(MaxLiveObjectEvacuationRatio, ! "MaxLiveObjectEvacuationRatio"); ! status &= verify_percentage(AdaptiveSizePolicyWeight, ! "AdaptiveSizePolicyWeight"); ! status &= verify_percentage(AdaptivePermSizeWeight, "AdaptivePermSizeWeight"); ! status &= verify_percentage(ThresholdTolerance, "ThresholdTolerance"); ! status &= verify_percentage(MinHeapFreeRatio, "MinHeapFreeRatio"); ! status &= verify_percentage(MaxHeapFreeRatio, "MaxHeapFreeRatio"); ! ! if (MinHeapFreeRatio > MaxHeapFreeRatio) { jio_fprintf(defaultStream::error_stream(), ! "MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or " ! "equal to MaxHeapFreeRatio (" UINTX_FORMAT ")\n", ! MinHeapFreeRatio, MaxHeapFreeRatio); status = false; } ! // Keeping the heap 100% free is hard ;-) so limit it to 99%. ! MinHeapFreeRatio = MIN2(MinHeapFreeRatio, (uintx) 99); ! ! if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) { ! MarkSweepAlwaysCompactCount = 1; // Move objects every gc. } // Check user specified sharing option conflict with Parallel GC bool cannot_share = (UseConcMarkSweepGC || UseTrainGC || UseParallelGC *************** *** 1186,1201 **** "allocation buffers\n(-XX:+UseTLAB).\n"); status = false; } else { ! guarantee(CMSIncrementalDutyCycle <= 100, ! "invalid value for CMSIncrementalDutyCycle"); ! guarantee(CMSIncrementalDutyCycleMin <= 100, ! "invalid value for CMSIncrementalDutyCycleMin"); ! guarantee(CMSIncrementalSafetyFactor <= 100, ! "invalid value for CMSIncrementalSafetyFactor"); ! guarantee(CMSIncrementalOffset <= 100, ! "invalid value for CMSIncrementalOffset"); ! guarantee(CMSExpAvgFactor <= 100, ! "invalid value for CMSExpAvgFactor"); // If it was not set on the command line, set // CMSInitiatingOccupancyFraction to 1 so icms can initiate cycles early. if (CMSInitiatingOccupancyFraction < 0) { --- 1189,1204 ---- "allocation buffers\n(-XX:+UseTLAB).\n"); status = false; } else { ! status &= verify_percentage(CMSIncrementalDutyCycle, ! "CMSIncrementalDutyCycle"); ! status &= verify_percentage(CMSIncrementalDutyCycleMin, ! "CMSIncrementalDutyCycleMin"); ! status &= verify_percentage(CMSIncrementalSafetyFactor, ! "CMSIncrementalSafetyFactor"); ! status &= verify_percentage(CMSIncrementalOffset, ! "CMSIncrementalOffset"); ! status &= verify_percentage(CMSExpAvgFactor, ! "CMSExpAvgFactor"); // If it was not set on the command line, set // CMSInitiatingOccupancyFraction to 1 so icms can initiate cycles early. if (CMSInitiatingOccupancyFraction < 0) { *************** *** 1461,1467 **** option->optionString); return JNI_EINVAL; } else { ! FLAG_SET(intx, MaxHeapFreeRatio, maxf); } // Xminf } else if (match_option(option, "-Xminf", &tail)) { --- 1464,1470 ---- option->optionString); return JNI_EINVAL; } else { ! FLAG_SET(uintx, MaxHeapFreeRatio, maxf); } // Xminf } else if (match_option(option, "-Xminf", &tail)) { *************** *** 1472,1478 **** option->optionString); return JNI_EINVAL; } else { ! FLAG_SET(intx, MinHeapFreeRatio, minf); } // -Xss } else if (match_option(option, "-Xss", &tail)) { --- 1475,1481 ---- option->optionString); return JNI_EINVAL; } else { ! FLAG_SET(uintx, MinHeapFreeRatio, minf); } // -Xss } else if (match_option(option, "-Xss", &tail)) { *** src/share/vm/memory/tenuredGeneration.cpp-1.25 Fri Jan 9 16:46:40 2004 --- src/share/vm/memory/tenuredGeneration.cpp Fri Jan 9 16:46:40 2004 *************** *** 125,148 **** _shrink_factor = 0; // We don't have floating point command-line arguments ! const double minimum_free_percentage = (double) MinHeapFreeRatio / 100; const double maximum_used_percentage = 1.0 - minimum_free_percentage; - const double maximum_free_percentage = (double) MaxHeapFreeRatio / 100; - const double minimum_used_percentage = 1.0 - maximum_free_percentage; // Compute some numbers about the state of the heap. - const size_t free_after_gc = free(); const size_t used_after_gc = used(); const size_t capacity_after_gc = capacity(); ! size_t minimum_desired_capacity = used_after_gc / maximum_used_percentage; ! size_t maximum_desired_capacity = used_after_gc / minimum_used_percentage; // Don't shrink less than the initial generation size ! minimum_desired_capacity = MAX2(minimum_desired_capacity, spec()->init_size()); ! maximum_desired_capacity = MAX2(maximum_desired_capacity, spec()->init_size()); assert(used_after_gc <= minimum_desired_capacity, "sanity check"); - assert(minimum_desired_capacity <= maximum_desired_capacity, "sanity check"); if (PrintGC && Verbose) { const double free_percentage = ((double)free_after_gc) / capacity_after_gc; gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: "); gclog_or_tty->print_cr(" " --- 125,147 ---- _shrink_factor = 0; // We don't have floating point command-line arguments ! // Note: argument processing ensures that MinHeapFreeRatio < 100. ! const double minimum_free_percentage = MinHeapFreeRatio / 100.0; const double maximum_used_percentage = 1.0 - minimum_free_percentage; // Compute some numbers about the state of the heap. const size_t used_after_gc = used(); const size_t capacity_after_gc = capacity(); ! ! const double min_tmp = used_after_gc / maximum_used_percentage; ! size_t minimum_desired_capacity = MIN2(min_tmp, double(max_uintx)); // Don't shrink less than the initial generation size ! minimum_desired_capacity = MAX2(minimum_desired_capacity, ! spec()->init_size()); assert(used_after_gc <= minimum_desired_capacity, "sanity check"); if (PrintGC && Verbose) { + const size_t free_after_gc = free(); const double free_percentage = ((double)free_after_gc) / capacity_after_gc; gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: "); gclog_or_tty->print_cr(" " *************** *** 151,168 **** minimum_free_percentage, maximum_used_percentage); gclog_or_tty->print_cr(" " - " maximum_free_percentage: %6.2f" - " minimum_used_percentage: %6.2f", - maximum_free_percentage, - minimum_used_percentage); - gclog_or_tty->print_cr(" " - " _capacity_at_prologue: %6.1fK" - " minimum_desired_capacity: %6.1fK" - " maximum_desired_capacity: %6.1fK", - _capacity_at_prologue / (double) K, - minimum_desired_capacity / (double) K, - maximum_desired_capacity / (double) K); - gclog_or_tty->print_cr(" " " free_after_gc : %6.1fK" " used_after_gc : %6.1fK" " capacity_after_gc : %6.1fK", --- 150,155 ---- *************** *** 173,178 **** --- 160,166 ---- " free_percentage: %6.2f", free_percentage); } + if (capacity_after_gc < minimum_desired_capacity) { // If we have less free space than we want then expand size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; *************** *** 189,210 **** expand_bytes / (double) K, _min_heap_delta_bytes / (double) K); } ! } else { ! // No expansion, now see if we want to shrink ! size_t shrink_bytes = 0; ! // We would never want to shrink more than this ! size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; if (capacity_after_gc > maximum_desired_capacity) { // Capacity too large, compute shrinking size shrink_bytes = capacity_after_gc - maximum_desired_capacity; ! // We don't want shrink all the way back to initSize if people call System.gc(), ! // because some programs do that between "phases" and then we'd just have ! // to grow the heap up again for the next phase. So we damp the shrinking: ! // 0% on the first call, 10% on the second call, 40% on the third call, and 100% ! // by the fourth call. But if we recompute size without shrinking, it goes back ! // to 0%. ! shrink_bytes = ((double) shrink_bytes) * current_shrink_factor / 100; ! assert(shrink_bytes >= 0 && shrink_bytes <= max_shrink_bytes, "invalid shrink size"); if (current_shrink_factor == 0) { _shrink_factor = 10; } else { --- 177,225 ---- expand_bytes / (double) K, _min_heap_delta_bytes / (double) K); } ! return; ! } ! ! // No expansion, now see if we want to shrink ! size_t shrink_bytes = 0; ! // We would never want to shrink more than this ! size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; ! ! if (MaxHeapFreeRatio < 100) { ! const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; ! const double minimum_used_percentage = 1.0 - maximum_free_percentage; ! const double max_tmp = used_after_gc / minimum_used_percentage; ! size_t maximum_desired_capacity = MIN2(max_tmp, double(max_uintx)); ! maximum_desired_capacity = MAX2(maximum_desired_capacity, ! spec()->init_size()); ! if (PrintGC && Verbose) { ! gclog_or_tty->print_cr(" " ! " maximum_free_percentage: %6.2f" ! " minimum_used_percentage: %6.2f", ! maximum_free_percentage, ! minimum_used_percentage); ! gclog_or_tty->print_cr(" " ! " _capacity_at_prologue: %6.1fK" ! " minimum_desired_capacity: %6.1fK" ! " maximum_desired_capacity: %6.1fK", ! _capacity_at_prologue / (double) K, ! minimum_desired_capacity / (double) K, ! maximum_desired_capacity / (double) K); ! } ! assert(minimum_desired_capacity <= maximum_desired_capacity, ! "sanity check"); ! if (capacity_after_gc > maximum_desired_capacity) { // Capacity too large, compute shrinking size shrink_bytes = capacity_after_gc - maximum_desired_capacity; ! // We don't want shrink all the way back to initSize if people call ! // System.gc(), because some programs do that between "phases" and then ! // we'd just have to grow the heap up again for the next phase. So we ! // damp the shrinking: 0% on the first call, 10% on the second call, 40% ! // on the third call, and 100% by the fourth call. But if we recompute ! // size without shrinking, it goes back to 0%. ! shrink_bytes = shrink_bytes / 100 * current_shrink_factor; ! assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); if (current_shrink_factor == 0) { _shrink_factor = 10; } else { *************** *** 228,264 **** _min_heap_delta_bytes / (double) K); } } ! if (capacity_after_gc > _capacity_at_prologue) { ! // We might have expanded for promotions, in which case ! // we might want to take back that expansion if there's room ! // after GC. That keeps us from stretching the heap with promotions ! // when there's plenty of room. ! size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; ! expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); ! // We have two shrinking computations, take the largest ! shrink_bytes = MAX2(shrink_bytes,
11-06-2004

WORK AROUND ###@###.### 2003-10-31 From Paul's email (in the evaulation), the problem goes away on linux amd64 if you remove the -Xmaxf1 flag from the command line.
31-10-2003