JDK-6659207 : access violation in CompilerThread0
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: hs10,6,6u5,6u7-rev
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS:
    generic,solaris_10,windows_xp,windows_vista generic,solaris_10,windows_xp,windows_vista
  • CPU: generic,x86
  • Submitted: 2008-02-05
  • Updated: 2024-05-06
  • Resolved: 2011-03-07
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.
JDK 6 Other Other
6u10Fixed OpenJDK6Fixed OpenJDK6,hs11Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_04"
Java(TM) SE Runtime Environment (build 1.6.0_04-b12)
Java HotSpot(TM) 64-Bit Server VM (build 10.0-b19, mixed mode)

FULL OS VERSION :
Microsoft Windows [Version 6.0.6000]
(Vista Business 64)

A DESCRIPTION OF THE PROBLEM :
  Program consistently fails in 64-bit jvm (client & server) but works in 32-bit jvm. Get access violation in hotspot compiler thread (but reported as "outside the jvm in native code" - I think incorrectly).

Note that the error report below indicates an error occurred getting the native stack. During one run I attached visual studio and captured the native stack when the access violation occurred, pasted below:
>	jvm.dll!0000000008093cbb()
 	[Frames below may be incorrect and/or missing, no symbols loaded for jvm.dll]
 	jvm.dll!00000000080963c7()
 	jvm.dll!00000000080d8aa1()
 	jvm.dll!00000000080d95e5()
 	jvm.dll!0000000008086d7d()
 	jvm.dll!00000000080dc132()
 	jvm.dll!00000000080dcf8a()
 	jvm.dll!00000000083db2df()
 	jvm.dll!000000000831be59()
 	msvcrt.dll!000007feff5e94e7()
 	msvcrt.dll!000007feff5e967d()
 	kernel32.dll!000000007780cdcd()
 	ntdll.dll!0000000077a2c6e1()

Crash Log is attached seperatly


THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the sample code using a 64-bit JVM (may be vista specific? haven't tried on other platforms)

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expect program to exit normally after the loop. Actual behavior is access violation on the last iteration of the loop.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
<snip>
Running test  9998 -> 1220321112
Running test  9999 -> 1468100534
#
# An unexpected error has been detected by Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION[thread 4404 also had an error] (0xc0000005)
 at pc=0x0000000008093cbb, pid=2304, tid=4504
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (10.0-b19 mixed mode windows-amd64)
# Problematic frame:
# V  [jvm.dll+0x93cbb]
#
# An error report file with more information is saved as:
# D:\PRWorkspace\PR05-DevTip\AccessViolationTest\hs_err_pid2304.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.ArrayList;
import java.util.Arrays;

public class AV64bit {

	private static AV64bit oFactoryInstance = new AV64bit();
	public static StringBuffer acquire(int requested) {
		return (StringBuffer) oFactoryInstance.acquireObject(requested);
	}

	private final int[] mPoolCapacities = { 32 + 1, 64 + 1, 128 + 1, 256 + 1, 1024 + 1, 2 * 1024 + 1, 4 * 1024 + 1, 6 * 1024 + 1, 10 * 1024 + 1, 32 * 1024 + 1, 60 * 1024 + 1, 100 * 1024 + 1 };
	private final int[] mPerCapacityPoolSize = { 10, 10, 50, 100, 100, 100, 10, 100, 100, 50, 10, 10 };

	@SuppressWarnings("unchecked")
	private ArrayList[] mPoolLists = new ArrayList[mPoolCapacities.length];
	private long[] mCreateCount = new long[mPoolCapacities.length];
	private long[] mReuseCount = new long[mPoolCapacities.length];
	private long[] mTAL = new long[mPoolCapacities.length];
	private int iOverAlloc;
	private AV64bit() {
		Arrays.fill(mTAL, System.currentTimeMillis());
	}
	@SuppressWarnings("unchecked")
	private Object acquireObject(int requested) {
		int which = getWhich(requested);

		int capacity;
		if (which > -1) {
			capacity = mPoolCapacities[which];

			ArrayList list = null;
			synchronized (mPoolLists) {
				if (mPoolLists[which] == null) {
					mPoolLists[which] = new ArrayList(mPerCapacityPoolSize[which]);
				}
				list = mPoolLists[which];
			}

			// remove a Product from the allocations list,
			synchronized (list) {
				int size = list.size();
				if (size > 0) {
					mReuseCount[which]++;
					return list.remove(--size);
				}
			}
		} else {
			capacity = requested;
		}

		// count allocations as we go for reporting
		if (which == -1)
			iOverAlloc++;
		else
			mCreateCount[which]++;

		return newProduct(capacity);
	}
	private int getWhich(int capacity) {
		if (capacity == 0)
			return 0; // return FIRST bucket (zero-based)

		for (int i = 0; i < mPoolCapacities.length; i++)
			if (capacity <= mPoolCapacities[i])
				return i;

		return -1;
	}
	private Object newProduct(int capacity) {
		return new StringBuffer(capacity);
	}

	public static void main(String[] args) {
		for (int i = 0; i < 10000; i++) {
			StringBuffer buffer = AV64bit.acquire(1024);
			System.out.printf("Running test %5d -> %d\n", i, buffer.hashCode());
		}
	}

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None found.

Comments
SUGGESTED FIX repo: /net/jano2.sfbay/export2/hotspot/hg/hotspot-comp.clean changeset: 52:8bb88f9877e5 user: never date: Tue Mar 18 23:54:17 2008 -0700 description: 6659207: access violation in CompilerThread0 Summary: split_thru_phi produces top on a non-dead path Reviewed-by: kvn, rasbold, sgoldman files: src/share/vm/opto/loopopts.cpp test/compiler/6659207/Test.java --- old/src/share/vm/opto/loopopts.cpp Tue Mar 18 10:41:07 2008 +++ new/src/share/vm/opto/loopopts.cpp Tue Mar 18 10:41:06 2008 @@ -29,6 +29,11 @@ //------------------------------split_thru_phi--------------------------------- // Split Node 'n' through merge point if there is enough win. Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) { + if (n->Opcode() == Op_ConvI2L && n->bottom_type() != TypeLong::LONG) { + // ConvI2L may have type information on it which is unsafe to push up + // so disable this for now + return NULL; + } int wins = 0; assert( !n->is_CFG(), "" ); assert( region->is_Region(), "" );
06-03-2008

EVALUATION After raising the number of iterations to 20000, I can reproduce this crash on sparc 64 bit going all the way back to 1.6.0. V [libjvm.so+0x341264];; __1cMPhaseChaitinQgather_lrg_masks6Mb_v_+0x2a8 V [libjvm.so+0x1d67d0];; __1cMPhaseChaitinRRegister_Allocate6M_v_+0x408 V [libjvm.so+0x1cb754];; __1cHCompileICode_Gen6M_v_+0x32c V [libjvm.so+0x38b88c];; __1cHCompile2t6MpnFciEnv_pnKC2Compiler_pnIciMethod_ib_v_+0xb24 V [libjvm.so+0x1ef388];; __1cKC2CompilerOcompile_method6MpnFciEnv_pnIciMethod_i_v_+0x80 V [libjvm.so+0x1efbe4];; __1cNCompileBrokerZinvoke_compiler_on_method6FpnLCompileTask__v_+0x79c V [libjvm.so+0x270860];; __1cNCompileBrokerUcompiler_thread_loop6F_v_+0x5c0 V [libjvm.so+0x6f5bcc];; __1cKJavaThreadRthread_main_inner6M_v_+0x4c V [libjvm.so+0x6366c4];; java_start+0x184 In debug mode is asserts in PhaseChaitin::union when it can't find the entry for the source node. Narrowing it down using the prt archives it appeared with the fix for 6260293 though I don't think that's really the cause. I think it just unmasks the issue. The underlying issue appears to be a ConvI2L with a constrained type is pushed through a phi so that it ends up with a -1 input which causes it to be replaced with top. Clearly using a constrained type in this way is unsafe since it's not connected to any dependence which keeps it from being moved above the control that proves it. More properly it should probably be an unconstrained ConvI2L with a CastL2L that asserts the restricted range as a result of the control edge but we don't have a CastL2L. I think the fix for 6260293 allows this optimization to occur in situations where it previously wouldn't since the constrained ConvI2L dates back at least to 1.5.
05-02-2008