From 1081efba4f3a23560e2abcf0245c838abdcfbf96 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Thu, 5 Jan 2012 18:18:04 -0800 Subject: [PATCH 01/96] 6414899: P11Digest should support cloning Enhanced the PKCS11 Digest implementation to support cloning Reviewed-by: vinnie --- jdk/make/sun/security/pkcs11/mapfile-vers | 6 +- .../sun/security/pkcs11/P11Digest.java | 179 +++++---- .../sun/security/pkcs11/wrapper/PKCS11.java | 377 ++++++++++++------ .../share/lib/security/sunpkcs11-solaris.cfg | 14 +- .../security/pkcs11/wrapper/pkcs11wrapper.h | 6 +- .../pkcs11/MessageDigest/TestCloning.java | 141 +++++++ 6 files changed, 498 insertions(+), 225 deletions(-) create mode 100644 jdk/test/sun/security/pkcs11/MessageDigest/TestCloning.java diff --git a/jdk/make/sun/security/pkcs11/mapfile-vers b/jdk/make/sun/security/pkcs11/mapfile-vers index ddf61d3c8c8..7301c11417d 100644 --- a/jdk/make/sun/security/pkcs11/mapfile-vers +++ b/jdk/make/sun/security/pkcs11/mapfile-vers @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -47,8 +47,8 @@ SUNWprivate_1.1 { Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseSession; # Java_sun_security_pkcs11_wrapper_PKCS11_C_1CloseAllSessions; Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSessionInfo; -# Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOperationState; -# Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationState; + Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOperationState; + Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationState; Java_sun_security_pkcs11_wrapper_PKCS11_C_1Login; Java_sun_security_pkcs11_wrapper_PKCS11_C_1Logout; Java_sun_security_pkcs11_wrapper_PKCS11_C_1CreateObject; diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java b/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java index bb38a3dfda4..08f22fffc11 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11Digest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,13 +49,12 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*; * @author Andreas Sterbenz * @since 1.5 */ -final class P11Digest extends MessageDigestSpi { +final class P11Digest extends MessageDigestSpi implements Cloneable { - /* unitialized, fields uninitialized, no session acquired */ + /* fields initialized, no session acquired */ private final static int S_BLANK = 1; - // data in buffer, all fields valid, session acquired - // but digest not initialized + /* data in buffer, session acquired, but digest not initialized */ private final static int S_BUFFERED = 2; /* session initialized for digesting */ @@ -69,8 +68,8 @@ final class P11Digest extends MessageDigestSpi { // algorithm name private final String algorithm; - // mechanism id - private final long mechanism; + // mechanism id object + private final CK_MECHANISM mechanism; // length of the digest in bytes private final int digestLength; @@ -81,11 +80,8 @@ final class P11Digest extends MessageDigestSpi { // current state, one of S_* above private int state; - // one byte buffer for the update(byte) method, initialized on demand - private byte[] oneByte; - // buffer to reduce number of JNI calls - private final byte[] buffer; + private byte[] buffer; // offset into the buffer private int bufOfs; @@ -94,7 +90,7 @@ final class P11Digest extends MessageDigestSpi { super(); this.token = token; this.algorithm = algorithm; - this.mechanism = mechanism; + this.mechanism = new CK_MECHANISM(mechanism); switch ((int)mechanism) { case (int)CKM_MD2: case (int)CKM_MD5: @@ -117,7 +113,6 @@ final class P11Digest extends MessageDigestSpi { } buffer = new byte[BUFFER_SIZE]; state = S_BLANK; - engineReset(); } // see JCA spec @@ -125,44 +120,31 @@ final class P11Digest extends MessageDigestSpi { return digestLength; } - private void cancelOperation() { - token.ensureValid(); - if (session == null) { - return; - } - if ((state != S_INIT) || (token.explicitCancel == false)) { - return; - } - // need to explicitly "cancel" active op by finishing it - try { - token.p11.C_DigestFinal(session.id(), buffer, 0, buffer.length); - } catch (PKCS11Exception e) { - throw new ProviderException("cancel() failed", e); - } finally { - state = S_BUFFERED; - } - } - private void fetchSession() { token.ensureValid(); if (state == S_BLANK) { - engineReset(); + try { + session = token.getOpSession(); + state = S_BUFFERED; + } catch (PKCS11Exception e) { + throw new ProviderException("No more session available", e); + } } } // see JCA spec protected void engineReset() { - try { - cancelOperation(); - bufOfs = 0; - if (session == null) { - session = token.getOpSession(); + token.ensureValid(); + + if (session != null) { + if (state == S_INIT && token.explicitCancel == true) { + session = token.killSession(session); + } else { + session = token.releaseSession(session); } - state = S_BUFFERED; - } catch (PKCS11Exception e) { - state = S_BLANK; - throw new ProviderException("reset() failed, ", e); } + state = S_BLANK; + bufOfs = 0; } // see JCA spec @@ -180,18 +162,22 @@ final class P11Digest extends MessageDigestSpi { protected int engineDigest(byte[] digest, int ofs, int len) throws DigestException { if (len < digestLength) { - throw new DigestException("Length must be at least " + digestLength); + throw new DigestException("Length must be at least " + + digestLength); } + fetchSession(); try { int n; if (state == S_BUFFERED) { - n = token.p11.C_DigestSingle(session.id(), - new CK_MECHANISM(mechanism), - buffer, 0, bufOfs, digest, ofs, len); + n = token.p11.C_DigestSingle(session.id(), mechanism, buffer, 0, + bufOfs, digest, ofs, len); + bufOfs = 0; } else { if (bufOfs != 0) { - doUpdate(buffer, 0, bufOfs); + token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, + bufOfs); + bufOfs = 0; } n = token.p11.C_DigestFinal(session.id(), digest, ofs, len); } @@ -202,36 +188,44 @@ final class P11Digest extends MessageDigestSpi { } catch (PKCS11Exception e) { throw new ProviderException("digest() failed", e); } finally { - state = S_BLANK; - bufOfs = 0; - session = token.releaseSession(session); + engineReset(); } } // see JCA spec protected void engineUpdate(byte in) { - if (oneByte == null) { - oneByte = new byte[1]; - } - oneByte[0] = in; - engineUpdate(oneByte, 0, 1); + byte[] temp = { in }; + engineUpdate(temp, 0, 1); } // see JCA spec protected void engineUpdate(byte[] in, int ofs, int len) { - fetchSession(); if (len <= 0) { return; } - if ((bufOfs != 0) && (bufOfs + len > buffer.length)) { - doUpdate(buffer, 0, bufOfs); - bufOfs = 0; - } - if (bufOfs + len > buffer.length) { - doUpdate(in, ofs, len); - } else { - System.arraycopy(in, ofs, buffer, bufOfs, len); - bufOfs += len; + + fetchSession(); + try { + if (state == S_BUFFERED) { + token.p11.C_DigestInit(session.id(), mechanism); + state = S_INIT; + } + if ((bufOfs != 0) && (bufOfs + len > buffer.length)) { + // process the buffered data + token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs); + bufOfs = 0; + } + if (bufOfs + len > buffer.length) { + // process the new data + token.p11.C_DigestUpdate(session.id(), 0, in, ofs, len); + } else { + // buffer the new data + System.arraycopy(in, ofs, buffer, bufOfs, len); + bufOfs += len; + } + } catch (PKCS11Exception e) { + engineReset(); + throw new ProviderException("update() failed", e); } } @@ -239,11 +233,7 @@ final class P11Digest extends MessageDigestSpi { // the master secret is sensitive. We may want to consider making this // method public in a future release. protected void implUpdate(SecretKey key) throws InvalidKeyException { - fetchSession(); - if (bufOfs != 0) { - doUpdate(buffer, 0, bufOfs); - bufOfs = 0; - } + // SunJSSE calls this method only if the key does not have a RAW // encoding, i.e. if it is sensitive. Therefore, no point in calling // SecretKeyFactory to try to convert it. Just verify it ourselves. @@ -252,60 +242,77 @@ final class P11Digest extends MessageDigestSpi { } P11Key p11Key = (P11Key)key; if (p11Key.token != token) { - throw new InvalidKeyException("Not a P11Key of this provider: " + key); + throw new InvalidKeyException("Not a P11Key of this provider: " + + key); } + + fetchSession(); try { if (state == S_BUFFERED) { - token.p11.C_DigestInit(session.id(), new CK_MECHANISM(mechanism)); + token.p11.C_DigestInit(session.id(), mechanism); state = S_INIT; } + + if (bufOfs != 0) { + token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs); + bufOfs = 0; + } token.p11.C_DigestKey(session.id(), p11Key.keyID); } catch (PKCS11Exception e) { + engineReset(); throw new ProviderException("update(SecretKey) failed", e); } } // see JCA spec protected void engineUpdate(ByteBuffer byteBuffer) { - fetchSession(); int len = byteBuffer.remaining(); if (len <= 0) { return; } + if (byteBuffer instanceof DirectBuffer == false) { super.engineUpdate(byteBuffer); return; } + + fetchSession(); long addr = ((DirectBuffer)byteBuffer).address(); int ofs = byteBuffer.position(); try { if (state == S_BUFFERED) { - token.p11.C_DigestInit(session.id(), new CK_MECHANISM(mechanism)); + token.p11.C_DigestInit(session.id(), mechanism); state = S_INIT; - if (bufOfs != 0) { - doUpdate(buffer, 0, bufOfs); - bufOfs = 0; - } + } + if (bufOfs != 0) { + token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs); + bufOfs = 0; } token.p11.C_DigestUpdate(session.id(), addr + ofs, null, 0, len); byteBuffer.position(ofs + len); } catch (PKCS11Exception e) { + engineReset(); throw new ProviderException("update() failed", e); } } - private void doUpdate(byte[] in, int ofs, int len) { - if (len <= 0) { - return; - } + public Object clone() throws CloneNotSupportedException { + P11Digest copy = (P11Digest) super.clone(); + copy.buffer = buffer.clone(); try { - if (state == S_BUFFERED) { - token.p11.C_DigestInit(session.id(), new CK_MECHANISM(mechanism)); - state = S_INIT; + if (session != null) { + copy.session = copy.token.getOpSession(); + } + if (state == S_INIT) { + byte[] stateValues = + token.p11.C_GetOperationState(session.id()); + token.p11.C_SetOperationState(copy.session.id(), + stateValues, 0, 0); } - token.p11.C_DigestUpdate(session.id(), 0, in, ofs, len); } catch (PKCS11Exception e) { - throw new ProviderException("update() failed", e); + throw (CloneNotSupportedException) + (new CloneNotSupportedException(algorithm).initCause(e)); } + return copy; } } diff --git a/jdk/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/jdk/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java index 771c3431b93..b407e56cfd3 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java +++ b/jdk/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -133,14 +133,15 @@ public class PKCS11 { * @preconditions (pkcs11ModulePath <> null) * @postconditions */ - PKCS11(String pkcs11ModulePath, String functionListName) throws IOException { + PKCS11(String pkcs11ModulePath, String functionListName) + throws IOException { connect(pkcs11ModulePath, functionListName); this.pkcs11ModulePath = pkcs11ModulePath; } - public static synchronized PKCS11 getInstance(String pkcs11ModulePath, String functionList, - CK_C_INITIALIZE_ARGS pInitArgs, boolean omitInitialize) - throws IOException, PKCS11Exception { + public static synchronized PKCS11 getInstance(String pkcs11ModulePath, + String functionList, CK_C_INITIALIZE_ARGS pInitArgs, + boolean omitInitialize) throws IOException, PKCS11Exception { // we may only call C_Initialize once per native .so/.dll // so keep a cache using the (non-canonicalized!) path PKCS11 pkcs11 = moduleMap.get(pkcs11ModulePath); @@ -177,7 +178,8 @@ public class PKCS11 { * @preconditions (pkcs11ModulePath <> null) * @postconditions */ - private native void connect(String pkcs11ModulePath, String functionListName) throws IOException; + private native void connect(String pkcs11ModulePath, String functionListName) + throws IOException; /** * Disconnects the PKCS#11 library from this object. After calling this @@ -255,7 +257,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native long[] C_GetSlotList(boolean tokenPresent) throws PKCS11Exception; + public native long[] C_GetSlotList(boolean tokenPresent) + throws PKCS11Exception; /** @@ -287,7 +290,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native CK_TOKEN_INFO C_GetTokenInfo(long slotID) throws PKCS11Exception; + public native CK_TOKEN_INFO C_GetTokenInfo(long slotID) + throws PKCS11Exception; /** @@ -322,7 +326,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native CK_MECHANISM_INFO C_GetMechanismInfo(long slotID, long type) throws PKCS11Exception; + public native CK_MECHANISM_INFO C_GetMechanismInfo(long slotID, long type) + throws PKCS11Exception; /** @@ -339,7 +344,8 @@ public class PKCS11 { * @preconditions * @postconditions */ -// public native void C_InitToken(long slotID, char[] pPin, char[] pLabel) throws PKCS11Exception; +// public native void C_InitToken(long slotID, char[] pPin, char[] pLabel) +// throws PKCS11Exception; /** @@ -354,7 +360,8 @@ public class PKCS11 { * @preconditions * @postconditions */ -// public native void C_InitPIN(long hSession, char[] pPin) throws PKCS11Exception; +// public native void C_InitPIN(long hSession, char[] pPin) +// throws PKCS11Exception; /** @@ -371,7 +378,8 @@ public class PKCS11 { * @preconditions * @postconditions */ -// public native void C_SetPIN(long hSession, char[] pOldPin, char[] pNewPin) throws PKCS11Exception; +// public native void C_SetPIN(long hSession, char[] pOldPin, char[] pNewPin) +// throws PKCS11Exception; @@ -398,7 +406,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native long C_OpenSession(long slotID, long flags, Object pApplication, CK_NOTIFY Notify) throws PKCS11Exception; + public native long C_OpenSession(long slotID, long flags, + Object pApplication, CK_NOTIFY Notify) throws PKCS11Exception; /** @@ -440,7 +449,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native CK_SESSION_INFO C_GetSessionInfo(long hSession) throws PKCS11Exception; + public native CK_SESSION_INFO C_GetSessionInfo(long hSession) + throws PKCS11Exception; /** @@ -457,7 +467,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ -// public native byte[] C_GetOperationState(long hSession) throws PKCS11Exception; + public native byte[] C_GetOperationState(long hSession) + throws PKCS11Exception; /** @@ -478,7 +489,8 @@ public class PKCS11 { * @preconditions * @postconditions */ -// public native void C_SetOperationState(long hSession, byte[] pOperationState, long hEncryptionKey, long hAuthenticationKey) throws PKCS11Exception; + public native void C_SetOperationState(long hSession, byte[] pOperationState, + long hEncryptionKey, long hAuthenticationKey) throws PKCS11Exception; /** @@ -495,7 +507,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_Login(long hSession, long userType, char[] pPin) throws PKCS11Exception; + public native void C_Login(long hSession, long userType, char[] pPin) + throws PKCS11Exception; /** @@ -531,7 +544,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native long C_CreateObject(long hSession, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; + public native long C_CreateObject(long hSession, CK_ATTRIBUTE[] pTemplate) + throws PKCS11Exception; /** @@ -552,7 +566,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native long C_CopyObject(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; + public native long C_CopyObject(long hSession, long hObject, + CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; /** @@ -567,7 +582,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_DestroyObject(long hSession, long hObject) throws PKCS11Exception; + public native void C_DestroyObject(long hSession, long hObject) + throws PKCS11Exception; /** @@ -584,7 +600,8 @@ public class PKCS11 { * @preconditions * @postconditions */ -// public native long C_GetObjectSize(long hSession, long hObject) throws PKCS11Exception; +// public native long C_GetObjectSize(long hSession, long hObject) +// throws PKCS11Exception; /** @@ -604,7 +621,8 @@ public class PKCS11 { * @preconditions (pTemplate <> null) * @postconditions (result <> null) */ - public native void C_GetAttributeValue(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; + public native void C_GetAttributeValue(long hSession, long hObject, + CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; /** @@ -623,7 +641,8 @@ public class PKCS11 { * @preconditions (pTemplate <> null) * @postconditions */ - public native void C_SetAttributeValue(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; + public native void C_SetAttributeValue(long hSession, long hObject, + CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; /** @@ -640,7 +659,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_FindObjectsInit(long hSession, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; + public native void C_FindObjectsInit(long hSession, CK_ATTRIBUTE[] pTemplate) + throws PKCS11Exception; /** @@ -659,7 +679,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native long[] C_FindObjects(long hSession, long ulMaxObjectCount) throws PKCS11Exception; + public native long[] C_FindObjects(long hSession, long ulMaxObjectCount) + throws PKCS11Exception; /** @@ -695,7 +716,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_EncryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception; + public native void C_EncryptInit(long hSession, CK_MECHANISM pMechanism, + long hKey) throws PKCS11Exception; /** @@ -713,7 +735,8 @@ public class PKCS11 { * @preconditions (pData <> null) * @postconditions (result <> null) */ - public native int C_Encrypt(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOfs, int outLen) throws PKCS11Exception; + public native int C_Encrypt(long hSession, byte[] in, int inOfs, int inLen, + byte[] out, int outOfs, int outLen) throws PKCS11Exception; /** @@ -732,7 +755,9 @@ public class PKCS11 { * @preconditions (pPart <> null) * @postconditions */ - public native int C_EncryptUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception; + public native int C_EncryptUpdate(long hSession, long directIn, byte[] in, + int inOfs, int inLen, long directOut, byte[] out, int outOfs, + int outLen) throws PKCS11Exception; /** @@ -749,7 +774,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native int C_EncryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception; + public native int C_EncryptFinal(long hSession, long directOut, byte[] out, + int outOfs, int outLen) throws PKCS11Exception; /** @@ -766,7 +792,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_DecryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception; + public native void C_DecryptInit(long hSession, CK_MECHANISM pMechanism, + long hKey) throws PKCS11Exception; /** @@ -785,7 +812,8 @@ public class PKCS11 { * @preconditions (pEncryptedPart <> null) * @postconditions (result <> null) */ - public native int C_Decrypt(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOfs, int outLen) throws PKCS11Exception; + public native int C_Decrypt(long hSession, byte[] in, int inOfs, int inLen, + byte[] out, int outOfs, int outLen) throws PKCS11Exception; /** @@ -805,7 +833,9 @@ public class PKCS11 { * @preconditions (pEncryptedPart <> null) * @postconditions */ - public native int C_DecryptUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception; + public native int C_DecryptUpdate(long hSession, long directIn, byte[] in, + int inOfs, int inLen, long directOut, byte[] out, int outOfs, + int outLen) throws PKCS11Exception; /** @@ -822,7 +852,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native int C_DecryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception; + public native int C_DecryptFinal(long hSession, long directOut, byte[] out, + int outOfs, int outLen) throws PKCS11Exception; @@ -842,7 +873,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_DigestInit(long hSession, CK_MECHANISM pMechanism) throws PKCS11Exception; + public native void C_DigestInit(long hSession, CK_MECHANISM pMechanism) + throws PKCS11Exception; // note that C_DigestSingle does not exist in PKCS#11 @@ -863,7 +895,9 @@ public class PKCS11 { * @preconditions (data <> null) * @postconditions (result <> null) */ - public native int C_DigestSingle(long hSession, CK_MECHANISM pMechanism, byte[] in, int inOfs, int inLen, byte[] digest, int digestOfs, int digestLen) throws PKCS11Exception; + public native int C_DigestSingle(long hSession, CK_MECHANISM pMechanism, + byte[] in, int inOfs, int inLen, byte[] digest, int digestOfs, + int digestLen) throws PKCS11Exception; /** @@ -879,7 +913,8 @@ public class PKCS11 { * @preconditions (pPart <> null) * @postconditions */ - public native void C_DigestUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception; + public native void C_DigestUpdate(long hSession, long directIn, byte[] in, + int inOfs, int inLen) throws PKCS11Exception; /** @@ -896,7 +931,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_DigestKey(long hSession, long hKey) throws PKCS11Exception; + public native void C_DigestKey(long hSession, long hKey) + throws PKCS11Exception; /** @@ -912,7 +948,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native int C_DigestFinal(long hSession, byte[] pDigest, int digestOfs, int digestLen) throws PKCS11Exception; + public native int C_DigestFinal(long hSession, byte[] pDigest, int digestOfs, + int digestLen) throws PKCS11Exception; @@ -937,7 +974,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_SignInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception; + public native void C_SignInit(long hSession, CK_MECHANISM pMechanism, + long hKey) throws PKCS11Exception; /** @@ -957,7 +995,8 @@ public class PKCS11 { * @preconditions (pData <> null) * @postconditions (result <> null) */ - public native byte[] C_Sign(long hSession, byte[] pData) throws PKCS11Exception; + public native byte[] C_Sign(long hSession, byte[] pData) + throws PKCS11Exception; /** @@ -974,7 +1013,8 @@ public class PKCS11 { * @preconditions (pPart <> null) * @postconditions */ - public native void C_SignUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception; + public native void C_SignUpdate(long hSession, long directIn, byte[] in, + int inOfs, int inLen) throws PKCS11Exception; /** @@ -991,7 +1031,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native byte[] C_SignFinal(long hSession, int expectedLen) throws PKCS11Exception; + public native byte[] C_SignFinal(long hSession, int expectedLen) + throws PKCS11Exception; /** @@ -1009,7 +1050,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_SignRecoverInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception; + public native void C_SignRecoverInit(long hSession, CK_MECHANISM pMechanism, + long hKey) throws PKCS11Exception; /** @@ -1028,7 +1070,9 @@ public class PKCS11 { * @preconditions (pData <> null) * @postconditions (result <> null) */ - public native int C_SignRecover(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOufs, int outLen) throws PKCS11Exception; + public native int C_SignRecover(long hSession, byte[] in, int inOfs, + int inLen, byte[] out, int outOufs, int outLen) + throws PKCS11Exception; @@ -1052,7 +1096,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_VerifyInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception; + public native void C_VerifyInit(long hSession, CK_MECHANISM pMechanism, + long hKey) throws PKCS11Exception; /** @@ -1071,7 +1116,8 @@ public class PKCS11 { * @preconditions (pData <> null) and (pSignature <> null) * @postconditions */ - public native void C_Verify(long hSession, byte[] pData, byte[] pSignature) throws PKCS11Exception; + public native void C_Verify(long hSession, byte[] pData, byte[] pSignature) + throws PKCS11Exception; /** @@ -1088,7 +1134,8 @@ public class PKCS11 { * @preconditions (pPart <> null) * @postconditions */ - public native void C_VerifyUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception; + public native void C_VerifyUpdate(long hSession, long directIn, byte[] in, + int inOfs, int inLen) throws PKCS11Exception; /** @@ -1104,7 +1151,8 @@ public class PKCS11 { * @preconditions (pSignature <> null) * @postconditions */ - public native void C_VerifyFinal(long hSession, byte[] pSignature) throws PKCS11Exception; + public native void C_VerifyFinal(long hSession, byte[] pSignature) + throws PKCS11Exception; /** @@ -1122,7 +1170,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native void C_VerifyRecoverInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception; + public native void C_VerifyRecoverInit(long hSession, + CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception; /** @@ -1140,7 +1189,9 @@ public class PKCS11 { * @preconditions (pSignature <> null) * @postconditions (result <> null) */ - public native int C_VerifyRecover(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOufs, int outLen) throws PKCS11Exception; + public native int C_VerifyRecover(long hSession, byte[] in, int inOfs, + int inLen, byte[] out, int outOufs, int outLen) + throws PKCS11Exception; @@ -1164,7 +1215,8 @@ public class PKCS11 { * @preconditions (pPart <> null) * @postconditions */ -// public native byte[] C_DigestEncryptUpdate(long hSession, byte[] pPart) throws PKCS11Exception; +// public native byte[] C_DigestEncryptUpdate(long hSession, byte[] pPart) +// throws PKCS11Exception; /** @@ -1184,7 +1236,8 @@ public class PKCS11 { * @preconditions (pEncryptedPart <> null) * @postconditions */ -// public native byte[] C_DecryptDigestUpdate(long hSession, byte[] pEncryptedPart) throws PKCS11Exception; +// public native byte[] C_DecryptDigestUpdate(long hSession, +// byte[] pEncryptedPart) throws PKCS11Exception; /** @@ -1204,7 +1257,8 @@ public class PKCS11 { * @preconditions (pPart <> null) * @postconditions */ -// public native byte[] C_SignEncryptUpdate(long hSession, byte[] pPart) throws PKCS11Exception; +// public native byte[] C_SignEncryptUpdate(long hSession, byte[] pPart) +// throws PKCS11Exception; /** @@ -1224,7 +1278,8 @@ public class PKCS11 { * @preconditions (pEncryptedPart <> null) * @postconditions */ -// public native byte[] C_DecryptVerifyUpdate(long hSession, byte[] pEncryptedPart) throws PKCS11Exception; +// public native byte[] C_DecryptVerifyUpdate(long hSession, +// byte[] pEncryptedPart) throws PKCS11Exception; @@ -1250,7 +1305,8 @@ public class PKCS11 { * @preconditions * @postconditions */ - public native long C_GenerateKey(long hSession, CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; + public native long C_GenerateKey(long hSession, CK_MECHANISM pMechanism, + CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; /** @@ -1280,9 +1336,8 @@ public class PKCS11 { * @postconditions (result <> null) and (result.length == 2) */ public native long[] C_GenerateKeyPair(long hSession, - CK_MECHANISM pMechanism, - CK_ATTRIBUTE[] pPublicKeyTemplate, - CK_ATTRIBUTE[] pPrivateKeyTemplate) throws PKCS11Exception; + CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pPublicKeyTemplate, + CK_ATTRIBUTE[] pPrivateKeyTemplate) throws PKCS11Exception; @@ -1305,7 +1360,8 @@ public class PKCS11 { * @preconditions * @postconditions (result <> null) */ - public native byte[] C_WrapKey(long hSession, CK_MECHANISM pMechanism, long hWrappingKey, long hKey) throws PKCS11Exception; + public native byte[] C_WrapKey(long hSession, CK_MECHANISM pMechanism, + long hWrappingKey, long hKey) throws PKCS11Exception; /** @@ -1331,8 +1387,8 @@ public class PKCS11 { * @postconditions */ public native long C_UnwrapKey(long hSession, CK_MECHANISM pMechanism, - long hUnwrappingKey, byte[] pWrappedKey, - CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; + long hUnwrappingKey, byte[] pWrappedKey, CK_ATTRIBUTE[] pTemplate) + throws PKCS11Exception; /** @@ -1356,7 +1412,7 @@ public class PKCS11 { * @postconditions */ public native long C_DeriveKey(long hSession, CK_MECHANISM pMechanism, - long hBaseKey, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; + long hBaseKey, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception; @@ -1377,7 +1433,8 @@ public class PKCS11 { * @preconditions (pSeed <> null) * @postconditions */ - public native void C_SeedRandom(long hSession, byte[] pSeed) throws PKCS11Exception; + public native void C_SeedRandom(long hSession, byte[] pSeed) + throws PKCS11Exception; /** @@ -1393,7 +1450,8 @@ public class PKCS11 { * @preconditions (randomData <> null) * @postconditions */ - public native void C_GenerateRandom(long hSession, byte[] randomData) throws PKCS11Exception; + public native void C_GenerateRandom(long hSession, byte[] randomData) + throws PKCS11Exception; @@ -1413,7 +1471,8 @@ public class PKCS11 { * @preconditions * @postconditions */ -// public native void C_GetFunctionStatus(long hSession) throws PKCS11Exception; +// public native void C_GetFunctionStatus(long hSession) +// throws PKCS11Exception; /** @@ -1450,7 +1509,8 @@ public class PKCS11 { * @preconditions (pRserved == null) * @postconditions */ -// public native long C_WaitForSlotEvent(long flags, Object pRserved) throws PKCS11Exception; +// public native long C_WaitForSlotEvent(long flags, Object pRserved) +// throws PKCS11Exception; /** * Returns the string representation of this object. @@ -1476,7 +1536,8 @@ public class PKCS11 { // parent. Used for tokens that only support single threaded access static class SynchronizedPKCS11 extends PKCS11 { - SynchronizedPKCS11(String pkcs11ModulePath, String functionListName) throws IOException { + SynchronizedPKCS11(String pkcs11ModulePath, String functionListName) + throws IOException { super(pkcs11ModulePath, functionListName); } @@ -1484,7 +1545,8 @@ static class SynchronizedPKCS11 extends PKCS11 { super.C_Initialize(pInitArgs); } - public synchronized void C_Finalize(Object pReserved) throws PKCS11Exception { + public synchronized void C_Finalize(Object pReserved) + throws PKCS11Exception { super.C_Finalize(pReserved); } @@ -1492,39 +1554,48 @@ static class SynchronizedPKCS11 extends PKCS11 { return super.C_GetInfo(); } - public synchronized long[] C_GetSlotList(boolean tokenPresent) throws PKCS11Exception { + public synchronized long[] C_GetSlotList(boolean tokenPresent) + throws PKCS11Exception { return super.C_GetSlotList(tokenPresent); } - public synchronized CK_SLOT_INFO C_GetSlotInfo(long slotID) throws PKCS11Exception { + public synchronized CK_SLOT_INFO C_GetSlotInfo(long slotID) + throws PKCS11Exception { return super.C_GetSlotInfo(slotID); } - public synchronized CK_TOKEN_INFO C_GetTokenInfo(long slotID) throws PKCS11Exception { + public synchronized CK_TOKEN_INFO C_GetTokenInfo(long slotID) + throws PKCS11Exception { return super.C_GetTokenInfo(slotID); } - public synchronized long[] C_GetMechanismList(long slotID) throws PKCS11Exception { + public synchronized long[] C_GetMechanismList(long slotID) + throws PKCS11Exception { return super.C_GetMechanismList(slotID); } - public synchronized CK_MECHANISM_INFO C_GetMechanismInfo(long slotID, long type) throws PKCS11Exception { + public synchronized CK_MECHANISM_INFO C_GetMechanismInfo(long slotID, + long type) throws PKCS11Exception { return super.C_GetMechanismInfo(slotID, type); } - public synchronized long C_OpenSession(long slotID, long flags, Object pApplication, CK_NOTIFY Notify) throws PKCS11Exception { + public synchronized long C_OpenSession(long slotID, long flags, + Object pApplication, CK_NOTIFY Notify) throws PKCS11Exception { return super.C_OpenSession(slotID, flags, pApplication, Notify); } - public synchronized void C_CloseSession(long hSession) throws PKCS11Exception { + public synchronized void C_CloseSession(long hSession) + throws PKCS11Exception { super.C_CloseSession(hSession); } - public synchronized CK_SESSION_INFO C_GetSessionInfo(long hSession) throws PKCS11Exception { + public synchronized CK_SESSION_INFO C_GetSessionInfo(long hSession) + throws PKCS11Exception { return super.C_GetSessionInfo(hSession); } - public synchronized void C_Login(long hSession, long userType, char[] pPin) throws PKCS11Exception { + public synchronized void C_Login(long hSession, long userType, char[] pPin) + throws PKCS11Exception { super.C_Login(hSession, userType, pPin); } @@ -1532,157 +1603,207 @@ static class SynchronizedPKCS11 extends PKCS11 { super.C_Logout(hSession); } - public synchronized long C_CreateObject(long hSession, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { + public synchronized long C_CreateObject(long hSession, + CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { return super.C_CreateObject(hSession, pTemplate); } - public synchronized long C_CopyObject(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { + public synchronized long C_CopyObject(long hSession, long hObject, + CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { return super.C_CopyObject(hSession, hObject, pTemplate); } - public synchronized void C_DestroyObject(long hSession, long hObject) throws PKCS11Exception { + public synchronized void C_DestroyObject(long hSession, long hObject) + throws PKCS11Exception { super.C_DestroyObject(hSession, hObject); } - public synchronized void C_GetAttributeValue(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { + public synchronized void C_GetAttributeValue(long hSession, long hObject, + CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { super.C_GetAttributeValue(hSession, hObject, pTemplate); } - public synchronized void C_SetAttributeValue(long hSession, long hObject, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { + public synchronized void C_SetAttributeValue(long hSession, long hObject, + CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { super.C_SetAttributeValue(hSession, hObject, pTemplate); } - public synchronized void C_FindObjectsInit(long hSession, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { + public synchronized void C_FindObjectsInit(long hSession, + CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { super.C_FindObjectsInit(hSession, pTemplate); } - public synchronized long[] C_FindObjects(long hSession, long ulMaxObjectCount) throws PKCS11Exception { + public synchronized long[] C_FindObjects(long hSession, + long ulMaxObjectCount) throws PKCS11Exception { return super.C_FindObjects(hSession, ulMaxObjectCount); } - public synchronized void C_FindObjectsFinal(long hSession) throws PKCS11Exception { + public synchronized void C_FindObjectsFinal(long hSession) + throws PKCS11Exception { super.C_FindObjectsFinal(hSession); } - public synchronized void C_EncryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { + public synchronized void C_EncryptInit(long hSession, + CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { super.C_EncryptInit(hSession, pMechanism, hKey); } - public synchronized int C_Encrypt(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOfs, int outLen) throws PKCS11Exception { + public synchronized int C_Encrypt(long hSession, byte[] in, int inOfs, + int inLen, byte[] out, int outOfs, int outLen) + throws PKCS11Exception { return super.C_Encrypt(hSession, in, inOfs, inLen, out, outOfs, outLen); } - public synchronized int C_EncryptUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception { - return super.C_EncryptUpdate(hSession, directIn, in, inOfs, inLen, directOut, out, outOfs, outLen); + public synchronized int C_EncryptUpdate(long hSession, long directIn, + byte[] in, int inOfs, int inLen, long directOut, byte[] out, + int outOfs, int outLen) throws PKCS11Exception { + return super.C_EncryptUpdate(hSession, directIn, in, inOfs, inLen, + directOut, out, outOfs, outLen); } - public synchronized int C_EncryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception { + public synchronized int C_EncryptFinal(long hSession, long directOut, + byte[] out, int outOfs, int outLen) throws PKCS11Exception { return super.C_EncryptFinal(hSession, directOut, out, outOfs, outLen); } - public synchronized void C_DecryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { + public synchronized void C_DecryptInit(long hSession, + CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { super.C_DecryptInit(hSession, pMechanism, hKey); } - public synchronized int C_Decrypt(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOfs, int outLen) throws PKCS11Exception { + public synchronized int C_Decrypt(long hSession, byte[] in, int inOfs, + int inLen, byte[] out, int outOfs, int outLen) + throws PKCS11Exception { return super.C_Decrypt(hSession, in, inOfs, inLen, out, outOfs, outLen); } - public synchronized int C_DecryptUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception { - return super.C_DecryptUpdate(hSession, directIn, in, inOfs, inLen, directOut, out, outOfs, outLen); + public synchronized int C_DecryptUpdate(long hSession, long directIn, + byte[] in, int inOfs, int inLen, long directOut, byte[] out, + int outOfs, int outLen) throws PKCS11Exception { + return super.C_DecryptUpdate(hSession, directIn, in, inOfs, inLen, + directOut, out, outOfs, outLen); } - public synchronized int C_DecryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception { + public synchronized int C_DecryptFinal(long hSession, long directOut, + byte[] out, int outOfs, int outLen) throws PKCS11Exception { return super.C_DecryptFinal(hSession, directOut, out, outOfs, outLen); } - public synchronized void C_DigestInit(long hSession, CK_MECHANISM pMechanism) throws PKCS11Exception { + public synchronized void C_DigestInit(long hSession, CK_MECHANISM pMechanism) + throws PKCS11Exception { super.C_DigestInit(hSession, pMechanism); } - public synchronized int C_DigestSingle(long hSession, CK_MECHANISM pMechanism, byte[] in, int inOfs, int inLen, byte[] digest, int digestOfs, int digestLen) throws PKCS11Exception { - return super.C_DigestSingle(hSession, pMechanism, in, inOfs, inLen, digest, digestOfs, digestLen); + public synchronized int C_DigestSingle(long hSession, + CK_MECHANISM pMechanism, byte[] in, int inOfs, int inLen, + byte[] digest, int digestOfs, int digestLen) throws PKCS11Exception { + return super.C_DigestSingle(hSession, pMechanism, in, inOfs, inLen, + digest, digestOfs, digestLen); } - public synchronized void C_DigestUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception { + public synchronized void C_DigestUpdate(long hSession, long directIn, + byte[] in, int inOfs, int inLen) throws PKCS11Exception { super.C_DigestUpdate(hSession, directIn, in, inOfs, inLen); } - public synchronized void C_DigestKey(long hSession, long hKey) throws PKCS11Exception { + public synchronized void C_DigestKey(long hSession, long hKey) + throws PKCS11Exception { super.C_DigestKey(hSession, hKey); } - public synchronized int C_DigestFinal(long hSession, byte[] pDigest, int digestOfs, int digestLen) throws PKCS11Exception { + public synchronized int C_DigestFinal(long hSession, byte[] pDigest, + int digestOfs, int digestLen) throws PKCS11Exception { return super.C_DigestFinal(hSession, pDigest, digestOfs, digestLen); } - public synchronized void C_SignInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { + public synchronized void C_SignInit(long hSession, CK_MECHANISM pMechanism, + long hKey) throws PKCS11Exception { super.C_SignInit(hSession, pMechanism, hKey); } - public synchronized byte[] C_Sign(long hSession, byte[] pData) throws PKCS11Exception { + public synchronized byte[] C_Sign(long hSession, byte[] pData) + throws PKCS11Exception { return super.C_Sign(hSession, pData); } - public synchronized void C_SignUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception { + public synchronized void C_SignUpdate(long hSession, long directIn, + byte[] in, int inOfs, int inLen) throws PKCS11Exception { super.C_SignUpdate(hSession, directIn, in, inOfs, inLen); } - public synchronized byte[] C_SignFinal(long hSession, int expectedLen) throws PKCS11Exception { + public synchronized byte[] C_SignFinal(long hSession, int expectedLen) + throws PKCS11Exception { return super.C_SignFinal(hSession, expectedLen); } - public synchronized void C_SignRecoverInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { + public synchronized void C_SignRecoverInit(long hSession, + CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { super.C_SignRecoverInit(hSession, pMechanism, hKey); } - public synchronized int C_SignRecover(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOufs, int outLen) throws PKCS11Exception { - return super.C_SignRecover(hSession, in, inOfs, inLen, out, outOufs, outLen); + public synchronized int C_SignRecover(long hSession, byte[] in, int inOfs, + int inLen, byte[] out, int outOufs, int outLen) + throws PKCS11Exception { + return super.C_SignRecover(hSession, in, inOfs, inLen, out, outOufs, + outLen); } - public synchronized void C_VerifyInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { + public synchronized void C_VerifyInit(long hSession, CK_MECHANISM pMechanism, + long hKey) throws PKCS11Exception { super.C_VerifyInit(hSession, pMechanism, hKey); } - public synchronized void C_Verify(long hSession, byte[] pData, byte[] pSignature) throws PKCS11Exception { + public synchronized void C_Verify(long hSession, byte[] pData, + byte[] pSignature) throws PKCS11Exception { super.C_Verify(hSession, pData, pSignature); } - public synchronized void C_VerifyUpdate(long hSession, long directIn, byte[] in, int inOfs, int inLen) throws PKCS11Exception { + public synchronized void C_VerifyUpdate(long hSession, long directIn, + byte[] in, int inOfs, int inLen) throws PKCS11Exception { super.C_VerifyUpdate(hSession, directIn, in, inOfs, inLen); } - public synchronized void C_VerifyFinal(long hSession, byte[] pSignature) throws PKCS11Exception { + public synchronized void C_VerifyFinal(long hSession, byte[] pSignature) + throws PKCS11Exception { super.C_VerifyFinal(hSession, pSignature); } - public synchronized void C_VerifyRecoverInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { + public synchronized void C_VerifyRecoverInit(long hSession, + CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception { super.C_VerifyRecoverInit(hSession, pMechanism, hKey); } - public synchronized int C_VerifyRecover(long hSession, byte[] in, int inOfs, int inLen, byte[] out, int outOufs, int outLen) throws PKCS11Exception { - return super.C_VerifyRecover(hSession, in, inOfs, inLen, out, outOufs, outLen); + public synchronized int C_VerifyRecover(long hSession, byte[] in, int inOfs, + int inLen, byte[] out, int outOufs, int outLen) + throws PKCS11Exception { + return super.C_VerifyRecover(hSession, in, inOfs, inLen, out, outOufs, + outLen); } - public synchronized long C_GenerateKey(long hSession, CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { + public synchronized long C_GenerateKey(long hSession, + CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pTemplate) + throws PKCS11Exception { return super.C_GenerateKey(hSession, pMechanism, pTemplate); } public synchronized long[] C_GenerateKeyPair(long hSession, - CK_MECHANISM pMechanism, - CK_ATTRIBUTE[] pPublicKeyTemplate, - CK_ATTRIBUTE[] pPrivateKeyTemplate) throws PKCS11Exception { - return super.C_GenerateKeyPair(hSession, pMechanism, pPublicKeyTemplate, pPrivateKeyTemplate); + CK_MECHANISM pMechanism, CK_ATTRIBUTE[] pPublicKeyTemplate, + CK_ATTRIBUTE[] pPrivateKeyTemplate) + throws PKCS11Exception { + return super.C_GenerateKeyPair(hSession, pMechanism, pPublicKeyTemplate, + pPrivateKeyTemplate); } - public synchronized byte[] C_WrapKey(long hSession, CK_MECHANISM pMechanism, long hWrappingKey, long hKey) throws PKCS11Exception { + public synchronized byte[] C_WrapKey(long hSession, CK_MECHANISM pMechanism, + long hWrappingKey, long hKey) throws PKCS11Exception { return super.C_WrapKey(hSession, pMechanism, hWrappingKey, hKey); } public synchronized long C_UnwrapKey(long hSession, CK_MECHANISM pMechanism, - long hUnwrappingKey, byte[] pWrappedKey, - CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception { - return super.C_UnwrapKey(hSession, pMechanism, hUnwrappingKey, pWrappedKey, pTemplate); + long hUnwrappingKey, byte[] pWrappedKey, CK_ATTRIBUTE[] pTemplate) + throws PKCS11Exception { + return super.C_UnwrapKey(hSession, pMechanism, hUnwrappingKey, + pWrappedKey, pTemplate); } public synchronized long C_DeriveKey(long hSession, CK_MECHANISM pMechanism, @@ -1690,14 +1811,14 @@ static class SynchronizedPKCS11 extends PKCS11 { return super.C_DeriveKey(hSession, pMechanism, hBaseKey, pTemplate); } - public synchronized void C_SeedRandom(long hSession, byte[] pSeed) throws PKCS11Exception { + public synchronized void C_SeedRandom(long hSession, byte[] pSeed) + throws PKCS11Exception { super.C_SeedRandom(hSession, pSeed); } - public synchronized void C_GenerateRandom(long hSession, byte[] randomData) throws PKCS11Exception { + public synchronized void C_GenerateRandom(long hSession, byte[] randomData) + throws PKCS11Exception { super.C_GenerateRandom(hSession, randomData); } - } - } diff --git a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg index 3b3f7fa82f9..a2233d8cef1 100644 --- a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg +++ b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg @@ -17,23 +17,27 @@ useEcX963Encoding = true attributes = compatibility disabledMechanisms = { -# the following mechanisms are disabled due to lack of digest cloning support -# need to fix 6414899 first + CKM_DSA_KEY_PAIR_GEN +# the following mechanisms are disabled due to CKR_SAVED_STATE_INVALID bug +# (Solaris bug 7058108) CKM_MD2 CKM_MD5 CKM_SHA_1 +# the following mechanisms are disabled due to no cloning support +# (Solaris bug 7050617) CKM_SHA256 CKM_SHA384 CKM_SHA512 - CKM_DSA_KEY_PAIR_GEN -# the following mechanisms are disabled due to performance issues (Solaris bug 6337157) +# the following mechanisms are disabled due to performance issues +# (Solaris bug 6337157) CKM_DSA_SHA1 CKM_MD5_RSA_PKCS CKM_SHA1_RSA_PKCS CKM_SHA256_RSA_PKCS CKM_SHA384_RSA_PKCS CKM_SHA512_RSA_PKCS -# the following mechanisms are disabled to ensure backward compatibility (Solaris bug 6545046) +# the following mechanisms are disabled to ensure backward compatibility +# (Solaris bug 6545046) CKM_DES_CBC_PAD CKM_DES3_CBC_PAD CKM_AES_CBC_PAD diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h index bf3adf86a9d..81e79b9acd3 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -96,8 +96,8 @@ #define P11_ENABLE_C_CLOSESESSION #undef P11_ENABLE_C_CLOSEALLSESSIONS #define P11_ENABLE_C_GETSESSIONINFO -#undef P11_ENABLE_C_GETOPERATIONSTATE -#undef P11_ENABLE_C_SETOPERATIONSTATE +#define P11_ENABLE_C_GETOPERATIONSTATE +#define P11_ENABLE_C_SETOPERATIONSTATE #define P11_ENABLE_C_LOGIN #define P11_ENABLE_C_LOGOUT #define P11_ENABLE_C_CREATEOBJECT diff --git a/jdk/test/sun/security/pkcs11/MessageDigest/TestCloning.java b/jdk/test/sun/security/pkcs11/MessageDigest/TestCloning.java new file mode 100644 index 00000000000..b25acf04905 --- /dev/null +++ b/jdk/test/sun/security/pkcs11/MessageDigest/TestCloning.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6414899 + * @summary Ensure the cloning functionality works. + * @author Valerie Peng + * @library .. + */ + +import java.util.*; + +import java.security.*; + +public class TestCloning extends PKCS11Test { + + private static final String[] ALGOS = { + "MD2", "MD5", "SHA1", "SHA-256", "SHA-384", "SHA-512" + }; + + public static void main(String[] args) throws Exception { + main(new TestCloning()); + } + + private static final byte[] data1 = new byte[10]; + private static final byte[] data2 = new byte[10*1024]; + + + public void main(Provider p) throws Exception { + Random r = new Random(); + byte[] data1 = new byte[10]; + byte[] data2 = new byte[2*1024]; + r.nextBytes(data1); + r.nextBytes(data2); + System.out.println("Testing against provider " + p.getName()); + for (int i = 0; i < ALGOS.length; i++) { + if (p.getService("MessageDigest", ALGOS[i]) == null) { + System.out.println(ALGOS[i] + " is not supported, skipping"); + continue; + } else { + System.out.println("Testing " + ALGOS[i] + " of " + p.getName()); + MessageDigest md = MessageDigest.getInstance(ALGOS[i], p); + try { + md = testCloning(md, p); + // repeat the test again after generating digest once + for (int j = 0; j < 10; j++) { + md = testCloning(md, p); + } + } catch (Exception ex) { + if (ALGOS[i] == "MD2" && + p.getName().equalsIgnoreCase("SunPKCS11-NSS")) { + // known bug in NSS; ignore for now + System.out.println("Ignore Known bug in MD2 of NSS"); + continue; + } + throw ex; + } + } + } + } + + private static MessageDigest testCloning(MessageDigest mdObj, Provider p) + throws Exception { + + // copy#0: clone at state BLANK w/o any data + MessageDigest mdCopy0 = (MessageDigest) mdObj.clone(); + + // copy#1: clone again at state BUFFERED w/ very short data + mdObj.update(data1); + mdCopy0.update(data1); + MessageDigest mdCopy1 = (MessageDigest) mdObj.clone(); + + // copy#2: clone again after updating it w/ long data to trigger + // the state into INIT + mdObj.update(data2); + mdCopy0.update(data2); + mdCopy1.update(data2); + MessageDigest mdCopy2 = (MessageDigest) mdObj.clone(); + + // copy#3: clone again after updating it w/ very short data + mdObj.update(data1); + mdCopy0.update(data1); + mdCopy1.update(data1); + mdCopy2.update(data1); + MessageDigest mdCopy3 = (MessageDigest) mdObj.clone(); + + // copy#4: clone again after updating it w/ long data + mdObj.update(data2); + mdCopy0.update(data2); + mdCopy1.update(data2); + mdCopy2.update(data2); + mdCopy3.update(data2); + MessageDigest mdCopy4 = (MessageDigest) mdObj.clone(); + + // check digest equalities + byte[] answer = mdObj.digest(); + byte[] result0 = mdCopy0.digest(); + byte[] result1 = mdCopy1.digest(); + byte[] result2 = mdCopy2.digest(); + byte[] result3 = mdCopy3.digest(); + byte[] result4 = mdCopy4.digest(); + + + check(answer, result0, "copy0"); + check(answer, result1, "copy1"); + check(answer, result2, "copy2"); + check(answer, result3, "copy3"); + check(answer, result4, "copy4"); + + return mdCopy3; + } + + private static void check(byte[] d1, byte[] d2, String copyName) + throws Exception { + if (Arrays.equals(d1, d2) == false) { + throw new RuntimeException(copyName + " digest mismatch!"); + } + } +} + From 5fa281c0ee35ebe6f734d3fd095a6e76b39d0855 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Fri, 6 Jan 2012 15:00:22 +0000 Subject: [PATCH 02/96] 7127235: (fs) NPE in Files.walkFileTree if cached attributes are GC'ed Reviewed-by: forax, chegar --- jdk/src/share/classes/java/nio/file/FileTreeWalker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java index 6e1a83ff16f..7b1f43fe4ac 100644 --- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java +++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java @@ -92,7 +92,7 @@ class FileTreeWalker { (System.getSecurityManager() == null)) { BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get(); - if (!followLinks || !cached.isSymbolicLink()) + if (cached != null && (!followLinks || !cached.isSymbolicLink())) attrs = cached; } IOException exc = null; From 12558e2ef937b379c1995161ed3483dd368f1b6d Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Fri, 6 Jan 2012 16:06:41 -0800 Subject: [PATCH 03/96] 7033170: Cipher.getMaxAllowedKeyLength(String) throws NoSuchAlgorithmException Changed to always use full transformation as provider properties. Reviewed-by: mullan --- .../sun/security/pkcs11/SunPKCS11.java | 18 +++++++++---- .../javax/crypto/Cipher/GetMaxAllowed.java | 25 ++++++++++++++++--- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java index b94ca875e6c..8c432571e3a 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -606,24 +606,32 @@ public final class SunPKCS11 extends AuthProvider { m(CKM_DES_CBC)); d(CIP, "DES/CBC/PKCS5Padding", P11Cipher, m(CKM_DES_CBC_PAD, CKM_DES_CBC)); - d(CIP, "DES/ECB", P11Cipher, s("DES"), + d(CIP, "DES/ECB/NoPadding", P11Cipher, + m(CKM_DES_ECB)); + d(CIP, "DES/ECB/PKCS5Padding", P11Cipher, s("DES"), m(CKM_DES_ECB)); d(CIP, "DESede/CBC/NoPadding", P11Cipher, m(CKM_DES3_CBC)); d(CIP, "DESede/CBC/PKCS5Padding", P11Cipher, m(CKM_DES3_CBC_PAD, CKM_DES3_CBC)); - d(CIP, "DESede/ECB", P11Cipher, s("DESede"), + d(CIP, "DESede/ECB/NoPadding", P11Cipher, + m(CKM_DES3_ECB)); + d(CIP, "DESede/ECB/PKCS5Padding", P11Cipher, s("DESede"), m(CKM_DES3_ECB)); d(CIP, "AES/CBC/NoPadding", P11Cipher, m(CKM_AES_CBC)); d(CIP, "AES/CBC/PKCS5Padding", P11Cipher, m(CKM_AES_CBC_PAD, CKM_AES_CBC)); - d(CIP, "AES/ECB", P11Cipher, s("AES"), + d(CIP, "AES/ECB/NoPadding", P11Cipher, + m(CKM_AES_ECB)); + d(CIP, "AES/ECB/PKCS5Padding", P11Cipher, s("AES"), m(CKM_AES_ECB)); d(CIP, "AES/CTR/NoPadding", P11Cipher, m(CKM_AES_CTR)); - d(CIP, "Blowfish/CBC", P11Cipher, + d(CIP, "Blowfish/CBC/NoPadding", P11Cipher, + m(CKM_BLOWFISH_CBC)); + d(CIP, "Blowfish/CBC/PKCS5Padding", P11Cipher, m(CKM_BLOWFISH_CBC)); // XXX RSA_X_509, RSA_OAEP not yet supported diff --git a/jdk/test/javax/crypto/Cipher/GetMaxAllowed.java b/jdk/test/javax/crypto/Cipher/GetMaxAllowed.java index 3c14f8663eb..7ef6f439aac 100644 --- a/jdk/test/javax/crypto/Cipher/GetMaxAllowed.java +++ b/jdk/test/javax/crypto/Cipher/GetMaxAllowed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @bug 4807942 + * @bug 4807942 7033170 * @summary Test the Cipher.getMaxAllowedKeyLength(String) and * getMaxAllowedParameterSpec(String) methods * @author Valerie Peng @@ -40,7 +40,7 @@ import javax.crypto.spec.*; public class GetMaxAllowed { - private static void runTest(boolean isUnlimited) throws Exception { + private static void runTest1(boolean isUnlimited) throws Exception { System.out.println("Testing " + (isUnlimited? "un":"") + "limited policy..."); @@ -78,6 +78,20 @@ public class GetMaxAllowed { System.out.println("All tests passed"); } + private static void runTest2() throws Exception { + System.out.println("Testing against Security.getAlgorithms()"); + + Set algorithms = Security.getAlgorithms("Cipher"); + + for (String algorithm: algorithms) { + int keylength = -1; + + // if 7033170 is not fixed, NoSuchAlgorithmException is thrown + keylength = Cipher.getMaxAllowedKeyLength(algorithm); + + } + } + public static void main(String[] args) throws Exception { // decide if the installed jurisdiction policy file is the // unlimited version @@ -88,6 +102,9 @@ public class GetMaxAllowed { } catch (InvalidKeyException ike) { isUnlimited = false; } - runTest(isUnlimited); + runTest1(isUnlimited); + + // test using the set of algorithms returned by Security.getAlgorithms() + runTest2(); } } From 57096116d9550b2dce5799791c18bea39c8c03b9 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 6 Jan 2012 18:47:43 -0800 Subject: [PATCH 04/96] 7123649: Remove public modifier from Math.powerOfTwoF Reviewed-by: smarks, alanb --- jdk/src/share/classes/java/lang/Math.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/lang/Math.java b/jdk/src/share/classes/java/lang/Math.java index 059c20213ba..e7ba12a864a 100644 --- a/jdk/src/share/classes/java/lang/Math.java +++ b/jdk/src/share/classes/java/lang/Math.java @@ -1900,7 +1900,7 @@ public final class Math { /** * Returns a floating-point power of two in the normal range. */ - public static float powerOfTwoF(int n) { + static float powerOfTwoF(int n) { assert(n >= FloatConsts.MIN_EXPONENT && n <= FloatConsts.MAX_EXPONENT); return Float.intBitsToFloat(((n + FloatConsts.EXP_BIAS) << (FloatConsts.SIGNIFICAND_WIDTH-1)) From 6eb76c4598c567821bd4adb2f091a3b6b0f86290 Mon Sep 17 00:00:00 2001 From: Gary Adams Date: Mon, 9 Jan 2012 19:33:02 +0000 Subject: [PATCH 05/96] 7030573: test/java/io/FileInputStream/LargeFileAvailable.java fails when there is insufficient disk space Reviewed-by: alanb --- .../FileInputStream/LargeFileAvailable.java | 66 +++++++++++-------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/jdk/test/java/io/FileInputStream/LargeFileAvailable.java b/jdk/test/java/io/FileInputStream/LargeFileAvailable.java index 4f82ec1b78b..b6fbe4d57d3 100644 --- a/jdk/test/java/io/FileInputStream/LargeFileAvailable.java +++ b/jdk/test/java/io/FileInputStream/LargeFileAvailable.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6402006 + * @bug 6402006 7030573 * @summary Test if available returns correct value when reading * a large file. */ @@ -35,23 +35,35 @@ import java.nio.file.Files; import static java.nio.file.StandardOpenOption.*; public class LargeFileAvailable { - private static final long FILESIZE = 7405576182L; public static void main(String args[]) throws Exception { - File file = createLargeFile(FILESIZE); + // Create a temporary file in the current directory. + // Use it to check if we have 7G available for + // a large sparse file test. As a fallback use whatever + // space is available, so the test can proceed. + File file = File.createTempFile("largefile", null, new File(".")); + long spaceavailable = file.getUsableSpace(); + long filesize = Math.min(spaceavailable, 7405576182L); + if (spaceavailable == 0L) { + // A full disk is considered fatal. + throw new RuntimeException("No space available for temp file."); + } + + createLargeFile(filesize, file); + try (FileInputStream fis = new FileInputStream(file)) { - if (file.length() != FILESIZE) { - throw new RuntimeException("unexpected file size = " + file.length()); + if (file.length() != filesize) { + throw new RuntimeException("unexpected file size = " + + file.length()); } - long bigSkip = 3110608882L; - long remaining = FILESIZE; + long bigSkip = Math.min(filesize/2, 3110608882L); + long remaining = filesize; remaining -= skipBytes(fis, bigSkip, remaining); remaining -= skipBytes(fis, 10L, remaining); remaining -= skipBytes(fis, bigSkip, remaining); if (fis.available() != (int) remaining) { - throw new RuntimeException("available() returns " + - fis.available() + - " but expected " + remaining); + throw new RuntimeException("available() returns " + + fis.available() + " but expected " + remaining); } } finally { file.delete(); @@ -64,39 +76,41 @@ public class LargeFileAvailable { throws IOException { long skip = is.skip(toSkip); if (skip != toSkip) { - throw new RuntimeException("skip() returns " + skip + - " but expected " + toSkip); + throw new RuntimeException("skip() returns " + skip + + " but expected " + toSkip); } long remaining = avail - skip; int expected = remaining >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) remaining; - System.out.println("Skipped " + skip + " bytes " + - " available() returns " + expected + + System.out.println("Skipped " + skip + " bytes " + + " available() returns " + expected + " remaining=" + remaining); if (is.available() != expected) { - throw new RuntimeException("available() returns " + - is.available() + " but expected " + expected); + throw new RuntimeException("available() returns " + + is.available() + " but expected " + expected); } return skip; } - private static File createLargeFile(long filesize) throws Exception { - // Create a large file as a sparse file if possible - File largefile = File.createTempFile("largefile", null); - // re-create as a sparse file - Files.delete(largefile.toPath()); + private static void createLargeFile(long filesize, + File file) throws Exception { + // Recreate a large file as a sparse file if possible + Files.delete(file.toPath()); + try (FileChannel fc = - FileChannel.open(largefile.toPath(), - CREATE_NEW, WRITE, SPARSE)) { + FileChannel.open(file.toPath(), + CREATE_NEW, WRITE, SPARSE)) { ByteBuffer bb = ByteBuffer.allocate(1).put((byte)1); bb.rewind(); - int rc = fc.write(bb, filesize-1); + int rc = fc.write(bb, filesize - 1); + if (rc != 1) { - throw new RuntimeException("Failed to write 1 byte to the large file"); + throw new RuntimeException("Failed to write 1 byte" + + " to the large file"); } } - return largefile; + return; } } From f8400651e0d515084a0d201e394ca9e1ae39b8ed Mon Sep 17 00:00:00 2001 From: Martin Desruisseaux Date: Mon, 9 Jan 2012 15:54:44 -0800 Subject: [PATCH 06/96] 7128441: StrictMath performance improvement note shared with Math Reviewed-by: darcy --- jdk/src/share/classes/java/lang/Math.java | 41 ++++++++---- .../share/classes/java/lang/StrictMath.java | 64 +++++-------------- 2 files changed, 43 insertions(+), 62 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Math.java b/jdk/src/share/classes/java/lang/Math.java index e7ba12a864a..5453010b674 100644 --- a/jdk/src/share/classes/java/lang/Math.java +++ b/jdk/src/share/classes/java/lang/Math.java @@ -818,8 +818,9 @@ public final class Math { return (a >= b) ? a : b; } - private static long negativeZeroFloatBits = Float.floatToIntBits(-0.0f); - private static long negativeZeroDoubleBits = Double.doubleToLongBits(-0.0d); + // Use raw bit-wise conversions on guaranteed non-NaN arguments. + private static long negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f); + private static long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d); /** * Returns the greater of two {@code float} values. That is, @@ -836,9 +837,12 @@ public final class Math { * @return the larger of {@code a} and {@code b}. */ public static float max(float a, float b) { - if (a != a) return a; // a is NaN - if ((a == 0.0f) && (b == 0.0f) - && (Float.floatToIntBits(a) == negativeZeroFloatBits)) { + if (a != a) + return a; // a is NaN + if ((a == 0.0f) && + (b == 0.0f) && + (Float.floatToRawIntBits(a) == negativeZeroFloatBits)) { + // Raw conversion ok since NaN can't map to -0.0. return b; } return (a >= b) ? a : b; @@ -859,9 +863,12 @@ public final class Math { * @return the larger of {@code a} and {@code b}. */ public static double max(double a, double b) { - if (a != a) return a; // a is NaN - if ((a == 0.0d) && (b == 0.0d) - && (Double.doubleToLongBits(a) == negativeZeroDoubleBits)) { + if (a != a) + return a; // a is NaN + if ((a == 0.0d) && + (b == 0.0d) && + (Double.doubleToRawLongBits(a) == negativeZeroDoubleBits)) { + // Raw conversion ok since NaN can't map to -0.0. return b; } return (a >= b) ? a : b; @@ -910,9 +917,12 @@ public final class Math { * @return the smaller of {@code a} and {@code b}. */ public static float min(float a, float b) { - if (a != a) return a; // a is NaN - if ((a == 0.0f) && (b == 0.0f) - && (Float.floatToIntBits(b) == negativeZeroFloatBits)) { + if (a != a) + return a; // a is NaN + if ((a == 0.0f) && + (b == 0.0f) && + (Float.floatToRawIntBits(b) == negativeZeroFloatBits)) { + // Raw conversion ok since NaN can't map to -0.0. return b; } return (a <= b) ? a : b; @@ -933,9 +943,12 @@ public final class Math { * @return the smaller of {@code a} and {@code b}. */ public static double min(double a, double b) { - if (a != a) return a; // a is NaN - if ((a == 0.0d) && (b == 0.0d) - && (Double.doubleToLongBits(b) == negativeZeroDoubleBits)) { + if (a != a) + return a; // a is NaN + if ((a == 0.0d) && + (b == 0.0d) && + (Double.doubleToRawLongBits(b) == negativeZeroDoubleBits)) { + // Raw conversion ok since NaN can't map to -0.0. return b; } return (a <= b) ? a : b; diff --git a/jdk/src/share/classes/java/lang/StrictMath.java b/jdk/src/share/classes/java/lang/StrictMath.java index 723f1ec4cd3..e1c489551f1 100644 --- a/jdk/src/share/classes/java/lang/StrictMath.java +++ b/jdk/src/share/classes/java/lang/StrictMath.java @@ -161,6 +161,8 @@ public final class StrictMath { * in radians. */ public static strictfp double toRadians(double angdeg) { + // Do not delegate to Math.toRadians(angdeg) because + // this method has the strictfp modifier. return angdeg / 180.0 * PI; } @@ -176,6 +178,8 @@ public final class StrictMath { * in degrees. */ public static strictfp double toDegrees(double angrad) { + // Do not delegate to Math.toDegrees(angrad) because + // this method has the strictfp modifier. return angrad * 180.0 / PI; } @@ -708,7 +712,7 @@ public final class StrictMath { * @return the absolute value of the argument. */ public static int abs(int a) { - return (a < 0) ? -a : a; + return Math.abs(a); } /** @@ -725,7 +729,7 @@ public final class StrictMath { * @return the absolute value of the argument. */ public static long abs(long a) { - return (a < 0) ? -a : a; + return Math.abs(a); } /** @@ -744,7 +748,7 @@ public final class StrictMath { * @return the absolute value of the argument. */ public static float abs(float a) { - return (a <= 0.0F) ? 0.0F - a : a; + return Math.abs(a); } /** @@ -763,7 +767,7 @@ public final class StrictMath { * @return the absolute value of the argument. */ public static double abs(double a) { - return (a <= 0.0D) ? 0.0D - a : a; + return Math.abs(a); } /** @@ -777,7 +781,7 @@ public final class StrictMath { * @return the larger of {@code a} and {@code b}. */ public static int max(int a, int b) { - return (a >= b) ? a : b; + return Math.max(a, b); } /** @@ -791,13 +795,9 @@ public final class StrictMath { * @return the larger of {@code a} and {@code b}. */ public static long max(long a, long b) { - return (a >= b) ? a : b; + return Math.max(a, b); } - // Use raw bit-wise conversions on guaranteed non-NaN arguments. - private static long negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f); - private static long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d); - /** * Returns the greater of two {@code float} values. That is, * the result is the argument closer to positive infinity. If the @@ -813,15 +813,7 @@ public final class StrictMath { * @return the larger of {@code a} and {@code b}. */ public static float max(float a, float b) { - if (a != a) - return a; // a is NaN - if ((a == 0.0f) && - (b == 0.0f) && - (Float.floatToRawIntBits(a) == negativeZeroFloatBits)) { - // Raw conversion ok since NaN can't map to -0.0. - return b; - } - return (a >= b) ? a : b; + return Math.max(a, b); } /** @@ -839,15 +831,7 @@ public final class StrictMath { * @return the larger of {@code a} and {@code b}. */ public static double max(double a, double b) { - if (a != a) - return a; // a is NaN - if ((a == 0.0d) && - (b == 0.0d) && - (Double.doubleToRawLongBits(a) == negativeZeroDoubleBits)) { - // Raw conversion ok since NaN can't map to -0.0. - return b; - } - return (a >= b) ? a : b; + return Math.max(a, b); } /** @@ -861,7 +845,7 @@ public final class StrictMath { * @return the smaller of {@code a} and {@code b}. */ public static int min(int a, int b) { - return (a <= b) ? a : b; + return Math.min(a, b); } /** @@ -875,7 +859,7 @@ public final class StrictMath { * @return the smaller of {@code a} and {@code b}. */ public static long min(long a, long b) { - return (a <= b) ? a : b; + return Math.min(a, b); } /** @@ -893,15 +877,7 @@ public final class StrictMath { * @return the smaller of {@code a} and {@code b.} */ public static float min(float a, float b) { - if (a != a) - return a; // a is NaN - if ((a == 0.0f) && - (b == 0.0f) && - (Float.floatToRawIntBits(b) == negativeZeroFloatBits)) { - // Raw conversion ok since NaN can't map to -0.0. - return b; - } - return (a <= b) ? a : b; + return Math.min(a, b); } /** @@ -919,15 +895,7 @@ public final class StrictMath { * @return the smaller of {@code a} and {@code b}. */ public static double min(double a, double b) { - if (a != a) - return a; // a is NaN - if ((a == 0.0d) && - (b == 0.0d) && - (Double.doubleToRawLongBits(b) == negativeZeroDoubleBits)) { - // Raw conversion ok since NaN can't map to -0.0. - return b; - } - return (a <= b) ? a : b; + return Math.min(a, b); } /** From a821772a15ddb8fbf2f189986de7bda758f4c60c Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 9 Jan 2012 20:14:15 -0800 Subject: [PATCH 07/96] 7128512: Javadoc typo in java.lang.invoke.MethodHandle Reviewed-by: mduigou --- jdk/src/share/classes/java/lang/invoke/MethodHandle.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java index 3eda73af277..7bccf22c708 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java @@ -275,7 +275,7 @@ mh.invokeExact(System.out, "Hello, world."); * generates a single invokevirtual instruction with * the symbolic type descriptor indicated in the following comment. * In these examples, the helper method {@code assertEquals} is assumed to - * be a method which calls {@link Objects.equals java.util.Objects#equals} + * be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals } * on its arguments, and asserts that the result is true. * *

Exceptions

From f44b5b581292a5cba4be2f9b1b2ec0140bb0ba88 Mon Sep 17 00:00:00 2001 From: Brandon Passanisi Date: Tue, 10 Jan 2012 10:57:12 +0000 Subject: [PATCH 08/96] 7123415: Some cases of network interface indexes being read incorrectly Reviewed-by: chegar --- jdk/src/solaris/native/java/net/net_util_md.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/solaris/native/java/net/net_util_md.c b/jdk/src/solaris/native/java/net/net_util_md.c index b542f4187bc..963ef2e4416 100644 --- a/jdk/src/solaris/native/java/net/net_util_md.c +++ b/jdk/src/solaris/native/java/net/net_util_md.c @@ -588,7 +588,7 @@ static void initLoopbackRoutes() { int plen, scope, dad_status, if_idx; if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) { - while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", + while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, &dad_status, devname) == 13) { @@ -1078,7 +1078,7 @@ int getDefaultIPv6Interface(struct in6_addr *target_addr) { int plen, scope, dad_status, if_idx; if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) { - while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", + while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, &dad_status, devname) == 13) { From 59c8f5f79f6b18a615d2defef62f9ed38cc86424 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Tue, 10 Jan 2012 15:46:30 +0400 Subject: [PATCH 09/96] 7110815: closed/javax/swing/JSplitPane/4885629/bug4885629.java unstable on MacOS Reviewed-by: kizune --- .../swing/JSplitPane/4885629/bug4885629.java | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 jdk/test/javax/swing/JSplitPane/4885629/bug4885629.java diff --git a/jdk/test/javax/swing/JSplitPane/4885629/bug4885629.java b/jdk/test/javax/swing/JSplitPane/4885629/bug4885629.java new file mode 100644 index 00000000000..e475aecfab3 --- /dev/null +++ b/jdk/test/javax/swing/JSplitPane/4885629/bug4885629.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4885629 + * @summary With JSplitPane in VERTICAL_SPLIT, SplitPaneBorder draws bottom edge of divider + * @author Andrey Pikalev + */ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.plaf.basic.BasicBorders; +import javax.swing.plaf.basic.BasicLookAndFeel; +import javax.swing.plaf.basic.BasicSplitPaneUI; +import java.awt.*; + + +public class bug4885629 { + + private static final Color darkShadow = new Color(100,120,200); + private static final Color darkHighlight = new Color(200,120,50); + private static final Color lightHighlight = darkHighlight.brighter(); + private static final Color BGCOLOR = Color.blue; + + private static JSplitPane sp; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new BasicLookAndFeel() { + public boolean isSupportedLookAndFeel(){ return true; } + public boolean isNativeLookAndFeel(){ return false; } + public String getDescription() { return "Foo"; } + public String getID() { return "FooID"; } + public String getName() { return "FooName"; } + }); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + JFrame frame = new JFrame(); + + JComponent a = new JPanel(); + a.setBackground(Color.white); + a.setMinimumSize(new Dimension(10, 10)); + + JComponent b = new JPanel(); + b.setBackground(Color.white); + b.setMinimumSize(new Dimension(10, 10)); + + sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, a, b); + sp.setPreferredSize(new Dimension(20, 20)); + sp.setBackground(BGCOLOR); + + Border bo = new BasicBorders.SplitPaneBorder(lightHighlight, + Color.red); + Border ibo = new EmptyBorder(0, 0, 0, 0); + sp.setBorder(bo); + sp.setMinimumSize(new Dimension(200, 200)); + + ((BasicSplitPaneUI) sp.getUI()).getDivider().setBorder(ibo); + + frame.getContentPane().setLayout(new FlowLayout()); + frame.getContentPane().setBackground(darkShadow); + frame.getContentPane().add(sp); + + frame.setSize(200, 200); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + }); + + ((SunToolkit) SunToolkit.getDefaultToolkit()).realSync(); + + final Robot robot = new Robot(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Rectangle rect = ((BasicSplitPaneUI) sp.getUI()).getDivider().getBounds(); + + Point p = rect.getLocation(); + + SwingUtilities.convertPointToScreen(p, sp); + + for (int i = 0; i < rect.width; i++) { + if (!BGCOLOR.equals(robot.getPixelColor(p.x + i, p.y + rect.height - 1))) { + throw new Error("The divider's area has incorrect color."); + } + } + } + }); + } +} From a5c9da18fbf880ff182e65f347bc526d52da0495 Mon Sep 17 00:00:00 2001 From: Krystal Mok Date: Tue, 10 Jan 2012 12:48:08 +0000 Subject: [PATCH 10/96] 7128584: Typo in sun.misc.VM's private directMemory field comment Reviewed-by: forax, chegar --- jdk/src/share/classes/sun/misc/VM.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/misc/VM.java b/jdk/src/share/classes/sun/misc/VM.java index 61b3b0fd974..9928b840ea9 100644 --- a/jdk/src/share/classes/sun/misc/VM.java +++ b/jdk/src/share/classes/sun/misc/VM.java @@ -168,7 +168,7 @@ public class VM { // // 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(). + // otherwise to Runtime.getRuntime().maxMemory(). // private static long directMemory = 64 * 1024 * 1024; From a6f9704a9165804333defdebe59aa0992a0784e4 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Tue, 10 Jan 2012 17:11:10 +0400 Subject: [PATCH 11/96] 6505523: NullPointerException in BasicTreeUI when a node is removed by expansion listener Reviewed-by: rupashka --- .../javax/swing/plaf/basic/BasicTreeUI.java | 28 ++-- .../javax/swing/JTree/6505523/bug6505523.java | 132 ++++++++++++++++++ 2 files changed, 147 insertions(+), 13 deletions(-) create mode 100644 jdk/test/javax/swing/JTree/6505523/bug6505523.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java index f17b53739ed..f74edaf1ce4 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java @@ -1932,20 +1932,22 @@ public class BasicTreeUI extends TreeUI else { Rectangle beginRect = getPathBounds(tree, getPathForRow (tree, beginRow)); - Rectangle visRect = tree.getVisibleRect(); - Rectangle testRect = beginRect; - int beginY = beginRect.y; - int maxY = beginY + visRect.height; + if (beginRect != null) { + Rectangle visRect = tree.getVisibleRect(); + Rectangle testRect = beginRect; + int beginY = beginRect.y; + int maxY = beginY + visRect.height; - for(int counter = beginRow + 1; counter <= endRow; counter++) { - testRect = getPathBounds(tree, - getPathForRow(tree, counter)); - if((testRect.y + testRect.height) > maxY) - counter = endRow; + for(int counter = beginRow + 1; counter <= endRow; counter++) { + testRect = getPathBounds(tree, + getPathForRow(tree, counter)); + if((testRect.y + testRect.height) > maxY) + counter = endRow; + } + tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1, + testRect.y + testRect.height- + beginY)); } - tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1, - testRect.y + testRect.height- - beginY)); } } } @@ -3485,7 +3487,7 @@ public class BasicTreeUI extends TreeUI } Rectangle bounds = getPathBounds(tree, path); - if (y > (bounds.y + bounds.height)) { + if (bounds == null || y > (bounds.y + bounds.height)) { return false; } diff --git a/jdk/test/javax/swing/JTree/6505523/bug6505523.java b/jdk/test/javax/swing/JTree/6505523/bug6505523.java new file mode 100644 index 00000000000..40357dee6c9 --- /dev/null +++ b/jdk/test/javax/swing/JTree/6505523/bug6505523.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6505523 + * @summary NullPointerException in BasicTreeUI when a node is removed by expansion listener + * @author Alexandr Scherbatiy + * @run main bug6505523 + */ +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import sun.awt.SunToolkit; + +public class bug6505523 { + + private static JTree tree; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + Point point = getRowPointToClick(2); + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + toolkit.realSync(); + + } + + private static Point getRowPointToClick(final int row) throws Exception { + + final Point[] result = new Point[1]; + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + Rectangle rect = tree.getRowBounds(row); + Point point = new Point(rect.x - 5, rect.y + rect.height / 2); + SwingUtilities.convertPointToScreen(point, tree); + result[0] = point; + } + }); + + return result[0]; + } + + private static void createAndShowGUI() { + final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Problem with NPE under JDK 1.6"); + final DefaultMutableTreeNode problematic = new DefaultMutableTreeNode("Expand me and behold a NPE in stderr"); + problematic.add(new DefaultMutableTreeNode("some content")); + root.add(new DefaultMutableTreeNode("irrelevant...")); + root.add(problematic); + + final DefaultTreeModel model = new DefaultTreeModel(root); + tree = new JTree(model); + tree.setRootVisible(true); + tree.setShowsRootHandles(true); + tree.expandRow(0); + tree.collapseRow(2); + + // this is critical - without dragEnabled everything works + tree.setDragEnabled(true); + + tree.addTreeExpansionListener(new TreeExpansionListener() { + + @Override + public void treeExpanded(TreeExpansionEvent event) { + TreeNode parent = problematic.getParent(); + if (parent instanceof DefaultMutableTreeNode) { + model.removeNodeFromParent(problematic); + } + } + + @Override + public void treeCollapsed(TreeExpansionEvent event) { + } + }); + + JFrame frame = new JFrame("JTree Problem"); + frame.add(new JScrollPane(tree)); + frame.setSize(500, 300); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} \ No newline at end of file From d3428db5c5a5162b03a3b3bb82758e30dcad99fa Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 10 Jan 2012 17:12:11 -0800 Subject: [PATCH 12/96] 7112008: Javadoc for j.l.Object.finalize() vs JLS 12.6 Finalization of Class Instances Reviewed-by: mduigou --- jdk/src/share/classes/java/lang/Object.java | 32 +++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Object.java b/jdk/src/share/classes/java/lang/Object.java index d47b0a02311..763733c095a 100644 --- a/jdk/src/share/classes/java/lang/Object.java +++ b/jdk/src/share/classes/java/lang/Object.java @@ -58,8 +58,7 @@ public class Object { * * @return The {@code Class} object that represents the runtime * class of this object. - * @see Class Literals, section 15.8.2 of - * The Java™ Language Specification. + * @jls 15.8.2 Class Literals */ public final native Class getClass(); @@ -92,7 +91,7 @@ public class Object { * objects. (This is typically implemented by converting the internal * address of the object into an integer, but this implementation * technique is not required by the - * JavaTM programming language.) + * Java™ programming language.) * * @return a hash code value for this object. * @see java.lang.Object#equals(java.lang.Object) @@ -203,7 +202,7 @@ public class Object { * exception at run time. * * @return a clone of this instance. - * @exception CloneNotSupportedException if the object's class does not + * @throws CloneNotSupportedException if the object's class does not * support the {@code Cloneable} interface. Subclasses * that override the {@code clone} method can also * throw this exception to indicate that an instance cannot @@ -264,7 +263,7 @@ public class Object { *

* Only one thread at a time can own an object's monitor. * - * @exception IllegalMonitorStateException if the current thread is not + * @throws IllegalMonitorStateException if the current thread is not * the owner of this object's monitor. * @see java.lang.Object#notifyAll() * @see java.lang.Object#wait() @@ -288,7 +287,7 @@ public class Object { * description of the ways in which a thread can become the owner of * a monitor. * - * @exception IllegalMonitorStateException if the current thread is not + * @throws IllegalMonitorStateException if the current thread is not * the owner of this object's monitor. * @see java.lang.Object#notify() * @see java.lang.Object#wait() @@ -368,11 +367,11 @@ public class Object { * a monitor. * * @param timeout the maximum time to wait in milliseconds. - * @exception IllegalArgumentException if the value of timeout is + * @throws IllegalArgumentException if the value of timeout is * negative. - * @exception IllegalMonitorStateException if the current thread is not + * @throws IllegalMonitorStateException if the current thread is not * the owner of the object's monitor. - * @exception InterruptedException if any thread interrupted the + * @throws InterruptedException if any thread interrupted the * current thread before or while the current thread * was waiting for a notification. The interrupted * status of the current thread is cleared when @@ -433,12 +432,12 @@ public class Object { * @param timeout the maximum time to wait in milliseconds. * @param nanos additional time, in nanoseconds range * 0-999999. - * @exception IllegalArgumentException if the value of timeout is + * @throws IllegalArgumentException if the value of timeout is * negative or the value of nanos is * not in the range 0-999999. - * @exception IllegalMonitorStateException if the current thread is not + * @throws IllegalMonitorStateException if the current thread is not * the owner of this object's monitor. - * @exception InterruptedException if any thread interrupted the + * @throws InterruptedException if any thread interrupted the * current thread before or while the current thread * was waiting for a notification. The interrupted * status of the current thread is cleared when @@ -489,9 +488,9 @@ public class Object { * description of the ways in which a thread can become the owner of * a monitor. * - * @exception IllegalMonitorStateException if the current thread is not + * @throws IllegalMonitorStateException if the current thread is not * the owner of the object's monitor. - * @exception InterruptedException if any thread interrupted the + * @throws InterruptedException if any thread interrupted the * current thread before or while the current thread * was waiting for a notification. The interrupted * status of the current thread is cleared when @@ -510,7 +509,7 @@ public class Object { * system resources or to perform other cleanup. *

* The general contract of {@code finalize} is that it is invoked - * if and when the JavaTM virtual + * if and when the Java™ virtual * machine has determined that there is no longer any * means by which this object can be accessed by any thread that has * not yet died, except as a result of an action taken by the @@ -549,6 +548,9 @@ public class Object { * ignored. * * @throws Throwable the {@code Exception} raised by this method + * @see java.lang.ref.WeakReference + * @see java.lang.ref.PhantomReference + * @jls 12.6 Finalization of Class Instances */ protected void finalize() throws Throwable { } } From cd63594f4ae71a3d8417f275c8f5cd092400efef Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 10 Jan 2012 17:46:46 -0800 Subject: [PATCH 13/96] 7128931: Bad HTML escaping in java.lang.Throwable javadoc Reviewed-by: mduigou --- jdk/src/share/classes/java/lang/Throwable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/lang/Throwable.java b/jdk/src/share/classes/java/lang/Throwable.java index 2319aafd00f..c9c14e3b212 100644 --- a/jdk/src/share/classes/java/lang/Throwable.java +++ b/jdk/src/share/classes/java/lang/Throwable.java @@ -625,7 +625,7 @@ public class Throwable implements Serializable { * at Resource2.close(Resource2.java:20) * at Foo4.main(Foo4.java:5) * Caused by: java.lang.Exception: Rats, you caught me - * at Resource2$CloseFailException.(Resource2.java:45) + * at Resource2$CloseFailException.<init>(Resource2.java:45) * ... 2 more * */ From 1f16d123b1a4da5ad2347a300b0408b505b62ffc Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 11 Jan 2012 10:52:25 +0000 Subject: [PATCH 14/96] 7128648: HttpURLConnection.getHeaderFields should return an unmodifiable Map Reviewed-by: michaelm --- .../www/protocol/http/HttpURLConnection.java | 8 +- .../HttpURLConnection/UnmodifiableMaps.java | 149 ++++++++++++++++++ 2 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 jdk/test/java/net/HttpURLConnection/UnmodifiableMaps.java diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index ae2d682c9b9..8e894c7188e 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -2633,8 +2633,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { if (filteredHeaders != null) return filteredHeaders; - filteredHeaders = new HashMap<>(); - Map> headers; + Map> headers, tmpMap = new HashMap<>(); if (cachedHeaders != null) headers = cachedHeaders.getHeaders(); @@ -2650,11 +2649,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection { filteredVals.add(fVal); } if (!filteredVals.isEmpty()) - filteredHeaders.put(key, - Collections.unmodifiableList(filteredVals)); + tmpMap.put(key, Collections.unmodifiableList(filteredVals)); } - return filteredHeaders; + return filteredHeaders = Collections.unmodifiableMap(tmpMap); } /** diff --git a/jdk/test/java/net/HttpURLConnection/UnmodifiableMaps.java b/jdk/test/java/net/HttpURLConnection/UnmodifiableMaps.java new file mode 100644 index 00000000000..40205c893ae --- /dev/null +++ b/jdk/test/java/net/HttpURLConnection/UnmodifiableMaps.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7128648 + * @summary HttpURLConnection.getHeaderFields should return an unmodifiable Map + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.HttpURLConnection; +import java.util.Collection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.Headers; + +public class UnmodifiableMaps { + + void test(String[] args) throws Exception { + HttpServer server = startHttpServer(); + try { + InetSocketAddress address = server.getAddress(); + URI uri = new URI("http://" + InetAddress.getLocalHost().getHostAddress() + + ":" + address.getPort() + "/foo"); + doClient(uri); + } finally { + server.stop(0); + } + } + + void doClient(URI uri) throws Exception { + HttpURLConnection uc = (HttpURLConnection) uri.toURL().openConnection(); + + // Test1: getRequestProperties is unmodifiable + System.out.println("Check getRequestProperties"); + checkUnmodifiable(uc.getRequestProperties()); + uc.addRequestProperty("X", "V"); + uc.addRequestProperty("X1", "V1"); + checkUnmodifiable(uc.getRequestProperties()); + + int resp = uc.getResponseCode(); + check(resp == 200, + "Unexpected response code. Expected 200, got " + resp); + + // Test2: getHeaderFields is unmodifiable + System.out.println("Check getHeaderFields"); + checkUnmodifiable(uc.getHeaderFields()); + // If the implementation does caching, check again. + checkUnmodifiable(uc.getHeaderFields()); + } + + // HTTP Server + HttpServer startHttpServer() throws IOException { + HttpServer httpServer = HttpServer.create(new InetSocketAddress(0), 0); + httpServer.createContext("/foo", new SimpleHandler()); + httpServer.start(); + return httpServer; + } + + class SimpleHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + Headers respHeaders = t.getResponseHeaders(); + // ensure some response headers, over the usual ones + respHeaders.add("RespHdr1", "Value1"); + respHeaders.add("RespHdr2", "Value2"); + respHeaders.add("RespHdr3", "Value3"); + t.sendResponseHeaders(200, -1); + t.close(); + } + } + + void checkUnmodifiable(Map> map) { + checkUnmodifiableMap(map); + + // Now check the individual values + Collection> values = map.values(); + for (List value : values) { + checkUnmodifiableList(value); + } + } + + void checkUnmodifiableMap(final Map> map) { + expectThrow( new Runnable() { + public void run() { map.clear(); }}); + expectThrow( new Runnable() { + public void run() { map.put("X", new ArrayList()); }}); + expectThrow( new Runnable() { + public void run() { map.remove("X"); }}); + } + + void checkUnmodifiableList(final List list) { + expectThrow( new Runnable() { + public void run() { list.clear(); }}); + expectThrow( new Runnable() { + public void run() { list.add("X"); }}); + expectThrow( new Runnable() { + public void run() { list.remove("X"); }}); + } + + void expectThrow(Runnable r) { + try { r.run(); fail("Excepted UOE to be thrown."); Thread.dumpStack(); } + catch (UnsupportedOperationException e) { pass(); } + } + + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++;} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} + public static void main(String[] args) throws Throwable { + Class k = new Object(){}.getClass().getEnclosingClass(); + try {k.getMethod("instanceMain",String[].class) + .invoke( k.newInstance(), (Object) args);} + catch (Throwable e) {throw e.getCause();}} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} + From 69a71c999c711ca6c697c30bedfe7ef1217e5602 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 11 Jan 2012 13:07:15 +0000 Subject: [PATCH 15/96] 7068856: (fs) Typo in Files.isSameFile() javadoc 7099208: (fs) Files.newBufferedReader has typo in javadoc Reviewed-by: forax --- jdk/src/share/classes/java/nio/file/Files.java | 2 +- jdk/src/share/classes/java/nio/file/Path.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/java/nio/file/Files.java b/jdk/src/share/classes/java/nio/file/Files.java index 2683b7efe09..f46ae4cd40b 100644 --- a/jdk/src/share/classes/java/nio/file/Files.java +++ b/jdk/src/share/classes/java/nio/file/Files.java @@ -1431,7 +1431,7 @@ public final class Files { *

  • It is transitive: for three {@code Paths} * {@code f}, {@code g}, and {@code h}, if {@code isSameFile(f,g)} returns * {@code true} and {@code isSameFile(g,h)} returns {@code true}, then - * {@code isSameFile(g,h)} will return return {@code true}. + * {@code isSameFile(f,h)} will return return {@code true}. * * * @param path diff --git a/jdk/src/share/classes/java/nio/file/Path.java b/jdk/src/share/classes/java/nio/file/Path.java index 6e572684727..92cd1f9661e 100644 --- a/jdk/src/share/classes/java/nio/file/Path.java +++ b/jdk/src/share/classes/java/nio/file/Path.java @@ -72,7 +72,7 @@ import java.util.Iterator; * directory and is UTF-8 encoded. *
      *     Path path = FileSystems.getDefault().getPath("logs", "access.log");
    - *     BufferReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
    + *     BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
      * 
    * *

    Interoperability

    From 86fa49b707dd741f521036a063e9f83517180203 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Wed, 11 Jan 2012 08:14:47 -0800 Subject: [PATCH 16/96] 7125442: jar application located in two bytes character named folder cannot be run with JRE 7 u1/u2 Reviewed-by: sherman, mchung, darcy --- jdk/src/share/bin/java.c | 11 +-- jdk/test/tools/launcher/I18NJarTest.java | 110 +++++++++++++++++++++++ jdk/test/tools/launcher/TestHelper.java | 28 ++++-- 3 files changed, 135 insertions(+), 14 deletions(-) create mode 100644 jdk/test/tools/launcher/I18NJarTest.java diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c index f084bd2ba2e..2d88dc9f751 100644 --- a/jdk/src/share/bin/java.c +++ b/jdk/src/share/bin/java.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1225,14 +1225,7 @@ LoadMainClass(JNIEnv *env, int mode, char *name) "checkAndLoadMain", "(ZILjava/lang/String;)Ljava/lang/Class;")); - switch (mode) { - case LM_CLASS: - str = NewPlatformString(env, name); - break; - default: - str = (*env)->NewStringUTF(env, name); - break; - } + str = NewPlatformString(env, name); result = (*env)->CallStaticObjectMethod(env, cls, mid, USE_STDERR, mode, str); if (JLI_IsTraceLauncher()) { diff --git a/jdk/test/tools/launcher/I18NJarTest.java b/jdk/test/tools/launcher/I18NJarTest.java new file mode 100644 index 00000000000..70193296c17 --- /dev/null +++ b/jdk/test/tools/launcher/I18NJarTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7125442 + * @summary ensures a jar path as well as a class located in a path containing + * unicode characters are launched. + * @compile -XDignore.symbol.file I18NJarTest.java TestHelper.java + * @run main/othervm I18NJarTest + */ +import java.io.File; +import java.util.Locale; + +/* + * Note 1: the system must have the correct Locale, in order for the test to + * work correctly, on those systems that do not comply, the test will succeed. + * Here are some guidelines to set the locale correctly. + * On Windows: ControlPanel->Regional Settings, + * ensure that "Japanese" is selected and checked, and in + * "Code page conversion tables", the following must be checked, + * 932 (ANSI/OEM - Japanese Shift-JIS). + * On Unix: use "locale -a" verify one of these exist ja_JP.UTF-8 or + * ja_JP.utf8 or ja_JP.ujis, and export one of them with LC_ALL. + * + * + * Note 2: since we need to set the locale, it is safest to execute this test + * in its own VM (othervm mode), such that the ensuing tests can run unperturbed, + * regardless of the outcome. + */ +public class I18NJarTest { + private static final File cwd = new File("."); + private static final File dir = new File("\uFF66\uFF67\uFF68\uFF69"); + private static final String encoding = System.getProperty("sun.jnu.encoding", ""); + + public static void main(String... args) throws Exception { + boolean localeAvailable = false; + for (Locale l : Locale.getAvailableLocales()) { + if (l.toLanguageTag().equals(Locale.JAPAN.toLanguageTag())) { + localeAvailable = true; + break; + } + } + if (!localeAvailable) { + System.out.println("Warning: locale: " + Locale.JAPAN + + " not found, test passes vacuosly"); + return; + } + if (encoding.equals("MS932") || encoding.equals("UTF-8")) { + Locale.setDefault(Locale.JAPAN); + System.out.println("using locale " + Locale.JAPAN + + ", encoding " + encoding); + } else { + System.out.println("Warning: current encoding is " + encoding + + "this test requires MS932 or UTF-8," + + " test passes vacuosly"); + return; + } + dir.mkdir(); + File dirfile = new File(dir, "foo.jar"); + TestHelper.createJar(dirfile, + "public static void main(String... args) {", + "System.out.println(\"Hello World\");", + "System.exit(0);", + "}"); + + // remove the class files, to ensure that the class is indeed picked up + // from the jar file and not from ambient classpath. + File[] classFiles = cwd.listFiles(TestHelper.createFilter(TestHelper.CLASS_FILE_EXT)); + for (File f : classFiles) { + f.delete(); + } + + // test with a jar file + TestHelper.TestResult tr = TestHelper.doExec(TestHelper.javaCmd, + "-jar", dirfile.getAbsolutePath()); + System.out.println(tr); + if (!tr.isOK()) { + throw new RuntimeException("TEST FAILED"); + } + + // test the same class but by specifying it as a classpath + tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", + dirfile.getAbsolutePath(), "Foo"); + System.out.println(tr); + if (!tr.isOK()) { + throw new RuntimeException("TEST FAILED"); + } + } +} diff --git a/jdk/test/tools/launcher/TestHelper.java b/jdk/test/tools/launcher/TestHelper.java index 6465811cebf..c0f1119554c 100644 --- a/jdk/test/tools/launcher/TestHelper.java +++ b/jdk/test/tools/launcher/TestHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,23 +21,24 @@ * questions. */ -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.FileVisitResult; -import java.nio.file.SimpleFileVisitor; -import javax.tools.ToolProvider; import java.io.BufferedReader; import java.io.File; +import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; +import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.Files; +import java.nio.file.FileVisitResult; +import java.nio.file.SimpleFileVisitor; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; import static java.nio.file.StandardCopyOption.*; @@ -68,6 +69,10 @@ public enum TestHelper { static final boolean isDualMode = isSolaris; static final boolean isSparc = System.getProperty("os.arch").startsWith("sparc"); + static final String JAVA_FILE_EXT = ".java"; + static final String CLASS_FILE_EXT = ".class"; + static final String JAR_FILE_EXT = ".jar"; + static int testExitValue = 0; static { @@ -303,6 +308,19 @@ public enum TestHelper { } } + static FileFilter createFilter(final String extension) { + return new FileFilter() { + @Override + public boolean accept(File pathname) { + String name = pathname.getName(); + if (name.endsWith(extension)) { + return true; + } + return false; + } + }; + } + /* * A class to encapsulate the test results and stuff, with some ease * of use methods to check the test results. From 2c453c5844b04e8533977f46fd1a9aa04b9b2d36 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Wed, 11 Jan 2012 18:23:24 +0000 Subject: [PATCH 17/96] 7126754: Generics compilation failure casting List to List Problems with Types.rewriteQuantifiers not preserving variance Reviewed-by: jjg --- .../com/sun/tools/javac/code/Types.java | 47 ++++++++++--------- .../tools/javac/cast/7126754/T7126754.java | 14 ++++++ .../tools/javac/cast/7126754/T7126754.out | 4 ++ 3 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 langtools/test/tools/javac/cast/7126754/T7126754.java create mode 100644 langtools/test/tools/javac/cast/7126754/T7126754.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 5fc9d4547ed..aac5c29f1a0 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3600,39 +3600,44 @@ public class Types { @Override public Type visitCapturedType(CapturedType t, Void s) { - Type bound = visitWildcardType(t.wildcard, null); - return (bound.contains(t)) ? - erasure(bound) : - bound; + Type w_bound = t.wildcard.type; + Type bound = w_bound.contains(t) ? + erasure(w_bound) : + visit(w_bound); + return rewriteAsWildcardType(visit(bound), t.wildcard.bound, t.wildcard.kind); } @Override public Type visitTypeVar(TypeVar t, Void s) { if (rewriteTypeVars) { - Type bound = high ? - (t.bound.contains(t) ? + Type bound = t.bound.contains(t) ? erasure(t.bound) : - visit(t.bound)) : - syms.botType; - return rewriteAsWildcardType(bound, t); - } - else + visit(t.bound); + return rewriteAsWildcardType(bound, t, EXTENDS); + } else { return t; + } } @Override public Type visitWildcardType(WildcardType t, Void s) { - Type bound = high ? t.getExtendsBound() : - t.getSuperBound(); - if (bound == null) - bound = high ? syms.objectType : syms.botType; - return rewriteAsWildcardType(visit(bound), t.bound); + Type bound2 = visit(t.type); + return t.type == bound2 ? t : rewriteAsWildcardType(bound2, t.bound, t.kind); } - private Type rewriteAsWildcardType(Type bound, TypeVar formal) { - return high ? - makeExtendsWildcard(B(bound), formal) : - makeSuperWildcard(B(bound), formal); + private Type rewriteAsWildcardType(Type bound, TypeVar formal, BoundKind bk) { + switch (bk) { + case EXTENDS: return high ? + makeExtendsWildcard(B(bound), formal) : + makeExtendsWildcard(syms.objectType, formal); + case SUPER: return high ? + makeSuperWildcard(syms.botType, formal) : + makeSuperWildcard(B(bound), formal); + case UNBOUND: return makeExtendsWildcard(syms.objectType, formal); + default: + Assert.error("Invalid bound kind " + bk); + return null; + } } Type B(Type t) { diff --git a/langtools/test/tools/javac/cast/7126754/T7126754.java b/langtools/test/tools/javac/cast/7126754/T7126754.java new file mode 100644 index 00000000000..79e49ecf23a --- /dev/null +++ b/langtools/test/tools/javac/cast/7126754/T7126754.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @author mcimadamore + * @bug 7005671 + * @summary Generics compilation failure casting List to List + * @compile/fail/ref=T7126754.out -Xlint:unchecked -Werror -XDrawDiagnostics T7126754.java + */ + +import java.util.List; + +class T7126754 { + List> c = null; + List> d = (List>)c; +} diff --git a/langtools/test/tools/javac/cast/7126754/T7126754.out b/langtools/test/tools/javac/cast/7126754/T7126754.out new file mode 100644 index 00000000000..73baf16fe12 --- /dev/null +++ b/langtools/test/tools/javac/cast/7126754/T7126754.out @@ -0,0 +1,4 @@ +T7126754.java:13:68: compiler.warn.prob.found.req: (compiler.misc.unchecked.cast.to.type), java.util.List>, java.util.List> +- compiler.err.warnings.and.werror +1 error +1 warning From 007126d01029478cc421af2cf421d92b525c1194 Mon Sep 17 00:00:00 2001 From: Markus Gronlund Date: Wed, 11 Jan 2012 17:34:02 -0500 Subject: [PATCH 18/96] 7115199: Add event tracing hooks and Java Flight Recorder infrastructure Added a nop tracing infrastructure, JFR makefile changes and other infrastructure used only by JFR. Reviewed-by: acorn, sspitsyn --- hotspot/make/Makefile | 12 +++++- hotspot/make/bsd/makefiles/vm.make | 10 +++++ hotspot/make/defs.make | 4 ++ hotspot/make/linux/makefiles/vm.make | 10 +++++ hotspot/make/solaris/makefiles/vm.make | 6 ++- hotspot/make/windows/build.bat | 2 + hotspot/make/windows/create_obj_files.sh | 7 +++ .../windows/makefiles/projectcreator.make | 5 ++- hotspot/make/windows/makefiles/vm.make | 36 ++++++++++++++-- .../src/share/vm/classfile/symbolTable.cpp | 18 ++++++++ .../src/share/vm/classfile/symbolTable.hpp | 3 ++ .../share/vm/classfile/systemDictionary.cpp | 6 +++ hotspot/src/share/vm/oops/klass.cpp | 3 ++ hotspot/src/share/vm/oops/klass.hpp | 8 ++++ hotspot/src/share/vm/oops/methodKlass.cpp | 1 + hotspot/src/share/vm/oops/methodOop.hpp | 8 +++- hotspot/src/share/vm/prims/jni.cpp | 15 ++++++- hotspot/src/share/vm/prims/jniExport.hpp | 42 ++++++++++++++++++ hotspot/src/share/vm/runtime/java.cpp | 7 +++ hotspot/src/share/vm/runtime/mutexLocker.cpp | 14 +++++- hotspot/src/share/vm/runtime/mutexLocker.hpp | 6 +++ hotspot/src/share/vm/runtime/os.cpp | 1 + hotspot/src/share/vm/runtime/thread.cpp | 24 +++++++++++ hotspot/src/share/vm/runtime/thread.hpp | 6 +++ .../src/share/vm/runtime/vm_operations.hpp | 1 + .../src/share/vm/trace/traceEventTypes.hpp | 30 +++++++++++++ hotspot/src/share/vm/trace/traceMacros.hpp | 43 +++++++++++++++++++ hotspot/src/share/vm/trace/tracing.hpp | 30 +++++++++++++ .../share/vm/utilities/globalDefinitions.hpp | 5 +++ 29 files changed, 352 insertions(+), 11 deletions(-) create mode 100644 hotspot/src/share/vm/prims/jniExport.hpp create mode 100644 hotspot/src/share/vm/trace/traceEventTypes.hpp create mode 100644 hotspot/src/share/vm/trace/traceMacros.hpp create mode 100644 hotspot/src/share/vm/trace/tracing.hpp diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index 5bef049093b..1d6af55a37c 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -367,7 +367,7 @@ endif $(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar $(install-file) -# Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h) +# Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h) $(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/% $(install-file) @@ -384,6 +384,16 @@ $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h: $(HS_JNI_ARCH_SRC) $(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/services/% $(install-file) +JFR_EXISTS=$(shell if [ -d $(HS_ALT_SRC) ]; then echo 1; else echo 0; fi) +# export jfr.h +ifeq ($JFR_EXISTS,1) +$(EXPORT_INCLUDE_DIR)/%: $(HS_ALT_SRC)/share/vm/jfr/agent/% + $(install-file) +else +$(EXPORT_INCLUDE_DIR)/jfr.h: + +endif + # Doc files (jvmti.html) $(EXPORT_DOCS_DIR)/platform/jvmti/%: $(DOCS_DIR)/% $(install-file) diff --git a/hotspot/make/bsd/makefiles/vm.make b/hotspot/make/bsd/makefiles/vm.make index 35eca5dbeb3..0fad0639727 100644 --- a/hotspot/make/bsd/makefiles/vm.make +++ b/hotspot/make/bsd/makefiles/vm.make @@ -96,6 +96,10 @@ ifdef DEFAULT_LIBPATH CPPFLAGS += -DDEFAULT_LIBPATH="\"$(DEFAULT_LIBPATH)\"" endif +ifndef JAVASE_EMBEDDED +CFLAGS += -DINCLUDE_TRACE +endif + # CFLAGS_WARN holds compiler options to suppress/enable warnings. CFLAGS += $(CFLAGS_WARN/BYFILE) @@ -147,6 +151,12 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm +ifndef JAVASE_EMBEDDED +SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ + find $(HS_ALT_SRC)/share/vm/jfr -type d; \ + fi) +endif + CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) CORE_PATHS+=$(GENERATED)/jvmtifiles diff --git a/hotspot/make/defs.make b/hotspot/make/defs.make index 7434daebce6..3a355c76997 100644 --- a/hotspot/make/defs.make +++ b/hotspot/make/defs.make @@ -294,3 +294,7 @@ EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jvmticmlr.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jni.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h + +ifndef JAVASE_EMBEDDED +EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jfr.h +endif diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make index d40678202e2..fa2bcc3b05a 100644 --- a/hotspot/make/linux/makefiles/vm.make +++ b/hotspot/make/linux/makefiles/vm.make @@ -98,6 +98,10 @@ CPPFLAGS = \ ${JRE_VERSION} \ ${VM_DISTRO} +ifndef JAVASE_EMBEDDED +CFLAGS += -DINCLUDE_TRACE +endif + # CFLAGS_WARN holds compiler options to suppress/enable warnings. CFLAGS += $(CFLAGS_WARN/BYFILE) @@ -143,6 +147,12 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm +ifndef JAVASE_EMBEDDED +SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ + find $(HS_ALT_SRC)/share/vm/jfr -type d; \ + fi) +endif + CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) CORE_PATHS+=$(GENERATED)/jvmtifiles diff --git a/hotspot/make/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make index 7b950af7f24..0895ea0ba79 100644 --- a/hotspot/make/solaris/makefiles/vm.make +++ b/hotspot/make/solaris/makefiles/vm.make @@ -93,7 +93,7 @@ CFLAGS += $(CFLAGS_WARN) CFLAGS += $(CFLAGS/NOEX) # Extra flags from gnumake's invocation or environment -CFLAGS += $(EXTRA_CFLAGS) +CFLAGS += $(EXTRA_CFLAGS) -DINCLUDE_TRACE # Math Library (libm.so), do not use -lm. # There might be two versions of libm.so on the build system: @@ -160,6 +160,10 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm +SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ + find $(HS_ALT_SRC)/share/vm/jfr -type d; \ + fi) + CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) CORE_PATHS+=$(GENERATED)/jvmtifiles diff --git a/hotspot/make/windows/build.bat b/hotspot/make/windows/build.bat index ee0a6b058d2..ac63bb2ad4a 100644 --- a/hotspot/make/windows/build.bat +++ b/hotspot/make/windows/build.bat @@ -35,6 +35,8 @@ cl 2>&1 | grep "IA-64" >NUL if %errorlevel% == 0 goto isia64 cl 2>&1 | grep "AMD64" >NUL if %errorlevel% == 0 goto amd64 +cl 2>&1 | grep "x64" >NUL +if %errorlevel% == 0 goto amd64 set ARCH=x86 set BUILDARCH=i486 set Platform_arch=x86 diff --git a/hotspot/make/windows/create_obj_files.sh b/hotspot/make/windows/create_obj_files.sh index 59fe3a6932c..61903387dbe 100644 --- a/hotspot/make/windows/create_obj_files.sh +++ b/hotspot/make/windows/create_obj_files.sh @@ -73,6 +73,13 @@ done BASE_PATHS="${BASE_PATHS} ${GENERATED}/jvmtifiles" +if [ -d "${ALTSRC}/share/vm/jfr" ]; then + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/agent" + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/agent/isolated_deps/util" + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/jvm" + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr" +fi + CORE_PATHS="${BASE_PATHS}" # shared is already in BASE_PATHS. Should add vm/memory but that one is also in BASE_PATHS. if [ -d "${ALTSRC}/share/vm/gc_implementation" ]; then diff --git a/hotspot/make/windows/makefiles/projectcreator.make b/hotspot/make/windows/makefiles/projectcreator.make index 938ce82e9f1..3a6f9aa1b8d 100644 --- a/hotspot/make/windows/makefiles/projectcreator.make +++ b/hotspot/make/windows/makefiles/projectcreator.make @@ -58,7 +58,8 @@ ProjectCreatorIncludesPRIVATE=\ -absoluteInclude $(HOTSPOTBUILDSPACE)/%f/generated \ -ignorePath $(HOTSPOTBUILDSPACE)/%f/generated \ -ignorePath src\share\vm\adlc \ - -ignorePath src\share\vm\shark + -ignorePath src\share\vm\shark \ + -ignorePath posix # This is referenced externally by both the IDE and batch builds ProjectCreatorOptions= @@ -88,7 +89,7 @@ ProjectCreatorIDEOptions=\ -jdkTargetRoot $(HOTSPOTJDKDIST) \ -define ALIGN_STACK_FRAMES \ -define VM_LITTLE_ENDIAN \ - -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \ + -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) set JAVA_HOME=$(HOTSPOTJDKDIST) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \ -postbuild "" "Building hotspot.exe..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \ -ignoreFile jsig.c \ -ignoreFile jvmtiEnvRecommended.cpp \ diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make index f0b1b933630..d8c43a1f329 100644 --- a/hotspot/make/windows/makefiles/vm.make +++ b/hotspot/make/windows/makefiles/vm.make @@ -19,7 +19,7 @@ # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA # or visit www.oracle.com if you need additional information or have any # questions. -# +# # # Resource file containing VERSIONINFO @@ -30,7 +30,7 @@ Res_Files=.\version.res COMMONSRC=$(WorkSpace)\src ALTSRC=$(WorkSpace)\src\closed -!ifdef RELEASE +!ifdef RELEASE !ifdef DEVELOP CPP_FLAGS=$(CPP_FLAGS) /D "DEBUG" !else @@ -74,6 +74,10 @@ CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_TARGET=\"$(BUILD_FLAVOR)\"" CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_USER=\"$(BuildUser)\"" CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_VM_DISTRO=\"$(HOTSPOT_VM_DISTRO)\"" +!ifndef JAVASE_EMBEDDED +CPP_FLAGS=$(CPP_FLAGS) /D "INCLUDE_TRACE" +!endif + CPP_FLAGS=$(CPP_FLAGS) $(CPP_INCLUDE_DIRS) # Define that so jni.h is on correct side @@ -97,7 +101,7 @@ AGCT_EXPORT=/export:AsyncGetCallTrace !endif # If you modify exports below please do the corresponding changes in -# src/share/tools/ProjectCreator/WinGammaPlatformVC7.java +# src/share/tools/ProjectCreator/WinGammaPlatformVC7.java LINK_FLAGS=$(LINK_FLAGS) $(STACK_SIZE) /subsystem:windows /dll /base:0x8000000 \ /export:JNI_GetDefaultJavaVMInitArgs \ /export:JNI_CreateJavaVM \ @@ -170,6 +174,7 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/oops VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/runtime VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/services +VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/trace VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/utilities VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/libadt VM_PATH=$(VM_PATH);$(WorkSpace)/src/os/windows/vm @@ -177,6 +182,13 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/os_cpu/windows_$(Platform_arch)/vm VM_PATH=$(VM_PATH);$(WorkSpace)/src/cpu/$(Platform_arch)/vm VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/opto +!if exists($(ALTSRC)\share\vm\jfr) +VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/agent +VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/agent/isolated_deps/util +VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/jvm +VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr +!endif + VM_PATH={$(VM_PATH)} # Special case files not using precompiled header files. @@ -263,6 +275,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi {$(COMMONSRC)\share\vm\services}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< +{$(COMMONSRC)\share\vm\trace}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + {$(COMMONSRC)\share\vm\utilities}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< @@ -340,6 +355,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi {$(ALTSRC)\share\vm\services}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< +{$(ALTSRC)\share\vm\trace}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + {$(ALTSRC)\share\vm\utilities}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< @@ -371,6 +389,18 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi {..\generated\jvmtifiles}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< +{$(ALTSRC)\share\vm\jfr}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + +{$(ALTSRC)\share\vm\jfr\agent}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + +{$(ALTSRC)\share\vm\jfr\agent\isolated_deps\util}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + +{$(ALTSRC)\share\vm\jfr\jvm}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + default:: _build_pch_file.obj: diff --git a/hotspot/src/share/vm/classfile/symbolTable.cpp b/hotspot/src/share/vm/classfile/symbolTable.cpp index e3dd0862910..4dcdc533845 100644 --- a/hotspot/src/share/vm/classfile/symbolTable.cpp +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp @@ -204,6 +204,24 @@ Symbol* SymbolTable::lookup_only(const char* name, int len, return s; } +// Look up the address of the literal in the SymbolTable for this Symbol* +// Do not create any new symbols +// Do not increment the reference count to keep this alive +Symbol** SymbolTable::lookup_symbol_addr(Symbol* sym){ + unsigned int hash = hash_symbol((char*)sym->bytes(), sym->utf8_length()); + int index = the_table()->hash_to_index(hash); + + for (HashtableEntry* e = the_table()->bucket(index); e != NULL; e = e->next()) { + if (e->hash() == hash) { + Symbol* literal_sym = e->literal(); + if (sym == literal_sym) { + return e->literal_addr(); + } + } + } + return NULL; +} + // Suggestion: Push unicode-based lookup all the way into the hashing // and probing logic, so there is no need for convert_to_utf8 until // an actual new Symbol* is created. diff --git a/hotspot/src/share/vm/classfile/symbolTable.hpp b/hotspot/src/share/vm/classfile/symbolTable.hpp index ca0b07d7888..be74fab49d7 100644 --- a/hotspot/src/share/vm/classfile/symbolTable.hpp +++ b/hotspot/src/share/vm/classfile/symbolTable.hpp @@ -144,6 +144,9 @@ public: static void release(Symbol* sym); + // Look up the address of the literal in the SymbolTable for this Symbol* + static Symbol** lookup_symbol_addr(Symbol* sym); + // jchar (utf16) version of lookups static Symbol* lookup_unicode(const jchar* name, int len, TRAPS); static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 1591b795fde..88ccc91b790 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -2131,6 +2131,12 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash, } } + // Assign a classid if one has not already been assigned. The + // counter does not need to be atomically incremented since this + // is only done while holding the SystemDictionary_lock. + // All loaded classes get a unique ID. + TRACE_INIT_ID(k); + // Check for a placeholder. If there, remove it and make a // new system dictionary entry. placeholders()->find_and_remove(p_index, p_hash, name, class_loader, THREAD); diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 8541bd5d2b9..77a2638f35e 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -158,6 +158,9 @@ klassOop Klass::base_create_klass_oop(KlassHandle& klass, int size, kl->set_next_sibling(NULL); kl->set_alloc_count(0); kl->set_alloc_size(0); +#ifdef TRACE_SET_KLASS_TRACE_ID + TRACE_SET_KLASS_TRACE_ID(kl, 0); +#endif kl->set_prototype_header(markOopDesc::prototype()); kl->set_biased_lock_revocation_count(0); diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 407b1ef295a..131b14c6a0b 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -33,6 +33,7 @@ #include "oops/klassPS.hpp" #include "oops/oop.hpp" #include "runtime/orderAccess.hpp" +#include "trace/traceMacros.hpp" #include "utilities/accessFlags.hpp" #ifndef SERIALGC #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp" @@ -80,6 +81,7 @@ // [last_biased_lock_bulk_revocation_time] (64 bits) // [prototype_header] // [biased_lock_revocation_count] +// [trace_id] // Forward declarations. @@ -263,6 +265,9 @@ class Klass : public Klass_vtbl { markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type jint _biased_lock_revocation_count; +#ifdef TRACE_DEFINE_KLASS_TRACE_ID + TRACE_DEFINE_KLASS_TRACE_ID; +#endif public: // returns the enclosing klassOop @@ -683,6 +688,9 @@ class Klass : public Klass_vtbl { jlong last_biased_lock_bulk_revocation_time() { return _last_biased_lock_bulk_revocation_time; } void set_last_biased_lock_bulk_revocation_time(jlong cur_time) { _last_biased_lock_bulk_revocation_time = cur_time; } +#ifdef TRACE_DEFINE_KLASS_METHODS + TRACE_DEFINE_KLASS_METHODS; +#endif // garbage collection support virtual void follow_weak_klass_links( diff --git a/hotspot/src/share/vm/oops/methodKlass.cpp b/hotspot/src/share/vm/oops/methodKlass.cpp index f8d15108e75..b2d62358db8 100644 --- a/hotspot/src/share/vm/oops/methodKlass.cpp +++ b/hotspot/src/share/vm/oops/methodKlass.cpp @@ -83,6 +83,7 @@ methodOop methodKlass::allocate(constMethodHandle xconst, m->set_max_stack(0); m->set_max_locals(0); m->set_intrinsic_id(vmIntrinsics::_none); + m->set_jfr_towrite(false); m->set_method_data(NULL); m->set_interpreter_throwout_count(0); m->set_vtable_index(methodOopDesc::garbage_vtable_index); diff --git a/hotspot/src/share/vm/oops/methodOop.hpp b/hotspot/src/share/vm/oops/methodOop.hpp index e8e73c63105..cc9520a7f2a 100644 --- a/hotspot/src/share/vm/oops/methodOop.hpp +++ b/hotspot/src/share/vm/oops/methodOop.hpp @@ -77,7 +77,7 @@ // | method_size | max_stack | // | max_locals | size_of_parameters | // |------------------------------------------------------| -// | intrinsic_id, (unused) | throwout_count | +// |intrinsic_id| flags | throwout_count | // |------------------------------------------------------| // | num_breakpoints | (unused) | // |------------------------------------------------------| @@ -124,6 +124,8 @@ class methodOopDesc : public oopDesc { u2 _max_locals; // Number of local variables used by this method u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) + u1 _jfr_towrite : 1, // Flags + : 7; u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting u2 _number_of_breakpoints; // fullspeed debugging support InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations @@ -225,6 +227,7 @@ class methodOopDesc : public oopDesc { void clear_number_of_breakpoints() { _number_of_breakpoints = 0; } // index into instanceKlass methods() array + // note: also used by jfr u2 method_idnum() const { return constMethod()->method_idnum(); } void set_method_idnum(u2 idnum) { constMethod()->set_method_idnum(idnum); } @@ -650,6 +653,9 @@ class methodOopDesc : public oopDesc { void init_intrinsic_id(); // updates from _none if a match static vmSymbols::SID klass_id_for_intrinsics(klassOop holder); + bool jfr_towrite() { return _jfr_towrite; } + void set_jfr_towrite(bool towrite) { _jfr_towrite = towrite; } + // On-stack replacement support bool has_osr_nmethod(int level, bool match_level) { return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL; diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index fc35714bbd5..833f6f1810c 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -48,6 +48,7 @@ #include "oops/typeArrayOop.hpp" #include "prims/jni.h" #include "prims/jniCheck.hpp" +#include "prims/jniExport.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm.h" #include "prims/jvm_misc.hpp" @@ -66,6 +67,8 @@ #include "runtime/signature.hpp" #include "runtime/vm_operations.hpp" #include "services/runtimeService.hpp" +#include "trace/tracing.hpp" +#include "trace/traceEventTypes.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" @@ -5139,6 +5142,11 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, v if (JvmtiExport::should_post_thread_life()) { JvmtiExport::post_thread_start(thread); } + + EVENT_BEGIN(TraceEventThreadStart, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj()))); + // Check if we should compile all classes on bootclasspath NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();) // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving. @@ -5337,6 +5345,10 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae JvmtiExport::post_thread_start(thread); } + EVENT_BEGIN(TraceEventThreadStart, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj()))); + *(JNIEnv**)penv = thread->jni_environment(); // Now leaving the VM, so change thread_state. This is normally automatically taken care @@ -5464,8 +5476,7 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) { return ret; } - if (JvmtiExport::is_jvmti_version(version)) { - ret = JvmtiExport::get_jvmti_interface(vm, penv, version); + if (JniExportedInterface::GetExportedInterface(vm, penv, version, &ret)) { return ret; } diff --git a/hotspot/src/share/vm/prims/jniExport.hpp b/hotspot/src/share/vm/prims/jniExport.hpp new file mode 100644 index 00000000000..841b3dc5ccc --- /dev/null +++ b/hotspot/src/share/vm/prims/jniExport.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_PRIMS_JNI_EXPORT_HPP +#define SHARE_VM_PRIMS_JNI_EXPORT_HPP + +#include "prims/jni.h" +#include "prims/jvmtiExport.hpp" + +class JniExportedInterface { + public: + static bool GetExportedInterface(JavaVM* vm, void** penv, jint version, jint* iface) { + if (JvmtiExport::is_jvmti_version(version)) { + *iface = JvmtiExport::get_jvmti_interface(vm, penv, version); + return true; + } + return false; + } +}; + +#endif // SHARE_VM_PRIMS_JNI_EXPORT_HPP diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index c04bd23caa2..f256e515e9c 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -57,6 +57,8 @@ #include "runtime/task.hpp" #include "runtime/timer.hpp" #include "runtime/vm_operations.hpp" +#include "trace/tracing.hpp" +#include "trace/traceEventTypes.hpp" #include "utilities/dtrace.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/histogram.hpp" @@ -502,6 +504,11 @@ void before_exit(JavaThread * thread) { if (JvmtiExport::should_post_thread_life()) { JvmtiExport::post_thread_end(thread); } + + EVENT_BEGIN(TraceEventThreadEnd, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj()))); + // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution JvmtiExport::post_vm_death(); diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp index 7653b5bef84..0a2d8795bfd 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp @@ -132,7 +132,13 @@ Mutex* HotCardCache_lock = NULL; Monitor* GCTaskManager_lock = NULL; Mutex* Management_lock = NULL; -Monitor* Service_lock = NULL; +Monitor* Service_lock = NULL; +Mutex* Stacktrace_lock = NULL; + +Monitor* JfrQuery_lock = NULL; +Monitor* JfrMsg_lock = NULL; +Mutex* JfrBuffer_lock = NULL; +Mutex* JfrStream_lock = NULL; #define MAX_NUM_MUTEX 128 static Monitor * _mutex_array[MAX_NUM_MUTEX]; @@ -207,6 +213,7 @@ void mutex_init() { def(Patching_lock , Mutex , special, true ); // used for safepointing and code patching. def(ObjAllocPost_lock , Monitor, special, false); def(Service_lock , Monitor, special, true ); // used for service thread operations + def(Stacktrace_lock , Mutex, special, true ); // used for JFR stacktrace database def(JmethodIdCreation_lock , Mutex , leaf, true ); // used for creating jmethodIDs. def(SystemDictionary_lock , Monitor, leaf, true ); // lookups done by VM thread @@ -271,6 +278,11 @@ void mutex_init() { def(Debug3_lock , Mutex , nonleaf+4, true ); def(ProfileVM_lock , Monitor, nonleaf+4, false); // used for profiling of the VMThread def(CompileThread_lock , Monitor, nonleaf+5, false ); + + def(JfrQuery_lock , Monitor, nonleaf, true); // JFR locks, keep these in consecutive order + def(JfrMsg_lock , Monitor, nonleaf+2, true); + def(JfrBuffer_lock , Mutex, nonleaf+3, true); + def(JfrStream_lock , Mutex, nonleaf+4, true); } GCMutexLocker::GCMutexLocker(Monitor * mutex) { diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp index 37a3d3132b4..2a6bf369d79 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp @@ -135,6 +135,12 @@ extern Mutex* HotCardCache_lock; // protects the hot card cache extern Mutex* Management_lock; // a lock used to serialize JVM management extern Monitor* Service_lock; // a lock used for service thread operation +extern Mutex* Stacktrace_lock; // used to guard access to the stacktrace table + +extern Monitor* JfrQuery_lock; // protects JFR use +extern Monitor* JfrMsg_lock; // protects JFR messaging +extern Mutex* JfrBuffer_lock; // protects JFR buffer operations +extern Mutex* JfrStream_lock; // protects JFR stream access // A MutexLocker provides mutual exclusion with respect to a given mutex // for the scope which contains the locker. The lock is an OS lock, not diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 773948971cd..33495d66d43 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1101,6 +1101,7 @@ bool os::set_boot_path(char fileSep, char pathSep) { "%/lib/jsse.jar:" "%/lib/jce.jar:" "%/lib/charsets.jar:" + "%/lib/jfr.jar:" #ifdef __APPLE__ "%/lib/JObjC.jar:" #endif diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index da291036e8a..18c04a905d5 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -73,6 +73,7 @@ #include "services/attachListener.hpp" #include "services/management.hpp" #include "services/threadService.hpp" +#include "trace/traceEventTypes.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" @@ -232,6 +233,7 @@ Thread::Thread() { CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;) _jvmti_env_iteration_count = 0; set_allocated_bytes(0); + set_trace_buffer(NULL); _vm_operation_started_count = 0; _vm_operation_completed_count = 0; _current_pending_monitor = NULL; @@ -1512,6 +1514,10 @@ void JavaThread::run() { JvmtiExport::post_thread_start(this); } + EVENT_BEGIN(TraceEventThreadStart, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(this->threadObj()))); + // We call another function to do the rest so we are sure that the stack addresses used // from there will be lower than the stack base just computed thread_main_inner(); @@ -1641,6 +1647,15 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { } } + // Called before the java thread exit since we want to read info + // from java_lang_Thread object + EVENT_BEGIN(TraceEventThreadEnd, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(this->threadObj()))); + + // Call after last event on thread + EVENT_THREAD_EXIT(this); + // Call Thread.exit(). We try 3 times in case we got another Thread.stop during // the execution of the method. If that is not enough, then we don't really care. Thread.stop // is deprecated anyhow. @@ -3186,6 +3201,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { return status; } + // Must be run after init_ft which initializes ft_enabled + if (TRACE_INITIALIZE() != JNI_OK) { + vm_exit_during_initialization("Failed to initialize tracing backend"); + } + // Should be done after the heap is fully created main_thread->cache_global_variables(); @@ -3423,6 +3443,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { create_vm_init_libraries(); } + if (!TRACE_START()) { + vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); + } + // Notify JVMTI agents that VM initialization is complete - nop if no agents. JvmtiExport::post_vm_initialized(); diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index da13f12258b..37bbf29372a 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -41,6 +41,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/threadLocalStorage.hpp" #include "runtime/unhandledOops.hpp" +#include "trace/tracing.hpp" #include "utilities/exceptions.hpp" #include "utilities/top.hpp" #ifndef SERIALGC @@ -246,6 +247,8 @@ class Thread: public ThreadShadow { jlong _allocated_bytes; // Cumulative number of bytes allocated on // the Java heap + TRACE_BUFFER _trace_buffer; // Thread-local buffer for tracing + int _vm_operation_started_count; // VM_Operation support int _vm_operation_completed_count; // VM_Operation support @@ -414,6 +417,9 @@ class Thread: public ThreadShadow { return allocated_bytes; } + TRACE_BUFFER trace_buffer() { return _trace_buffer; } + void set_trace_buffer(TRACE_BUFFER buf) { _trace_buffer = buf; } + // VM operation support int vm_operation_ticket() { return ++_vm_operation_started_count; } int vm_operation_completed_count() { return _vm_operation_completed_count; } diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp index 77f262f6eda..081c428a62b 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.hpp +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp @@ -93,6 +93,7 @@ template(HeapWalkOperation) \ template(HeapIterateOperation) \ template(ReportJavaOutOfMemory) \ + template(JFRCheckpoint) \ template(Exit) \ class VM_Operation: public CHeapObj { diff --git a/hotspot/src/share/vm/trace/traceEventTypes.hpp b/hotspot/src/share/vm/trace/traceEventTypes.hpp new file mode 100644 index 00000000000..e7448aaebdf --- /dev/null +++ b/hotspot/src/share/vm/trace/traceEventTypes.hpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_TRACE_TRACE_EVENT_TYPES_HPP +#define SHARE_VM_TRACE_TRACE_EVENT_TYPES_HPP + +/* Empty, just a placeholder for tracing events */ + +#endif diff --git a/hotspot/src/share/vm/trace/traceMacros.hpp b/hotspot/src/share/vm/trace/traceMacros.hpp new file mode 100644 index 00000000000..e9259352920 --- /dev/null +++ b/hotspot/src/share/vm/trace/traceMacros.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_TRACE_TRACE_MACRO_HPP +#define SHARE_VM_TRACE_TRACE_MACRO_HPP + +#define EVENT_BEGIN(type, name) +#define EVENT_SET(name, field, value) +#define EVENT_COMMIT(name, ...) +#define EVENT_STARTED(name, time) +#define EVENT_ENDED(name, time) +#define EVENT_THREAD_EXIT(thread) + +#define TRACE_ENABLED 0 + +#define TRACE_INIT_ID(k) +#define TRACE_BUFFER void* + +#define TRACE_START() true +#define TRACE_INITIALIZE() 0 + +#endif diff --git a/hotspot/src/share/vm/trace/tracing.hpp b/hotspot/src/share/vm/trace/tracing.hpp new file mode 100644 index 00000000000..dcf0e5eb893 --- /dev/null +++ b/hotspot/src/share/vm/trace/tracing.hpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_TRACE_TRACING_HPP +#define SHARE_VM_TRACE_TRACING_HPP + +#include "trace/traceMacros.hpp" + +#endif diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 1425912ce37..89201f62f92 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -298,6 +298,11 @@ const jushort max_jushort = (jushort)-1; // 0xFFFF largest jushort const juint max_juint = (juint)-1; // 0xFFFFFFFF largest juint const julong max_julong = (julong)-1; // 0xFF....FF largest julong +typedef jbyte s1; +typedef jshort s2; +typedef jint s4; +typedef jlong s8; + //---------------------------------------------------------------------------------------------------- // JVM spec restrictions From dac656c9554789c1edce99b003de79a4faf29e8d Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Fri, 13 Jan 2012 13:27:48 -0800 Subject: [PATCH 19/96] 7121547: G1: High number mispredicted branches while iterating over the marking bitmap There is a high number of mispredicted branches associated with calling BitMap::iteratate() from within CMBitMapRO::iterate(). Implement a version of CMBitMapRO::iterate() directly using inline-able routines. Reviewed-by: tonyp, iveresov --- .../gc_implementation/g1/concurrentMark.cpp | 11 ------- .../gc_implementation/g1/concurrentMark.hpp | 4 +-- .../g1/concurrentMark.inline.hpp | 29 +++++++++++++++++++ .../src/share/vm/utilities/bitMap.inline.hpp | 28 ++++++++++++++++-- 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 4712d803542..5c3d45931dc 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -104,17 +104,6 @@ int CMBitMapRO::heapWordDiffToOffsetDiff(size_t diff) const { return (int) (diff >> _shifter); } -bool CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { - HeapWord* left = MAX2(_bmStartWord, mr.start()); - HeapWord* right = MIN2(_bmStartWord + _bmWordSize, mr.end()); - if (right > left) { - // Right-open interval [leftOffset, rightOffset). - return _bm.iterate(cl, heapWordToOffset(left), heapWordToOffset(right)); - } else { - return true; - } -} - void CMBitMapRO::mostly_disjoint_range_union(BitMap* from_bitmap, size_t from_start_index, HeapWord* to_start_word, diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 1a407848499..53e2a21db59 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -84,8 +84,8 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC { } // iteration - bool iterate(BitMapClosure* cl) { return _bm.iterate(cl); } - bool iterate(BitMapClosure* cl, MemRegion mr); + inline bool iterate(BitMapClosure* cl, MemRegion mr); + inline bool iterate(BitMapClosure* cl); // Return the address corresponding to the next marked bit at or after // "addr", and before "limit", if "limit" is non-NULL. If there is no diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp index d72db9ea78f..fde69c4ab32 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp @@ -28,6 +28,35 @@ #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +inline bool CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { + HeapWord* start_addr = MAX2(startWord(), mr.start()); + HeapWord* end_addr = MIN2(endWord(), mr.end()); + + if (end_addr > start_addr) { + // Right-open interval [start-offset, end-offset). + BitMap::idx_t start_offset = heapWordToOffset(start_addr); + BitMap::idx_t end_offset = heapWordToOffset(end_addr); + + start_offset = _bm.get_next_one_offset(start_offset, end_offset); + while (start_offset < end_offset) { + HeapWord* obj_addr = offsetToHeapWord(start_offset); + oop obj = (oop) obj_addr; + if (!cl->do_bit(start_offset)) { + return false; + } + HeapWord* next_addr = MIN2(obj_addr + obj->size(), end_addr); + BitMap::idx_t next_offset = heapWordToOffset(next_addr); + start_offset = _bm.get_next_one_offset(next_offset, end_offset); + } + } + return true; +} + +inline bool CMBitMapRO::iterate(BitMapClosure* cl) { + MemRegion mr(startWord(), sizeInWords()); + return iterate(cl, mr); +} + inline void CMTask::push(oop obj) { HeapWord* objAddr = (HeapWord*) obj; assert(_g1h->is_in_g1_reserved(objAddr), "invariant"); diff --git a/hotspot/src/share/vm/utilities/bitMap.inline.hpp b/hotspot/src/share/vm/utilities/bitMap.inline.hpp index a25fa0ac891..7bb244795fc 100644 --- a/hotspot/src/share/vm/utilities/bitMap.inline.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -178,8 +178,30 @@ BitMap::get_next_one_offset_inline(idx_t l_offset, idx_t r_offset) const { for (; !(res & 1); res_offset++) { res = res >> 1; } - assert(res_offset >= l_offset && - res_offset < r_offset, "just checking"); + +#ifdef ASSERT + // In the following assert, if r_offset is not bitamp word aligned, + // checking that res_offset is strictly less than r_offset is too + // strong and will trip the assert. + // + // Consider the case where l_offset is bit 15 and r_offset is bit 17 + // of the same map word, and where bits [15:16:17:18] == [00:00:00:01]. + // All the bits in the range [l_offset:r_offset) are 0. + // The loop that calculates res_offset, above, would yield the offset + // of bit 18 because it's in the same map word as l_offset and there + // is a set bit in that map word above l_offset (i.e. res != NoBits). + // + // In this case, however, we can assert is that res_offset is strictly + // less than size() since we know that there is at least one set bit + // at an offset above, but in the same map word as, r_offset. + // Otherwise, if r_offset is word aligned then it will not be in the + // same map word as l_offset (unless it equals l_offset). So either + // there won't be a set bit between l_offset and the end of it's map + // word (i.e. res == NoBits), or res_offset will be less than r_offset. + + idx_t limit = is_word_aligned(r_offset) ? r_offset : size(); + assert(res_offset >= l_offset && res_offset < limit, "just checking"); +#endif // ASSERT return MIN2(res_offset, r_offset); } // skip over all word length 0-bit runs From af0211c20064cf35441b15ea7d3c89066e180dde Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Mon, 16 Jan 2012 11:21:21 +0100 Subject: [PATCH 20/96] 7130334: G1: Change comments and error messages that refer to CMS in g1/concurrentMark.cpp/hpp Removed references to CMS in the concurrentMark.cpp/hpp files. Reviewed-by: tonyp, jmasa, johnc --- .../gc_implementation/g1/concurrentMark.cpp | 23 ++++--------------- .../gc_implementation/g1/concurrentMark.hpp | 2 +- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 5c3d45931dc..63b8c2976d3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -42,8 +42,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" -// -// CMS Bit Map Wrapper +// Concurrent marking bit map wrapper CMBitMapRO::CMBitMapRO(ReservedSpace rs, int shifter) : _bm((uintptr_t*)NULL,0), @@ -53,13 +52,13 @@ CMBitMapRO::CMBitMapRO(ReservedSpace rs, int shifter) : ReservedSpace brs(ReservedSpace::allocation_align_size_up( (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1)); - guarantee(brs.is_reserved(), "couldn't allocate CMS bit map"); + guarantee(brs.is_reserved(), "couldn't allocate concurrent marking bit map"); // For now we'll just commit all of the bit map up fromt. // Later on we'll try to be more parsimonious with swap. guarantee(_virtual_space.initialize(brs, brs.size()), - "couldn't reseve backing store for CMS bit map"); + "couldn't reseve backing store for concurrent marking bit map"); assert(_virtual_space.committed_size() == brs.size(), - "didn't reserve backing store for all of CMS bit map?"); + "didn't reserve backing store for all of concurrent marking bit map?"); _bm.set_map((uintptr_t*)_virtual_space.low()); assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >= _bmWordSize, "inconsistency in bit map sizing"); @@ -420,8 +419,6 @@ bool CMMarkStack::drain(OopClosureClass* cl, CMBitMap* bm, bool yield_after) { assert(newOop->is_oop(), "Expected an oop"); assert(bm == NULL || bm->isMarked((HeapWord*)newOop), "only grey objects on this stack"); - // iterate over the oops in this oop, marking and pushing - // the ones in CMS generation. newOop->oop_iterate(cl); if (yield_after && _cm->do_yield_check()) { res = false; @@ -739,11 +736,6 @@ ConcurrentMark::~ConcurrentMark() { ShouldNotReachHere(); } -// This closure is used to mark refs into the g1 generation -// from external roots in the CMS bit map. -// Called at the first checkpoint. -// - void ConcurrentMark::clearNextBitmap() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1p = g1h->g1_policy(); @@ -3401,13 +3393,6 @@ void ConcurrentMark::print_worker_threads_on(outputStream* st) const { _parallel_workers->print_worker_threads_on(st); } -// Closures -// XXX: there seems to be a lot of code duplication here; -// should refactor and consolidate the shared code. - -// This closure is used to mark refs into the CMS generation in -// the CMS bit map. Called at the first checkpoint. - // We take a break if someone is trying to stop the world. bool ConcurrentMark::do_yield_check(uint worker_id) { if (should_yield()) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 53e2a21db59..0b8b633be34 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -386,7 +386,7 @@ protected: FreeRegionList _cleanup_list; - // CMS marking support structures + // Concurrent marking support structures CMBitMap _markBitMap1; CMBitMap _markBitMap2; CMBitMapRO* _prevMarkBitMap; // completed mark bitmap From c11ba93098bfbf8223cdbda8e643cb11f550c924 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Mon, 16 Jan 2012 22:10:05 +0100 Subject: [PATCH 21/96] 6976060: G1: humongous object allocations should initiate marking cycles when necessary Reviewed-by: tonyp, johnc --- .../gc_implementation/g1/g1CollectedHeap.cpp | 34 +++++--- .../gc_implementation/g1/g1CollectedHeap.hpp | 5 ++ .../g1/g1CollectorPolicy.cpp | 83 ++++++++++--------- .../g1/g1CollectorPolicy.hpp | 3 +- .../gc_implementation/g1/vm_operations_g1.cpp | 7 +- hotspot/src/share/vm/gc_interface/gcCause.cpp | 5 +- hotspot/src/share/vm/gc_interface/gcCause.hpp | 3 +- 7 files changed, 86 insertions(+), 54 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index f1645f32b0b..8a2a041540a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1045,19 +1045,26 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size, // regions, we'll first try to do the allocation without doing a // collection hoping that there's enough space in the heap. result = humongous_obj_allocate(word_size); - if (result != NULL) { - return result; - } - if (GC_locker::is_active_and_needs_gc()) { - should_try_gc = false; - } else { - // Read the GC count while still holding the Heap_lock. - gc_count_before = SharedHeap::heap()->total_collections(); - should_try_gc = true; + if (result == NULL) { + if (GC_locker::is_active_and_needs_gc()) { + should_try_gc = false; + } else { + // Read the GC count while still holding the Heap_lock. + gc_count_before = SharedHeap::heap()->total_collections(); + should_try_gc = true; + } } } + if (result != NULL) { + if (g1_policy()->need_to_start_conc_mark("concurrent humongous allocation")) { + // We need to release the Heap_lock before we try to call collect + collect(GCCause::_g1_humongous_allocation); + } + return result; + } + if (should_try_gc) { // If we failed to allocate the humongous object, we should try to // do a collection pause (if we're allowed) in case it reclaims @@ -1111,7 +1118,11 @@ HeapWord* G1CollectedHeap::attempt_allocation_at_safepoint(size_t word_size, return _mutator_alloc_region.attempt_allocation_locked(word_size, false /* bot_updates */); } else { - return humongous_obj_allocate(word_size); + HeapWord* result = humongous_obj_allocate(word_size); + if (result != NULL && g1_policy()->need_to_start_conc_mark("STW humongous allocation")) { + g1_policy()->set_initiate_conc_mark_if_possible(); + } + return result; } ShouldNotReachHere(); @@ -2295,7 +2306,8 @@ size_t G1CollectedHeap::unsafe_max_alloc() { bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { return ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || - (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)); + (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent) || + cause == GCCause::_g1_humongous_allocation); } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 30b7fedd417..3971535ff2c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -355,6 +355,7 @@ private: // explicitly started if: // (a) cause == _gc_locker and +GCLockerInvokesConcurrent, or // (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent. + // (c) cause == _g1_humongous_allocation bool should_do_concurrent_full_gc(GCCause::Cause cause); // Keeps track of how many "full collections" (i.e., Full GCs or @@ -1172,6 +1173,10 @@ public: _old_set.remove(hr); } + size_t non_young_capacity_bytes() { + return _old_set.total_capacity_bytes() + _humongous_set.total_capacity_bytes(); + } + void set_free_regions_coming(); void reset_free_regions_coming(); bool free_regions_coming() { return _free_regions_coming; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index f32db16d402..fdb0a2aa11a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -213,8 +213,6 @@ G1CollectorPolicy::G1CollectorPolicy() : _survivor_bytes_before_gc(0), _capacity_before_gc(0), - _prev_collection_pause_used_at_end_bytes(0), - _eden_cset_region_length(0), _survivor_cset_region_length(0), _old_cset_region_length(0), @@ -1140,6 +1138,45 @@ double G1CollectorPolicy::max_sum(double* data1, double* data2) { return ret; } +bool G1CollectorPolicy::need_to_start_conc_mark(const char* source) { + if (_g1->mark_in_progress()) { + return false; + } + + size_t marking_initiating_used_threshold = + (_g1->capacity() / 100) * InitiatingHeapOccupancyPercent; + size_t cur_used_bytes = _g1->non_young_capacity_bytes(); + + if (cur_used_bytes > marking_initiating_used_threshold) { + if (gcs_are_young()) { + ergo_verbose4(ErgoConcCycles, + "request concurrent cycle initiation", + ergo_format_reason("occupancy higher than threshold") + ergo_format_byte("occupancy") + ergo_format_byte_perc("threshold") + ergo_format_str("source"), + cur_used_bytes, + marking_initiating_used_threshold, + (double) InitiatingHeapOccupancyPercent, + source); + return true; + } else { + ergo_verbose4(ErgoConcCycles, + "do not request concurrent cycle initiation", + ergo_format_reason("still doing mixed collections") + ergo_format_byte("occupancy") + ergo_format_byte_perc("threshold") + ergo_format_str("source"), + cur_used_bytes, + marking_initiating_used_threshold, + (double) InitiatingHeapOccupancyPercent, + source); + } + } + + return false; +} + // Anything below that is considered to be zero #define MIN_TIMER_GRANULARITY 0.0000001 @@ -1166,44 +1203,16 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { #endif // PRODUCT last_pause_included_initial_mark = during_initial_mark_pause(); - if (last_pause_included_initial_mark) + if (last_pause_included_initial_mark) { record_concurrent_mark_init_end(0.0); - - size_t marking_initiating_used_threshold = - (_g1->capacity() / 100) * InitiatingHeapOccupancyPercent; - - if (!_g1->mark_in_progress() && !_last_young_gc) { - assert(!last_pause_included_initial_mark, "invariant"); - if (cur_used_bytes > marking_initiating_used_threshold) { - if (cur_used_bytes > _prev_collection_pause_used_at_end_bytes) { - assert(!during_initial_mark_pause(), "we should not see this here"); - - ergo_verbose3(ErgoConcCycles, - "request concurrent cycle initiation", - ergo_format_reason("occupancy higher than threshold") - ergo_format_byte("occupancy") - ergo_format_byte_perc("threshold"), - cur_used_bytes, - marking_initiating_used_threshold, - (double) InitiatingHeapOccupancyPercent); - - // Note: this might have already been set, if during the last - // pause we decided to start a cycle but at the beginning of - // this pause we decided to postpone it. That's OK. - set_initiate_conc_mark_if_possible(); - } else { - ergo_verbose2(ErgoConcCycles, - "do not request concurrent cycle initiation", - ergo_format_reason("occupancy lower than previous occupancy") - ergo_format_byte("occupancy") - ergo_format_byte("previous occupancy"), - cur_used_bytes, - _prev_collection_pause_used_at_end_bytes); - } - } } - _prev_collection_pause_used_at_end_bytes = cur_used_bytes; + if (!_last_young_gc && need_to_start_conc_mark("end of GC")) { + // Note: this might have already been set, if during the last + // pause we decided to start a cycle but at the beginning of + // this pause we decided to postpone it. That's OK. + set_initiate_conc_mark_if_possible(); + } _mmu_tracker->add_pause(end_time_sec - elapsed_ms/1000.0, end_time_sec, false); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index 90660c00162..ee2f1852514 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -177,7 +177,6 @@ private: double _cur_collection_start_sec; size_t _cur_collection_pause_used_at_start_bytes; size_t _cur_collection_pause_used_regions_at_start; - size_t _prev_collection_pause_used_at_end_bytes; double _cur_collection_par_time_ms; double _cur_satb_drain_time_ms; double _cur_clear_ct_time_ms; @@ -800,6 +799,8 @@ public: GenRemSet::Name rem_set_name() { return GenRemSet::CardTable; } + bool need_to_start_conc_mark(const char* source); + // Update the heuristic info to record a collection pause of the given // start time, where the given number of bytes were used at the start. // This may involve changing the desired size of a collection set. diff --git a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp index befacd69e5e..594faf6b1c4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,8 +74,9 @@ void VM_G1IncCollectionPause::doit() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); assert(!_should_initiate_conc_mark || ((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || - (_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)), - "only a GC locker or a System.gc() induced GC should start a cycle"); + (_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent) || + _gc_cause == GCCause::_g1_humongous_allocation), + "only a GC locker, a System.gc() or a hum allocation induced GC should start a cycle"); if (_word_size > 0) { // An allocation has been requested. So, try to do that first. diff --git a/hotspot/src/share/vm/gc_interface/gcCause.cpp b/hotspot/src/share/vm/gc_interface/gcCause.cpp index c4abd12a62a..5797ef85d73 100644 --- a/hotspot/src/share/vm/gc_interface/gcCause.cpp +++ b/hotspot/src/share/vm/gc_interface/gcCause.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,6 +84,9 @@ const char* GCCause::to_string(GCCause::Cause cause) { case _g1_inc_collection_pause: return "G1 Evacuation Pause"; + case _g1_humongous_allocation: + return "G1 Humongous Allocation"; + case _last_ditch_collection: return "Last ditch collection"; diff --git a/hotspot/src/share/vm/gc_interface/gcCause.hpp b/hotspot/src/share/vm/gc_interface/gcCause.hpp index fc49e306bbc..ae14115d7e2 100644 --- a/hotspot/src/share/vm/gc_interface/gcCause.hpp +++ b/hotspot/src/share/vm/gc_interface/gcCause.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,6 +66,7 @@ class GCCause : public AllStatic { _adaptive_size_policy, _g1_inc_collection_pause, + _g1_humongous_allocation, _last_ditch_collection, _last_gc_cause From c9eb103b7f16730832420f96abcc8292d26bf739 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 18 Jan 2012 10:30:12 -0500 Subject: [PATCH 22/96] 7097586: G1: improve the per-space output when using jmap -heap Extend the jmap -heap output for G1 to include some more G1-specific information. Reviewed-by: brutisso, johnc, poonam --- .../gc_implementation/g1/G1CollectedHeap.java | 26 +++++- .../g1/G1MonitoringSupport.java | 10 ++- .../g1/HeapRegionSetBase.java | 81 +++++++++++++++++++ .../sun/jvm/hotspot/tools/HeapSummary.java | 26 ++++-- .../gc_implementation/g1/concurrentMark.cpp | 4 + .../vm/gc_implementation/g1/heapRegionSet.hpp | 3 +- .../vm/gc_implementation/g1/vmStructs_g1.hpp | 9 ++- 7 files changed, 145 insertions(+), 14 deletions(-) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java index 502d8e4ad14..b75669ed026 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,8 +49,12 @@ public class G1CollectedHeap extends SharedHeap { static private long g1CommittedFieldOffset; // size_t _summary_bytes_used; static private CIntegerField summaryBytesUsedField; - // G1MonitoringSupport* _g1mm + // G1MonitoringSupport* _g1mm; static private AddressField g1mmField; + // MasterOldRegionSet _old_set; + static private long oldSetFieldOffset; + // MasterHumongousRegionSet _humongous_set; + static private long humongousSetFieldOffset; static { VM.registerVMInitializedObserver(new Observer() { @@ -67,12 +71,14 @@ public class G1CollectedHeap extends SharedHeap { g1CommittedFieldOffset = type.getField("_g1_committed").getOffset(); summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used"); g1mmField = type.getAddressField("_g1mm"); + oldSetFieldOffset = type.getField("_old_set").getOffset(); + humongousSetFieldOffset = type.getField("_humongous_set").getOffset(); } public long capacity() { Address g1CommittedAddr = addr.addOffsetTo(g1CommittedFieldOffset); - MemRegion g1_committed = new MemRegion(g1CommittedAddr); - return g1_committed.byteSize(); + MemRegion g1Committed = new MemRegion(g1CommittedAddr); + return g1Committed.byteSize(); } public long used() { @@ -94,6 +100,18 @@ public class G1CollectedHeap extends SharedHeap { return (G1MonitoringSupport) VMObjectFactory.newObject(G1MonitoringSupport.class, g1mmAddr); } + public HeapRegionSetBase oldSet() { + Address oldSetAddr = addr.addOffsetTo(oldSetFieldOffset); + return (HeapRegionSetBase) VMObjectFactory.newObject(HeapRegionSetBase.class, + oldSetAddr); + } + + public HeapRegionSetBase humongousSet() { + Address humongousSetAddr = addr.addOffsetTo(humongousSetFieldOffset); + return (HeapRegionSetBase) VMObjectFactory.newObject(HeapRegionSetBase.class, + humongousSetAddr); + } + private Iterator heapRegionIterator() { return hrs().heapRegionIterator(); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1MonitoringSupport.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1MonitoringSupport.java index 7b03aed9c9c..a9ced52b635 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1MonitoringSupport.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1MonitoringSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,6 +77,10 @@ public class G1MonitoringSupport extends VMObject { return edenUsedField.getValue(addr); } + public long edenRegionNum() { + return edenUsed() / HeapRegion.grainBytes(); + } + public long survivorCommitted() { return survivorCommittedField.getValue(addr); } @@ -85,6 +89,10 @@ public class G1MonitoringSupport extends VMObject { return survivorUsedField.getValue(addr); } + public long survivorRegionNum() { + return survivorUsed() / HeapRegion.grainBytes(); + } + public long oldCommitted() { return oldCommittedField.getValue(addr); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java new file mode 100644 index 00000000000..2fbdce7f06c --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.gc_implementation.g1; + +import java.util.Iterator; +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObject; +import sun.jvm.hotspot.runtime.VMObjectFactory; +import sun.jvm.hotspot.types.AddressField; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +// Mirror class for HeapRegionSetBase. Represents a group of regions. + +public class HeapRegionSetBase extends VMObject { + // size_t _length; + static private CIntegerField lengthField; + // size_t _region_num; + static private CIntegerField regionNumField; + // size_t _total_used_bytes; + static private CIntegerField totalUsedBytesField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + static private synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("HeapRegionSetBase"); + + lengthField = type.getCIntegerField("_length"); + regionNumField = type.getCIntegerField("_region_num"); + totalUsedBytesField = type.getCIntegerField("_total_used_bytes"); + } + + public long length() { + return lengthField.getValue(addr); + } + + public long regionNum() { + return regionNumField.getValue(addr); + } + + public long totalUsedBytes() { + return totalUsedBytesField.getValue(addr); + } + + public HeapRegionSetBase(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java index bcfc01543d7..d0ff86873b8 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,6 +67,7 @@ public class HeapSummary extends Tool { printValue("SurvivorRatio = ", getFlagValue("SurvivorRatio", flagMap)); printValMB("PermSize = ", getFlagValue("PermSize", flagMap)); printValMB("MaxPermSize = ", getFlagValue("MaxPermSize", flagMap)); + printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes()); System.out.println(); System.out.println("Heap Usage:"); @@ -100,11 +101,20 @@ public class HeapSummary extends Tool { } else if (sharedHeap instanceof G1CollectedHeap) { G1CollectedHeap g1h = (G1CollectedHeap) sharedHeap; G1MonitoringSupport g1mm = g1h.g1mm(); - System.out.println("G1 Young Generation"); - printG1Space("Eden Space:", g1mm.edenUsed(), g1mm.edenCommitted()); - printG1Space("From Space:", g1mm.survivorUsed(), g1mm.survivorCommitted()); - printG1Space("To Space:", 0, 0); - printG1Space("G1 Old Generation", g1mm.oldUsed(), g1mm.oldCommitted()); + long edenRegionNum = g1mm.edenRegionNum(); + long survivorRegionNum = g1mm.survivorRegionNum(); + HeapRegionSetBase oldSet = g1h.oldSet(); + HeapRegionSetBase humongousSet = g1h.humongousSet(); + long oldRegionNum = oldSet.regionNum() + humongousSet.regionNum(); + printG1Space("G1 Heap:", g1h.n_regions(), + g1h.used(), g1h.capacity()); + System.out.println("G1 Young Generation:"); + printG1Space("Eden Space:", edenRegionNum, + g1mm.edenUsed(), g1mm.edenCommitted()); + printG1Space("Survivor Space:", survivorRegionNum, + g1mm.survivorUsed(), g1mm.survivorCommitted()); + printG1Space("G1 Old Generation:", oldRegionNum, + g1mm.oldUsed(), g1mm.oldCommitted()); } else { throw new RuntimeException("unknown SharedHeap type : " + heap.getClass()); } @@ -216,9 +226,11 @@ public class HeapSummary extends Tool { System.out.println(alignment + (double)space.used() * 100.0 / space.capacity() + "% used"); } - private void printG1Space(String spaceName, long used, long capacity) { + private void printG1Space(String spaceName, long regionNum, + long used, long capacity) { long free = capacity - used; System.out.println(spaceName); + printValue("regions = ", regionNum); printValMB("capacity = ", capacity); printValMB("used = ", used); printValMB("free = ", free); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 63b8c2976d3..1d0415a3176 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -1886,6 +1886,10 @@ void ConcurrentMark::cleanup() { // races with it goes around and waits for completeCleanup to finish. g1h->increment_total_collections(); + // We reclaimed old regions so we should calculate the sizes to make + // sure we update the old gen/space data. + g1h->g1mm()->update_sizes(); + if (VerifyDuringGC) { HandleMark hm; // handle scope gclog_or_tty->print(" VerifyDuringGC:(after)"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp index 9e862b4b448..8231c772d3b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,6 +59,7 @@ class HRSPhaseSetter; class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC { friend class hrs_ext_msg; friend class HRSPhaseSetter; + friend class VMStructs; protected: static size_t calculate_region_num(HeapRegion* hr); diff --git a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp index 63c0e94317a..a646b48b0c5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,8 @@ nonstatic_field(G1CollectedHeap, _g1_committed, MemRegion) \ nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t) \ nonstatic_field(G1CollectedHeap, _g1mm, G1MonitoringSupport*) \ + nonstatic_field(G1CollectedHeap, _old_set, HeapRegionSetBase) \ + nonstatic_field(G1CollectedHeap, _humongous_set, HeapRegionSetBase) \ \ nonstatic_field(G1MonitoringSupport, _eden_committed, size_t) \ nonstatic_field(G1MonitoringSupport, _eden_used, size_t) \ @@ -47,6 +49,10 @@ nonstatic_field(G1MonitoringSupport, _survivor_used, size_t) \ nonstatic_field(G1MonitoringSupport, _old_committed, size_t) \ nonstatic_field(G1MonitoringSupport, _old_used, size_t) \ + \ + nonstatic_field(HeapRegionSetBase, _length, size_t) \ + nonstatic_field(HeapRegionSetBase, _region_num, size_t) \ + nonstatic_field(HeapRegionSetBase, _total_used_bytes, size_t) \ #define VM_TYPES_G1(declare_type, declare_toplevel_type) \ @@ -55,6 +61,7 @@ \ declare_type(HeapRegion, ContiguousSpace) \ declare_toplevel_type(HeapRegionSeq) \ + declare_toplevel_type(HeapRegionSetBase) \ declare_toplevel_type(G1MonitoringSupport) \ \ declare_toplevel_type(G1CollectedHeap*) \ From 43a30ad483088f639bd4792ff43660e3e0158f12 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 17 Jan 2012 10:21:43 -0800 Subject: [PATCH 23/96] 7129271: G1: Interference from multiple threads in PrintGC/PrintGCDetails output During an initial mark pause, signal the Concurrent Mark thread after the pause output from PrintGC/PrintGCDetails is complete. Reviewed-by: tonyp, brutisso --- .../gc_implementation/g1/g1CollectedHeap.cpp | 66 +++++++++++++------ 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 8a2a041540a..bf7ee95d572 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -3557,19 +3557,25 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { verify_region_sets_optional(); verify_dirty_young_regions(); + // This call will decide whether this pause is an initial-mark + // pause. If it is, during_initial_mark_pause() will return true + // for the duration of this pause. + g1_policy()->decide_on_conc_mark_initiation(); + + // We do not allow initial-mark to be piggy-backed on a mixed GC. + assert(!g1_policy()->during_initial_mark_pause() || + g1_policy()->gcs_are_young(), "sanity"); + + // We also do not allow mixed GCs during marking. + assert(!mark_in_progress() || g1_policy()->gcs_are_young(), "sanity"); + + // Record whether this pause is an initial mark. When the current + // thread has completed its logging output and it's safe to signal + // the CM thread, the flag's value in the policy has been reset. + bool should_start_conc_mark = g1_policy()->during_initial_mark_pause(); + + // Inner scope for scope based logging, timers, and stats collection { - // This call will decide whether this pause is an initial-mark - // pause. If it is, during_initial_mark_pause() will return true - // for the duration of this pause. - g1_policy()->decide_on_conc_mark_initiation(); - - // We do not allow initial-mark to be piggy-backed on a mixed GC. - assert(!g1_policy()->during_initial_mark_pause() || - g1_policy()->gcs_are_young(), "sanity"); - - // We also do not allow mixed GCs during marking. - assert(!mark_in_progress() || g1_policy()->gcs_are_young(), "sanity"); - char verbose_str[128]; sprintf(verbose_str, "GC pause "); if (g1_policy()->gcs_are_young()) { @@ -3625,7 +3631,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { Universe::verify(/* allow dirty */ false, /* silent */ false, /* option */ VerifyOption_G1UsePrevMarking); - } COMPILER2_PRESENT(DerivedPointerTable::clear()); @@ -3779,14 +3784,9 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { if (g1_policy()->during_initial_mark_pause()) { concurrent_mark()->checkpointRootsInitialPost(); set_marking_started(); - // CAUTION: after the doConcurrentMark() call below, - // the concurrent marking thread(s) could be running - // concurrently with us. Make sure that anything after - // this point does not assume that we are the only GC thread - // running. Note: of course, the actual marking work will - // not start until the safepoint itself is released in - // ConcurrentGCThread::safepoint_desynchronize(). - doConcurrentMark(); + // Note that we don't actually trigger the CM thread at + // this point. We do that later when we're sure that + // the current thread has completed its logging output. } allocate_dummy_regions(); @@ -3896,6 +3896,15 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { } } + // The closing of the inner scope, immediately above, will complete + // the PrintGC logging output. The record_collection_pause_end() call + // above will complete the logging output of PrintGCDetails. + // + // It is not yet to safe, however, to tell the concurrent mark to + // start as we have some optional output below. We don't want the + // output from the concurrent mark thread interfering with this + // logging output either. + _hrs.verify_optional(); verify_region_sets_optional(); @@ -3913,6 +3922,21 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { g1_rem_set()->print_summary_info(); } + // It should now be safe to tell the concurrent mark thread to start + // without its logging output interfering with the logging output + // that came from the pause. + + if (should_start_conc_mark) { + // CAUTION: after the doConcurrentMark() call below, + // the concurrent marking thread(s) could be running + // concurrently with us. Make sure that anything after + // this point does not assume that we are the only GC thread + // running. Note: of course, the actual marking work will + // not start until the safepoint itself is released in + // ConcurrentGCThread::safepoint_desynchronize(). + doConcurrentMark(); + } + return true; } From c90c1877567786d9fca65ce3e027e32d251a2ed1 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Thu, 19 Jan 2012 09:13:58 -0500 Subject: [PATCH 24/96] 7078465: G1: Don't use the undefined value (-1) for the G1 old memory pool max size Reviewed-by: johnc, brutisso --- .../vm/gc_implementation/g1/g1MonitoringSupport.hpp | 11 +++++------ hotspot/src/share/vm/services/g1MemoryPool.hpp | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp index ac2c4f0e975..a428b10378d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp @@ -89,16 +89,15 @@ class G1CollectedHeap; // // * Min Capacity // -// We set this to 0 for all spaces. We could consider setting the old -// min capacity to the min capacity of the heap (see 7078465). +// We set this to 0 for all spaces. // // * Max Capacity // // For jstat, we set the max capacity of all spaces to heap_capacity, -// given that we don't always have a reasonably upper bound on how big -// each space can grow. For the memory pools, we actually make the max -// capacity undefined. We could consider setting the old max capacity -// to the max capacity of the heap (see 7078465). +// given that we don't always have a reasonable upper bound on how big +// each space can grow. For the memory pools, we make the max +// capacity undefined with the exception of the old memory pool for +// which we make the max capacity same as the max heap capacity. // // If we had more accurate occupancy / capacity information per // region set the above calculations would be greatly simplified and diff --git a/hotspot/src/share/vm/services/g1MemoryPool.hpp b/hotspot/src/share/vm/services/g1MemoryPool.hpp index ce93d0e5a31..912e747b094 100644 --- a/hotspot/src/share/vm/services/g1MemoryPool.hpp +++ b/hotspot/src/share/vm/services/g1MemoryPool.hpp @@ -101,7 +101,7 @@ public: return _g1mm->old_space_used(); } size_t max_size() const { - return _undefined_max; + return _g1mm->old_gen_max(); } MemoryUsage get_memory_usage(); }; From 79463065839b742cc270c03bc0632724b0059800 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Fri, 20 Jan 2012 18:01:32 +0100 Subject: [PATCH 25/96] 7131791: G1: Asserts in nightly testing due to 6976060 Create a handle and fake an object to make sure that we don't loose the memory we just allocated Reviewed-by: tonyp, stefank --- .../src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index bf7ee95d572..1544673a367 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1059,8 +1059,14 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size, if (result != NULL) { if (g1_policy()->need_to_start_conc_mark("concurrent humongous allocation")) { - // We need to release the Heap_lock before we try to call collect + // We need to release the Heap_lock before we try to call collect(). + // The result will not be stored in any object before this method + // returns, so the GC might miss it. Thus, we create a handle to the result + // and fake an object at that place. + CollectedHeap::fill_with_object(result, word_size, false); + Handle h((oop)result); collect(GCCause::_g1_humongous_allocation); + assert(result == (HeapWord*)h(), "Humongous objects should not be moved by collections"); } return result; } From 4e395f3ddd48834bb9d5e362b097c39ab9c13fbb Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Mon, 23 Jan 2012 20:36:16 +0100 Subject: [PATCH 26/96] 7132311: G1: assert((s == klass->oop_size(this)) || (Universe::heap()->is_gc_active() && ((is_typeArray().. Move the check for when to call collect() to before we do a humongous object allocation Reviewed-by: stefank, tonyp --- .../gc_implementation/g1/g1CollectedHeap.cpp | 38 +++++++++---------- .../g1/g1CollectorPolicy.cpp | 15 +++++--- .../g1/g1CollectorPolicy.hpp | 2 +- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 1544673a367..bbe89aa5876 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1029,6 +1029,15 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size, assert(isHumongous(word_size), "attempt_allocation_humongous() " "should only be called for humongous allocations"); + // Humongous objects can exhaust the heap quickly, so we should check if we + // need to start a marking cycle at each humongous object allocation. We do + // the check before we do the actual allocation. The reason for doing it + // before the allocation is that we avoid having to keep track of the newly + // allocated memory while we do a GC. + if (g1_policy()->need_to_start_conc_mark("concurrent humongous allocation", word_size)) { + collect(GCCause::_g1_humongous_allocation); + } + // We will loop until a) we manage to successfully perform the // allocation or b) we successfully schedule a collection which // fails to perform the allocation. b) is the only case when we'll @@ -1045,30 +1054,17 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size, // regions, we'll first try to do the allocation without doing a // collection hoping that there's enough space in the heap. result = humongous_obj_allocate(word_size); - - if (result == NULL) { - if (GC_locker::is_active_and_needs_gc()) { - should_try_gc = false; - } else { - // Read the GC count while still holding the Heap_lock. - gc_count_before = SharedHeap::heap()->total_collections(); - should_try_gc = true; - } + if (result != NULL) { + return result; } - } - if (result != NULL) { - if (g1_policy()->need_to_start_conc_mark("concurrent humongous allocation")) { - // We need to release the Heap_lock before we try to call collect(). - // The result will not be stored in any object before this method - // returns, so the GC might miss it. Thus, we create a handle to the result - // and fake an object at that place. - CollectedHeap::fill_with_object(result, word_size, false); - Handle h((oop)result); - collect(GCCause::_g1_humongous_allocation); - assert(result == (HeapWord*)h(), "Humongous objects should not be moved by collections"); + if (GC_locker::is_active_and_needs_gc()) { + should_try_gc = false; + } else { + // Read the GC count while still holding the Heap_lock. + gc_count_before = SharedHeap::heap()->total_collections(); + should_try_gc = true; } - return result; } if (should_try_gc) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index fdb0a2aa11a..89fa51be308 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -1138,36 +1138,41 @@ double G1CollectorPolicy::max_sum(double* data1, double* data2) { return ret; } -bool G1CollectorPolicy::need_to_start_conc_mark(const char* source) { - if (_g1->mark_in_progress()) { +bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc_word_size) { + if (_g1->concurrent_mark()->cmThread()->during_cycle()) { return false; } size_t marking_initiating_used_threshold = (_g1->capacity() / 100) * InitiatingHeapOccupancyPercent; size_t cur_used_bytes = _g1->non_young_capacity_bytes(); + size_t alloc_byte_size = alloc_word_size * HeapWordSize; - if (cur_used_bytes > marking_initiating_used_threshold) { + if ((cur_used_bytes + alloc_byte_size) > marking_initiating_used_threshold) { if (gcs_are_young()) { - ergo_verbose4(ErgoConcCycles, + ergo_verbose5(ErgoConcCycles, "request concurrent cycle initiation", ergo_format_reason("occupancy higher than threshold") ergo_format_byte("occupancy") + ergo_format_byte("allocation request") ergo_format_byte_perc("threshold") ergo_format_str("source"), cur_used_bytes, + alloc_byte_size, marking_initiating_used_threshold, (double) InitiatingHeapOccupancyPercent, source); return true; } else { - ergo_verbose4(ErgoConcCycles, + ergo_verbose5(ErgoConcCycles, "do not request concurrent cycle initiation", ergo_format_reason("still doing mixed collections") ergo_format_byte("occupancy") + ergo_format_byte("allocation request") ergo_format_byte_perc("threshold") ergo_format_str("source"), cur_used_bytes, + alloc_byte_size, marking_initiating_used_threshold, (double) InitiatingHeapOccupancyPercent, source); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index ee2f1852514..a7f521bf9a5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -799,7 +799,7 @@ public: GenRemSet::Name rem_set_name() { return GenRemSet::CardTable; } - bool need_to_start_conc_mark(const char* source); + bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0); // Update the heuristic info to record a collection pause of the given // start time, where the given number of bytes were used at the start. From 8861552c075f5c54b8724a49ddf1cdfab0f39ed0 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Tue, 24 Jan 2012 17:08:58 -0500 Subject: [PATCH 27/96] 7132398: G1: java.lang.IllegalArgumentException: Invalid threshold: 9223372036854775807 > max (1073741824) Was not passing the right old pool max to the memory pool constructor in the fix for 7078465. Reviewed-by: brutisso, johnc --- hotspot/src/share/vm/services/g1MemoryPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/services/g1MemoryPool.cpp b/hotspot/src/share/vm/services/g1MemoryPool.cpp index c621ecc7951..af862372f80 100644 --- a/hotspot/src/share/vm/services/g1MemoryPool.cpp +++ b/hotspot/src/share/vm/services/g1MemoryPool.cpp @@ -78,7 +78,7 @@ G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, "G1 Old Gen", g1h->g1mm()->old_space_committed(), /* init_size */ - _undefined_max, + g1h->g1mm()->old_gen_max(), true /* support_usage_threshold */) { } MemoryUsage G1OldGenPool::get_memory_usage() { From 0fa6fc2279fd92943e12b494e0446a611eefcdeb Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Thu, 12 Jan 2012 00:06:47 -0800 Subject: [PATCH 28/96] 6484965: G1: piggy-back liveness accounting phase on marking Remove the separate counting phase of concurrent marking by tracking the amount of marked bytes and the cards spanned by marked objects in marking task/worker thread local data structures, which are updated as individual objects are marked. Reviewed-by: brutisso, tonyp --- .../gc_implementation/g1/concurrentMark.cpp | 896 ++++++++++++++---- .../gc_implementation/g1/concurrentMark.hpp | 134 ++- .../g1/concurrentMark.inline.hpp | 168 +++- .../g1/concurrentMarkThread.cpp | 32 +- .../g1/concurrentMarkThread.hpp | 5 +- .../gc_implementation/g1/g1CollectedHeap.cpp | 23 +- .../gc_implementation/g1/g1CollectedHeap.hpp | 6 +- .../vm/gc_implementation/g1/g1EvacFailure.hpp | 21 +- .../vm/gc_implementation/g1/g1OopClosures.hpp | 1 + .../vm/gc_implementation/g1/heapRegion.hpp | 4 +- 10 files changed, 1022 insertions(+), 268 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 1d0415a3176..94a4771719c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -484,6 +484,7 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, _card_bm((rs.size() + CardTableModRefBS::card_size - 1) >> CardTableModRefBS::card_shift, false /* in_resource_area*/), + _prevMarkBitMap(&_markBitMap1), _nextMarkBitMap(&_markBitMap2), _at_least_one_mark_complete(false), @@ -512,7 +513,11 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, _cleanup_times(), _total_counting_time(0.0), _total_rs_scrub_time(0.0), - _parallel_workers(NULL) { + + _parallel_workers(NULL), + + _count_card_bitmaps(NULL), + _count_marked_bytes(NULL) { CMVerboseLevel verbose_level = (CMVerboseLevel) G1MarkingVerboseLevel; if (verbose_level < no_verbose) { verbose_level = no_verbose; @@ -546,6 +551,11 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num); _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num); + _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_task_num); + _count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_task_num); + + BitMap::idx_t card_bm_size = _card_bm.size(); + // so that the assertion in MarkingTaskQueue::task_queue doesn't fail _active_tasks = _max_task_num; for (int i = 0; i < (int) _max_task_num; ++i) { @@ -553,10 +563,26 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, task_queue->initialize(); _task_queues->register_queue(i, task_queue); - _tasks[i] = new CMTask(i, this, task_queue, _task_queues); + _count_card_bitmaps[i] = BitMap(card_bm_size, false); + _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, max_regions); + + _tasks[i] = new CMTask(i, this, + _count_marked_bytes[i], + &_count_card_bitmaps[i], + task_queue, _task_queues); + _accum_task_vtime[i] = 0.0; } + // Calculate the card number for the bottom of the heap. Used + // in biasing indexes into the accounting card bitmaps. + _heap_bottom_card_num = + intptr_t(uintptr_t(_g1h->reserved_region().start()) >> + CardTableModRefBS::card_shift); + + // Clear all the liveness counting data + clear_all_count_data(); + if (ConcGCThreads > ParallelGCThreads) { vm_exit_during_initialization("Can't have more ConcGCThreads " "than ParallelGCThreads."); @@ -775,6 +801,9 @@ void ConcurrentMark::clearNextBitmap() { assert(!g1h->mark_in_progress(), "invariant"); } + // Clear the liveness counting data + clear_all_count_data(); + // Repeat the asserts from above. guarantee(cmThread()->during_cycle(), "invariant"); guarantee(!g1h->mark_in_progress(), "invariant"); @@ -1206,6 +1235,10 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { gclog_or_tty->print_cr("\nRemark led to restart for overflow."); } } else { + // Aggregate the per-task counting data that we have accumulated + // while marking. + aggregate_count_data(); + SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); // We're done with marking. // This is the end of the marking cycle, we're expected all @@ -1243,48 +1276,41 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { g1p->record_concurrent_mark_remark_end(); } -#define CARD_BM_TEST_MODE 0 - +// Used to calculate the # live objects per region +// for verification purposes class CalcLiveObjectsClosure: public HeapRegionClosure { CMBitMapRO* _bm; ConcurrentMark* _cm; - bool _changed; - bool _yield; - size_t _words_done; - size_t _tot_live; - size_t _tot_used; - size_t _regions_done; - double _start_vtime_sec; - BitMap* _region_bm; BitMap* _card_bm; + + // Debugging + size_t _tot_words_done; + size_t _tot_live; + size_t _tot_used; + + size_t _region_marked_bytes; + intptr_t _bottom_card_num; - bool _final; void mark_card_num_range(intptr_t start_card_num, intptr_t last_card_num) { - for (intptr_t i = start_card_num; i <= last_card_num; i++) { -#if CARD_BM_TEST_MODE - guarantee(_card_bm->at(i - _bottom_card_num), "Should already be set."); -#else - _card_bm->par_at_put(i - _bottom_card_num, 1); -#endif + assert(start_card_num <= last_card_num, "sanity"); + BitMap::idx_t start_idx = start_card_num - _bottom_card_num; + BitMap::idx_t last_idx = last_card_num - _bottom_card_num; + + for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) { + _card_bm->par_at_put(i, 1); } } public: - CalcLiveObjectsClosure(bool final, - CMBitMapRO *bm, ConcurrentMark *cm, + CalcLiveObjectsClosure(CMBitMapRO *bm, ConcurrentMark *cm, BitMap* region_bm, BitMap* card_bm) : - _bm(bm), _cm(cm), _changed(false), _yield(true), - _words_done(0), _tot_live(0), _tot_used(0), - _region_bm(region_bm), _card_bm(card_bm),_final(final), - _regions_done(0), _start_vtime_sec(0.0) - { - _bottom_card_num = - intptr_t(uintptr_t(G1CollectedHeap::heap()->reserved_region().start()) >> - CardTableModRefBS::card_shift); - } + _bm(bm), _cm(cm), _region_bm(region_bm), _card_bm(card_bm), + _region_marked_bytes(0), _tot_words_done(0), + _tot_live(0), _tot_used(0), + _bottom_card_num(cm->heap_bottom_card_num()) { } // It takes a region that's not empty (i.e., it has at least one // live object in it and sets its corresponding bit on the region @@ -1300,29 +1326,16 @@ public: _region_bm->par_at_put((BitMap::idx_t) index, true); } else { // Starts humongous case: calculate how many regions are part of - // this humongous region and then set the bit range. It might - // have been a bit more efficient to look at the object that - // spans these humongous regions to calculate their number from - // the object's size. However, it's a good idea to calculate - // this based on the metadata itself, and not the region - // contents, so that this code is not aware of what goes into - // the humongous regions (in case this changes in the future). + // this humongous region and then set the bit range. G1CollectedHeap* g1h = G1CollectedHeap::heap(); - size_t end_index = index + 1; - while (end_index < g1h->n_regions()) { - HeapRegion* chr = g1h->region_at(end_index); - if (!chr->continuesHumongous()) break; - end_index += 1; - } + HeapRegion *last_hr = g1h->heap_region_containing_raw(hr->end() - 1); + size_t end_index = last_hr->hrs_index() + 1; _region_bm->par_at_put_range((BitMap::idx_t) index, (BitMap::idx_t) end_index, true); } } bool doHeapRegion(HeapRegion* hr) { - if (!_final && _regions_done == 0) { - _start_vtime_sec = os::elapsedVTime(); - } if (hr->continuesHumongous()) { // We will ignore these here and process them when their @@ -1336,48 +1349,41 @@ public: } HeapWord* nextTop = hr->next_top_at_mark_start(); - HeapWord* start = hr->top_at_conc_mark_count(); - assert(hr->bottom() <= start && start <= hr->end() && - hr->bottom() <= nextTop && nextTop <= hr->end() && - start <= nextTop, - "Preconditions."); - // Otherwise, record the number of word's we'll examine. + HeapWord* start = hr->bottom(); + + assert(start <= hr->end() && start <= nextTop && nextTop <= hr->end(), + err_msg("Preconditions not met - " + "start: "PTR_FORMAT", nextTop: "PTR_FORMAT", end: "PTR_FORMAT, + start, nextTop, hr->end())); + + // Record the number of word's we'll examine. size_t words_done = (nextTop - start); + // Find the first marked object at or after "start". start = _bm->getNextMarkedWordAddress(start, nextTop); + size_t marked_bytes = 0; // Below, the term "card num" means the result of shifting an address // by the card shift -- address 0 corresponds to card number 0. One // must subtract the card num of the bottom of the heap to obtain a // card table index. + // The first card num of the sequence of live cards currently being // constructed. -1 ==> no sequence. intptr_t start_card_num = -1; + // The last card num of the sequence of live cards currently being // constructed. -1 ==> no sequence. intptr_t last_card_num = -1; while (start < nextTop) { - if (_yield && _cm->do_yield_check()) { - // We yielded. It might be for a full collection, in which case - // all bets are off; terminate the traversal. - if (_cm->has_aborted()) { - _changed = false; - return true; - } else { - // Otherwise, it might be a collection pause, and the region - // we're looking at might be in the collection set. We'll - // abandon this region. - return false; - } - } oop obj = oop(start); int obj_sz = obj->size(); + // The card num of the start of the current object. intptr_t obj_card_num = intptr_t(uintptr_t(start) >> CardTableModRefBS::card_shift); - HeapWord* obj_last = start + obj_sz - 1; intptr_t obj_last_card_num = intptr_t(uintptr_t(obj_last) >> CardTableModRefBS::card_shift); @@ -1395,110 +1401,404 @@ public: start_card_num = obj_card_num; } } -#if CARD_BM_TEST_MODE - /* - gclog_or_tty->print_cr("Setting bits from %d/%d.", - obj_card_num - _bottom_card_num, - obj_last_card_num - _bottom_card_num); - */ - for (intptr_t j = obj_card_num; j <= obj_last_card_num; j++) { - _card_bm->par_at_put(j - _bottom_card_num, 1); - } -#endif } // In any case, we set the last card num. last_card_num = obj_last_card_num; marked_bytes += (size_t)obj_sz * HeapWordSize; + // Find the next marked object after this one. start = _bm->getNextMarkedWordAddress(start + 1, nextTop); - _changed = true; } + // Handle the last range, if any. if (start_card_num != -1) { mark_card_num_range(start_card_num, last_card_num); } - if (_final) { - // Mark the allocated-since-marking portion... - HeapWord* tp = hr->top(); - if (nextTop < tp) { - start_card_num = - intptr_t(uintptr_t(nextTop) >> CardTableModRefBS::card_shift); - last_card_num = - intptr_t(uintptr_t(tp) >> CardTableModRefBS::card_shift); - mark_card_num_range(start_card_num, last_card_num); - // This definitely means the region has live objects. - set_bit_for_region(hr); - } + + // Mark the allocated-since-marking portion... + HeapWord* top = hr->top(); + if (nextTop < top) { + start_card_num = intptr_t(uintptr_t(nextTop) >> CardTableModRefBS::card_shift); + last_card_num = intptr_t(uintptr_t(top) >> CardTableModRefBS::card_shift); + + mark_card_num_range(start_card_num, last_card_num); + + // This definitely means the region has live objects. + set_bit_for_region(hr); } - hr->add_to_marked_bytes(marked_bytes); // Update the live region bitmap. if (marked_bytes > 0) { set_bit_for_region(hr); } - hr->set_top_at_conc_mark_count(nextTop); + + // Set the marked bytes for the current region so that + // it can be queried by a calling verificiation routine + _region_marked_bytes = marked_bytes; + _tot_live += hr->next_live_bytes(); _tot_used += hr->used(); - _words_done = words_done; - - if (!_final) { - ++_regions_done; - if (_regions_done % 10 == 0) { - double end_vtime_sec = os::elapsedVTime(); - double elapsed_vtime_sec = end_vtime_sec - _start_vtime_sec; - if (elapsed_vtime_sec > (10.0 / 1000.0)) { - jlong sleep_time_ms = - (jlong) (elapsed_vtime_sec * _cm->cleanup_sleep_factor() * 1000.0); - os::sleep(Thread::current(), sleep_time_ms, false); - _start_vtime_sec = end_vtime_sec; - } - } - } + _tot_words_done = words_done; return false; } - bool changed() { return _changed; } - void reset() { _changed = false; _words_done = 0; } - void no_yield() { _yield = false; } - size_t words_done() { return _words_done; } - size_t tot_live() { return _tot_live; } - size_t tot_used() { return _tot_used; } + size_t region_marked_bytes() const { return _region_marked_bytes; } + + // Debugging + size_t tot_words_done() const { return _tot_words_done; } + size_t tot_live() const { return _tot_live; } + size_t tot_used() const { return _tot_used; } +}; + +// Heap region closure used for verifying the counting data +// that was accumulated concurrently and aggregated during +// the remark pause. This closure is applied to the heap +// regions during the STW cleanup pause. + +class VerifyLiveObjectDataHRClosure: public HeapRegionClosure { + ConcurrentMark* _cm; + CalcLiveObjectsClosure _calc_cl; + BitMap* _region_bm; // Region BM to be verified + BitMap* _card_bm; // Card BM to be verified + bool _verbose; // verbose output? + + BitMap* _exp_region_bm; // Expected Region BM values + BitMap* _exp_card_bm; // Expected card BM values + + int _failures; + +public: + VerifyLiveObjectDataHRClosure(ConcurrentMark* cm, + BitMap* region_bm, + BitMap* card_bm, + BitMap* exp_region_bm, + BitMap* exp_card_bm, + bool verbose) : + _cm(cm), + _calc_cl(_cm->nextMarkBitMap(), _cm, exp_region_bm, exp_card_bm), + _region_bm(region_bm), _card_bm(card_bm), _verbose(verbose), + _exp_region_bm(exp_region_bm), _exp_card_bm(exp_card_bm), + _failures(0) { } + + int failures() const { return _failures; } + + bool doHeapRegion(HeapRegion* hr) { + if (hr->continuesHumongous()) { + // We will ignore these here and process them when their + // associated "starts humongous" region is processed (see + // set_bit_for_heap_region()). Note that we cannot rely on their + // associated "starts humongous" region to have their bit set to + // 1 since, due to the region chunking in the parallel region + // iteration, a "continues humongous" region might be visited + // before its associated "starts humongous". + return false; + } + + int failures = 0; + + // Call the CalcLiveObjectsClosure to walk the marking bitmap for + // this region and set the corresponding bits in the expected region + // and card bitmaps. + bool res = _calc_cl.doHeapRegion(hr); + assert(res == false, "should be continuing"); + + MutexLockerEx x((_verbose ? ParGCRareEvent_lock : NULL), + Mutex::_no_safepoint_check_flag); + + // Verify that _top_at_conc_count == ntams + if (hr->top_at_conc_mark_count() != hr->next_top_at_mark_start()) { + if (_verbose) { + gclog_or_tty->print_cr("Region " SIZE_FORMAT ": top at conc count incorrect: " + "expected " PTR_FORMAT ", actual: " PTR_FORMAT, + hr->hrs_index(), hr->next_top_at_mark_start(), + hr->top_at_conc_mark_count()); + } + failures += 1; + } + + // Verify the marked bytes for this region. + size_t exp_marked_bytes = _calc_cl.region_marked_bytes(); + size_t act_marked_bytes = hr->next_marked_bytes(); + + // We're not OK if expected marked bytes > actual marked bytes. It means + // we have missed accounting some objects during the actual marking. + if (exp_marked_bytes > act_marked_bytes) { + if (_verbose) { + gclog_or_tty->print_cr("Region " SIZE_FORMAT ": marked bytes mismatch: " + "expected: " SIZE_FORMAT ", actual: " SIZE_FORMAT, + hr->hrs_index(), exp_marked_bytes, act_marked_bytes); + } + failures += 1; + } + + // Verify the bit, for this region, in the actual and expected + // (which was just calculated) region bit maps. + // We're not OK if the bit in the calculated expected region + // bitmap is set and the bit in the actual region bitmap is not. + BitMap::idx_t index = (BitMap::idx_t)hr->hrs_index(); + + bool expected = _exp_region_bm->at(index); + bool actual = _region_bm->at(index); + if (expected && !actual) { + if (_verbose) { + gclog_or_tty->print_cr("Region " SIZE_FORMAT ": region bitmap mismatch: " + "expected: %d, actual: %d", + hr->hrs_index(), expected, actual); + } + failures += 1; + } + + // Verify that the card bit maps for the cards spanned by the current + // region match. We have an error if we have a set bit in the expected + // bit map and the corresponding bit in the actual bitmap is not set. + + BitMap::idx_t start_idx = _cm->card_bitmap_index_for(hr->bottom()); + BitMap::idx_t end_idx = _cm->card_bitmap_index_for(hr->top()); + + for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) { + expected = _exp_card_bm->at(i); + actual = _card_bm->at(i); + + if (expected && !actual) { + if (_verbose) { + gclog_or_tty->print_cr("Region " SIZE_FORMAT ": card bitmap mismatch at " SIZE_FORMAT ": " + "expected: %d, actual: %d", + hr->hrs_index(), i, expected, actual); + } + failures += 1; + } + } + + if (failures > 0 && _verbose) { + gclog_or_tty->print_cr("Region " HR_FORMAT ", ntams: " PTR_FORMAT ", " + "marked_bytes: calc/actual " SIZE_FORMAT "/" SIZE_FORMAT, + HR_FORMAT_PARAMS(hr), hr->next_top_at_mark_start(), + _calc_cl.region_marked_bytes(), hr->next_marked_bytes()); + } + + _failures += failures; + + // We could stop iteration over the heap when we + // find the first voilating region by returning true. + return false; + } }; -void ConcurrentMark::calcDesiredRegions() { - _region_bm.clear(); - _card_bm.clear(); - CalcLiveObjectsClosure calccl(false /*final*/, - nextMarkBitMap(), this, - &_region_bm, &_card_bm); - G1CollectedHeap *g1h = G1CollectedHeap::heap(); - g1h->heap_region_iterate(&calccl); +class G1ParVerifyFinalCountTask: public AbstractGangTask { +protected: + G1CollectedHeap* _g1h; + ConcurrentMark* _cm; + BitMap* _actual_region_bm; + BitMap* _actual_card_bm; - do { - calccl.reset(); - g1h->heap_region_iterate(&calccl); - } while (calccl.changed()); -} + uint _n_workers; + + BitMap* _expected_region_bm; + BitMap* _expected_card_bm; + + int _failures; + bool _verbose; + +public: + G1ParVerifyFinalCountTask(G1CollectedHeap* g1h, + BitMap* region_bm, BitMap* card_bm, + BitMap* expected_region_bm, BitMap* expected_card_bm) + : AbstractGangTask("G1 verify final counting"), + _g1h(g1h), _cm(_g1h->concurrent_mark()), + _actual_region_bm(region_bm), _actual_card_bm(card_bm), + _expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm), + _failures(0), _verbose(false), + _n_workers(0) { + assert(VerifyDuringGC, "don't call this otherwise"); + + // Use the value already set as the number of active threads + // in the call to run_task(). + if (G1CollectedHeap::use_parallel_gc_threads()) { + assert( _g1h->workers()->active_workers() > 0, + "Should have been previously set"); + _n_workers = _g1h->workers()->active_workers(); + } else { + _n_workers = 1; + } + + assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity"); + assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity"); + + _verbose = _cm->verbose_medium(); + } + + void work(uint worker_id) { + assert(worker_id < _n_workers, "invariant"); + + VerifyLiveObjectDataHRClosure verify_cl(_cm, + _actual_region_bm, _actual_card_bm, + _expected_region_bm, + _expected_card_bm, + _verbose); + + if (G1CollectedHeap::use_parallel_gc_threads()) { + _g1h->heap_region_par_iterate_chunked(&verify_cl, + worker_id, + _n_workers, + HeapRegion::VerifyCountClaimValue); + } else { + _g1h->heap_region_iterate(&verify_cl); + } + + Atomic::add(verify_cl.failures(), &_failures); + } + + int failures() const { return _failures; } +}; + +// Final update of count data (during cleanup). +// Adds [top_at_count, NTAMS) to the marked bytes for each +// region. Sets the bits in the card bitmap corresponding +// to the interval [top_at_count, top], and sets the +// liveness bit for each region containing live data +// in the region bitmap. + +class FinalCountDataUpdateClosure: public HeapRegionClosure { + ConcurrentMark* _cm; + BitMap* _region_bm; + BitMap* _card_bm; + + size_t _total_live_bytes; + size_t _total_used_bytes; + size_t _total_words_done; + + void set_card_bitmap_range(BitMap::idx_t start_idx, BitMap::idx_t last_idx) { + assert(start_idx <= last_idx, "sanity"); + + // Set the inclusive bit range [start_idx, last_idx]. + // For small ranges (up to 8 cards) use a simple loop; otherwise + // use par_at_put_range. + if ((last_idx - start_idx) <= 8) { + for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) { + _card_bm->par_set_bit(i); + } + } else { + assert(last_idx < _card_bm->size(), "sanity"); + // Note BitMap::par_at_put_range() is exclusive. + _card_bm->par_at_put_range(start_idx, last_idx+1, true); + } + } + + // It takes a region that's not empty (i.e., it has at least one + // live object in it and sets its corresponding bit on the region + // bitmap to 1. If the region is "starts humongous" it will also set + // to 1 the bits on the region bitmap that correspond to its + // associated "continues humongous" regions. + void set_bit_for_region(HeapRegion* hr) { + assert(!hr->continuesHumongous(), "should have filtered those out"); + + size_t index = hr->hrs_index(); + if (!hr->startsHumongous()) { + // Normal (non-humongous) case: just set the bit. + _region_bm->par_set_bit((BitMap::idx_t) index); + } else { + // Starts humongous case: calculate how many regions are part of + // this humongous region and then set the bit range. + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + HeapRegion *last_hr = g1h->heap_region_containing_raw(hr->end() - 1); + size_t end_index = last_hr->hrs_index() + 1; + _region_bm->par_at_put_range((BitMap::idx_t) index, + (BitMap::idx_t) end_index, true); + } + } + + public: + FinalCountDataUpdateClosure(ConcurrentMark* cm, + BitMap* region_bm, + BitMap* card_bm) : + _cm(cm), _region_bm(region_bm), _card_bm(card_bm), + _total_words_done(0), _total_live_bytes(0), _total_used_bytes(0) { } + + bool doHeapRegion(HeapRegion* hr) { + + if (hr->continuesHumongous()) { + // We will ignore these here and process them when their + // associated "starts humongous" region is processed (see + // set_bit_for_heap_region()). Note that we cannot rely on their + // associated "starts humongous" region to have their bit set to + // 1 since, due to the region chunking in the parallel region + // iteration, a "continues humongous" region might be visited + // before its associated "starts humongous". + return false; + } + + HeapWord* start = hr->top_at_conc_mark_count(); + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* top = hr->top(); + + assert(hr->bottom() <= start && start <= hr->end() && + hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); + + size_t words_done = ntams - hr->bottom(); + + if (start < ntams) { + // Region was changed between remark and cleanup pauses + // We need to add (ntams - start) to the marked bytes + // for this region, and set bits for the range + // [ card_idx(start), card_idx(ntams) ) in the card bitmap. + size_t live_bytes = (ntams - start) * HeapWordSize; + hr->add_to_marked_bytes(live_bytes); + + // Record the new top at conc count + hr->set_top_at_conc_mark_count(ntams); + + // The setting of the bits in the card bitmap takes place below + } + + // Mark the allocated-since-marking portion... + if (ntams < top) { + // This definitely means the region has live objects. + set_bit_for_region(hr); + } + + // Now set the bits for [start, top] + BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); + BitMap::idx_t last_idx = _cm->card_bitmap_index_for(top); + set_card_bitmap_range(start_idx, last_idx); + + // Set the bit for the region if it contains live data + if (hr->next_marked_bytes() > 0) { + set_bit_for_region(hr); + } + + _total_words_done += words_done; + _total_used_bytes += hr->used(); + _total_live_bytes += hr->next_marked_bytes(); + + return false; + } + + size_t total_words_done() const { return _total_words_done; } + size_t total_live_bytes() const { return _total_live_bytes; } + size_t total_used_bytes() const { return _total_used_bytes; } +}; class G1ParFinalCountTask: public AbstractGangTask { protected: G1CollectedHeap* _g1h; - CMBitMap* _bm; + ConcurrentMark* _cm; + BitMap* _actual_region_bm; + BitMap* _actual_card_bm; + uint _n_workers; + size_t *_live_bytes; size_t *_used_bytes; - BitMap* _region_bm; - BitMap* _card_bm; + public: - G1ParFinalCountTask(G1CollectedHeap* g1h, CMBitMap* bm, - BitMap* region_bm, BitMap* card_bm) - : AbstractGangTask("G1 final counting"), _g1h(g1h), - _bm(bm), _region_bm(region_bm), _card_bm(card_bm), - _n_workers(0) - { + G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) + : AbstractGangTask("G1 final counting"), + _g1h(g1h), _cm(_g1h->concurrent_mark()), + _actual_region_bm(region_bm), _actual_card_bm(card_bm), + _n_workers(0) { // Use the value already set as the number of active threads // in the call to run_task(). Needed for the allocation of // _live_bytes and _used_bytes. @@ -1520,29 +1820,32 @@ public: } void work(uint worker_id) { - CalcLiveObjectsClosure calccl(true /*final*/, - _bm, _g1h->concurrent_mark(), - _region_bm, _card_bm); - calccl.no_yield(); + assert(worker_id < _n_workers, "invariant"); + + FinalCountDataUpdateClosure final_update_cl(_cm, + _actual_region_bm, + _actual_card_bm); + if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->heap_region_par_iterate_chunked(&calccl, worker_id, - (int) _n_workers, + _g1h->heap_region_par_iterate_chunked(&final_update_cl, + worker_id, + _n_workers, HeapRegion::FinalCountClaimValue); } else { - _g1h->heap_region_iterate(&calccl); + _g1h->heap_region_iterate(&final_update_cl); } - assert(calccl.complete(), "Shouldn't have yielded!"); - assert(worker_id < _n_workers, "invariant"); - _live_bytes[worker_id] = calccl.tot_live(); - _used_bytes[worker_id] = calccl.tot_used(); + _live_bytes[worker_id] = final_update_cl.total_live_bytes(); + _used_bytes[worker_id] = final_update_cl.total_used_bytes(); } + size_t live_bytes() { size_t live_bytes = 0; for (uint i = 0; i < _n_workers; ++i) live_bytes += _live_bytes[i]; return live_bytes; } + size_t used_bytes() { size_t used_bytes = 0; for (uint i = 0; i < _n_workers; ++i) @@ -1705,8 +2008,7 @@ public: G1ParScrubRemSetTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) : AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()), - _region_bm(region_bm), _card_bm(card_bm) - {} + _region_bm(region_bm), _card_bm(card_bm) { } void work(uint worker_id) { if (G1CollectedHeap::use_parallel_gc_threads()) { @@ -1753,11 +2055,10 @@ void ConcurrentMark::cleanup() { uint n_workers; // Do counting once more with the world stopped for good measure. - G1ParFinalCountTask g1_par_count_task(g1h, nextMarkBitMap(), - &_region_bm, &_card_bm); + G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm); + if (G1CollectedHeap::use_parallel_gc_threads()) { - assert(g1h->check_heap_region_claim_values( - HeapRegion::InitialClaimValue), + assert(g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity check"); g1h->set_par_threads(); @@ -1768,14 +2069,42 @@ void ConcurrentMark::cleanup() { // Done with the parallel phase so reset to 0. g1h->set_par_threads(0); - assert(g1h->check_heap_region_claim_values( - HeapRegion::FinalCountClaimValue), + assert(g1h->check_heap_region_claim_values(HeapRegion::FinalCountClaimValue), "sanity check"); } else { n_workers = 1; g1_par_count_task.work(0); } + if (VerifyDuringGC) { + // Verify that the counting data accumulated during marking matches + // that calculated by walking the marking bitmap. + + // Bitmaps to hold expected values + BitMap expected_region_bm(_region_bm.size(), false); + BitMap expected_card_bm(_card_bm.size(), false); + + G1ParVerifyFinalCountTask g1_par_verify_task(g1h, + &_region_bm, + &_card_bm, + &expected_region_bm, + &expected_card_bm); + + if (G1CollectedHeap::use_parallel_gc_threads()) { + g1h->set_par_threads((int)n_workers); + g1h->workers()->run_task(&g1_par_verify_task); + // Done with the parallel phase so reset to 0. + g1h->set_par_threads(0); + + assert(g1h->check_heap_region_claim_values(HeapRegion::VerifyCountClaimValue), + "sanity check"); + } else { + g1_par_verify_task.work(0); + } + + guarantee(g1_par_verify_task.failures() == 0, "Unexpected accounting failures"); + } + size_t known_garbage_bytes = g1_par_count_task.used_bytes() - g1_par_count_task.live_bytes(); g1p->set_known_garbage_bytes(known_garbage_bytes); @@ -1968,12 +2297,11 @@ bool G1CMIsAliveClosure::do_object_b(oop obj) { class G1CMKeepAliveClosure: public OopClosure { G1CollectedHeap* _g1; ConcurrentMark* _cm; - CMBitMap* _bitMap; public: - G1CMKeepAliveClosure(G1CollectedHeap* g1, ConcurrentMark* cm, - CMBitMap* bitMap) : - _g1(g1), _cm(cm), - _bitMap(bitMap) {} + G1CMKeepAliveClosure(G1CollectedHeap* g1, ConcurrentMark* cm) : + _g1(g1), _cm(cm) { + assert(Thread::current()->is_VM_thread(), "otherwise fix worker id"); + } virtual void do_oop(narrowOop* p) { do_oop_work(p); } virtual void do_oop( oop* p) { do_oop_work(p); } @@ -1989,26 +2317,25 @@ class G1CMKeepAliveClosure: public OopClosure { } if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(obj)) { - _bitMap->mark(addr); + _cm->mark_and_count(obj); _cm->mark_stack_push(obj); } } }; class G1CMDrainMarkingStackClosure: public VoidClosure { + ConcurrentMark* _cm; CMMarkStack* _markStack; - CMBitMap* _bitMap; G1CMKeepAliveClosure* _oopClosure; public: - G1CMDrainMarkingStackClosure(CMBitMap* bitMap, CMMarkStack* markStack, + G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMMarkStack* markStack, G1CMKeepAliveClosure* oopClosure) : - _bitMap(bitMap), + _cm(cm), _markStack(markStack), - _oopClosure(oopClosure) - {} + _oopClosure(oopClosure) { } void do_void() { - _markStack->drain((OopClosure*)_oopClosure, _bitMap, false); + _markStack->drain((OopClosure*)_oopClosure, _cm->nextMarkBitMap(), false); } }; @@ -2087,8 +2414,7 @@ class G1CMParDrainMarkingStackClosure: public VoidClosure { CMTask* _task; public: G1CMParDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task) : - _cm(cm), _task(task) - {} + _cm(cm), _task(task) { } void do_void() { do { @@ -2227,9 +2553,9 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { rp->setup_policy(clear_all_soft_refs); assert(_markStack.isEmpty(), "mark stack should be empty"); - G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); + G1CMKeepAliveClosure g1_keep_alive(g1h, this); G1CMDrainMarkingStackClosure - g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); + g1_drain_mark_stack(this, &_markStack, &g1_keep_alive); // We use the work gang from the G1CollectedHeap and we utilize all // the worker threads. @@ -2601,18 +2927,6 @@ void ConcurrentMark::print_reachable(const char* str, // during an evacuation pause). This was a late change to the code and // is currently not being taken advantage of. -class CMGlobalObjectClosure : public ObjectClosure { -private: - ConcurrentMark* _cm; - -public: - void do_object(oop obj) { - _cm->deal_with_reference(obj); - } - - CMGlobalObjectClosure(ConcurrentMark* cm) : _cm(cm) { } -}; - void ConcurrentMark::deal_with_reference(oop obj) { if (verbose_high()) { gclog_or_tty->print_cr("[global] we're dealing with reference "PTR_FORMAT, @@ -2657,6 +2971,18 @@ void ConcurrentMark::deal_with_reference(oop obj) { } } +class CMGlobalObjectClosure : public ObjectClosure { +private: + ConcurrentMark* _cm; + +public: + void do_object(oop obj) { + _cm->deal_with_reference(obj); + } + + CMGlobalObjectClosure(ConcurrentMark* cm) : _cm(cm) { } +}; + void ConcurrentMark::drainAllSATBBuffers() { guarantee(false, "drainAllSATBBuffers(): don't call this any more"); @@ -2678,15 +3004,6 @@ void ConcurrentMark::drainAllSATBBuffers() { assert(satb_mq_set.completed_buffers_num() == 0, "invariant"); } -void ConcurrentMark::clear(oop p) { - assert(p != NULL && p->is_oop(), "expected an oop"); - HeapWord* addr = (HeapWord*)p; - assert(addr >= _nextMarkBitMap->startWord() || - addr < _nextMarkBitMap->endWord(), "in a region"); - - _nextMarkBitMap->clear(addr); -} - void ConcurrentMark::clearRangePrevBitmap(MemRegion mr) { // Note we are overriding the read-only view of the prev map here, via // the cast. @@ -3000,6 +3317,192 @@ void ConcurrentMark::clear_marking_state(bool clear_overflow) { } } +// Aggregate the counting data that was constructed concurrently +// with marking. +class AggregateCountDataHRClosure: public HeapRegionClosure { + ConcurrentMark* _cm; + BitMap* _cm_card_bm; + size_t _max_task_num; + + public: + AggregateCountDataHRClosure(ConcurrentMark *cm, + BitMap* cm_card_bm, + size_t max_task_num) : + _cm(cm), _cm_card_bm(cm_card_bm), + _max_task_num(max_task_num) { } + + bool is_card_aligned(HeapWord* p) { + return ((uintptr_t(p) & (CardTableModRefBS::card_size - 1)) == 0); + } + + bool doHeapRegion(HeapRegion* hr) { + if (hr->continuesHumongous()) { + // We will ignore these here and process them when their + // associated "starts humongous" region is processed. + // Note that we cannot rely on their associated + // "starts humongous" region to have their bit set to 1 + // since, due to the region chunking in the parallel region + // iteration, a "continues humongous" region might be visited + // before its associated "starts humongous". + return false; + } + + HeapWord* start = hr->bottom(); + HeapWord* limit = hr->next_top_at_mark_start(); + HeapWord* end = hr->end(); + + assert(start <= limit && limit <= hr->top() && hr->top() <= hr->end(), + err_msg("Preconditions not met - " + "start: "PTR_FORMAT", limit: "PTR_FORMAT", " + "top: "PTR_FORMAT", end: "PTR_FORMAT, + start, limit, hr->top(), hr->end())); + + assert(hr->next_marked_bytes() == 0, "Precondition"); + + if (start == limit) { + // NTAMS of this region has not been set so nothing to do. + return false; + } + + assert(is_card_aligned(start), "sanity"); + assert(is_card_aligned(end), "sanity"); + + BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); + BitMap::idx_t limit_idx = _cm->card_bitmap_index_for(limit); + BitMap::idx_t end_idx = _cm->card_bitmap_index_for(end); + + // If ntams is not card aligned then we bump the index for + // limit so that we get the card spanning ntams. + if (!is_card_aligned(limit)) { + limit_idx += 1; + } + + assert(limit_idx <= end_idx, "or else use atomics"); + + // Aggregate the "stripe" in the count data associated with hr. + size_t hrs_index = hr->hrs_index(); + size_t marked_bytes = 0; + + for (int i = 0; (size_t)i < _max_task_num; i += 1) { + size_t* marked_bytes_array = _cm->count_marked_bytes_array_for(i); + BitMap* task_card_bm = _cm->count_card_bitmap_for(i); + + // Fetch the marked_bytes in this region for task i and + // add it to the running total for this region. + marked_bytes += marked_bytes_array[hrs_index]; + + // Now union the bitmaps[0,max_task_num)[start_idx..limit_idx) + // into the global card bitmap. + BitMap::idx_t scan_idx = task_card_bm->get_next_one_offset(start_idx, limit_idx); + + while (scan_idx < limit_idx) { + assert(task_card_bm->at(scan_idx) == true, "should be"); + _cm_card_bm->set_bit(scan_idx); + assert(_cm_card_bm->at(scan_idx) == true, "should be"); + + // BitMap::get_next_one_offset() can handle the case when + // its left_offset parameter is greater than its right_offset + // parameter. If does, however, have an early exit if + // left_offset == right_offset. So let's limit the value + // passed in for left offset here. + BitMap::idx_t next_idx = MIN2(scan_idx + 1, limit_idx); + scan_idx = task_card_bm->get_next_one_offset(next_idx, limit_idx); + } + } + + // Update the marked bytes for this region. + hr->add_to_marked_bytes(marked_bytes); + + // Now set the top at count to NTAMS. + hr->set_top_at_conc_mark_count(limit); + + // Next heap region + return false; + } +}; + +class G1AggregateCountDataTask: public AbstractGangTask { +protected: + G1CollectedHeap* _g1h; + ConcurrentMark* _cm; + BitMap* _cm_card_bm; + size_t _max_task_num; + int _active_workers; + +public: + G1AggregateCountDataTask(G1CollectedHeap* g1h, + ConcurrentMark* cm, + BitMap* cm_card_bm, + size_t max_task_num, + int n_workers) : + AbstractGangTask("Count Aggregation"), + _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm), + _max_task_num(max_task_num), + _active_workers(n_workers) { } + + void work(uint worker_id) { + AggregateCountDataHRClosure cl(_cm, _cm_card_bm, _max_task_num); + + if (G1CollectedHeap::use_parallel_gc_threads()) { + _g1h->heap_region_par_iterate_chunked(&cl, worker_id, + _active_workers, + HeapRegion::AggregateCountClaimValue); + } else { + _g1h->heap_region_iterate(&cl); + } + } +}; + + +void ConcurrentMark::aggregate_count_data() { + int n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? + _g1h->workers()->active_workers() : + 1); + + G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm, + _max_task_num, n_workers); + + if (G1CollectedHeap::use_parallel_gc_threads()) { + assert(_g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue), + "sanity check"); + _g1h->set_par_threads(n_workers); + _g1h->workers()->run_task(&g1_par_agg_task); + _g1h->set_par_threads(0); + + assert(_g1h->check_heap_region_claim_values(HeapRegion::AggregateCountClaimValue), + "sanity check"); + _g1h->reset_heap_region_claim_values(); + } else { + g1_par_agg_task.work(0); + } +} + +// Clear the per-worker arrays used to store the per-region counting data +void ConcurrentMark::clear_all_count_data() { + // Clear the global card bitmap - it will be filled during + // liveness count aggregation (during remark) and the + // final counting task. + _card_bm.clear(); + + // Clear the global region bitmap - it will be filled as part + // of the final counting task. + _region_bm.clear(); + + size_t max_regions = _g1h->max_regions(); + assert(_max_task_num != 0, "unitialized"); + + for (int i = 0; (size_t) i < _max_task_num; i += 1) { + BitMap* task_card_bm = count_card_bitmap_for(i); + size_t* marked_bytes_array = count_marked_bytes_array_for(i); + + assert(task_card_bm->size() == _card_bm.size(), "size mismatch"); + assert(marked_bytes_array != NULL, "uninitialized"); + + memset(marked_bytes_array, 0, (max_regions * sizeof(size_t))); + task_card_bm->clear(); + } +} + void ConcurrentMark::print_stats() { if (verbose_stats()) { gclog_or_tty->print_cr("---------------------------------------------------------------------"); @@ -3335,6 +3838,8 @@ void ConcurrentMark::reset_active_task_region_fields_in_cset() { void ConcurrentMark::abort() { // Clear all marks to force marking thread to do nothing _nextMarkBitMap->clearAll(); + // Clear the liveness counting data + clear_all_count_data(); // Empty mark stack clear_marking_state(); for (int i = 0; i < (int)_max_task_num; ++i) { @@ -3387,10 +3892,9 @@ void ConcurrentMark::print_summary_info() { (_init_times.sum() + _remark_times.sum() + _cleanup_times.sum())/1000.0); gclog_or_tty->print_cr(" Total concurrent time = %8.2f s " - "(%8.2f s marking, %8.2f s counting).", + "(%8.2f s marking).", cmThread()->vtime_accum(), - cmThread()->vtime_mark_accum(), - cmThread()->vtime_count_accum()); + cmThread()->vtime_mark_accum()); } void ConcurrentMark::print_worker_threads_on(outputStream* st) const { @@ -4682,6 +5186,8 @@ void CMTask::do_marking_step(double time_target_ms, CMTask::CMTask(int task_id, ConcurrentMark* cm, + size_t* marked_bytes, + BitMap* card_bm, CMTaskQueue* task_queue, CMTaskQueueSet* task_queues) : _g1h(G1CollectedHeap::heap()), @@ -4691,7 +5197,9 @@ CMTask::CMTask(int task_id, _task_queue(task_queue), _task_queues(task_queues), _cm_oop_closure(NULL), - _aborted_region(MemRegion()) { + _aborted_region(MemRegion()), + _marked_bytes_array(marked_bytes), + _card_bm(card_bm) { guarantee(task_queue != NULL, "invariant"); guarantee(task_queues != NULL, "invariant"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 0b8b633be34..fc313869fd2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -426,7 +426,6 @@ protected: WorkGangBarrierSync _first_overflow_barrier_sync; WorkGangBarrierSync _second_overflow_barrier_sync; - // this is set by any task, when an overflow on the global data // structures is detected. volatile bool _has_overflown; @@ -578,6 +577,27 @@ protected: } } + // Live Data Counting data structures... + // These data structures are initialized at the start of + // marking. They are written to while marking is active. + // They are aggregated during remark; the aggregated values + // are then used to populate the _region_bm, _card_bm, and + // the total live bytes, which are then subsequently updated + // during cleanup. + + // An array of bitmaps (one bit map per task). Each bitmap + // is used to record the cards spanned by the live objects + // marked by that task/worker. + BitMap* _count_card_bitmaps; + + // Used to record the number of marked live bytes + // (for each region, by worker thread). + size_t** _count_marked_bytes; + + // Card index of the bottom of the G1 heap. Used for biasing indices into + // the card bitmaps. + intptr_t _heap_bottom_card_num; + public: // Manipulation of the global mark stack. // Notice that the first mark_stack_push is CAS-based, whereas the @@ -703,6 +723,7 @@ public: ConcurrentMark(ReservedSpace rs, int max_regions); ~ConcurrentMark(); + ConcurrentMarkThread* cmThread() { return _cmThread; } CMBitMapRO* prevMarkBitMap() const { return _prevMarkBitMap; } @@ -721,7 +742,7 @@ public: // This notifies CM that a root during initial-mark needs to be // grayed. It is MT-safe. - inline void grayRoot(oop obj, size_t word_size); + inline void grayRoot(oop obj, size_t word_size, uint worker_id); // It's used during evacuation pauses to gray a region, if // necessary, and it's MT-safe. It assumes that the caller has @@ -781,15 +802,13 @@ public: void checkpointRootsFinal(bool clear_all_soft_refs); void checkpointRootsFinalWork(); - void calcDesiredRegions(); void cleanup(); void completeCleanup(); // Mark in the previous bitmap. NB: this is usually read-only, so use // this carefully! inline void markPrev(oop p); - inline void markNext(oop p); - void clear(oop p); + // Clears marks for all objects in the given range, for the prev, // next, or both bitmaps. NB: the previous bitmap is usually // read-only, so use this carefully! @@ -913,6 +932,104 @@ public: bool verbose_high() { return _MARKING_VERBOSE_ && _verbose_level >= high_verbose; } + + // Counting data structure accessors + + // Returns the card number of the bottom of the G1 heap. + // Used in biasing indices into accounting card bitmaps. + intptr_t heap_bottom_card_num() const { + return _heap_bottom_card_num; + } + + // Returns the card bitmap for a given task or worker id. + BitMap* count_card_bitmap_for(uint worker_id) { + assert(0 <= worker_id && worker_id < _max_task_num, "oob"); + assert(_count_card_bitmaps != NULL, "uninitialized"); + BitMap* task_card_bm = &_count_card_bitmaps[worker_id]; + assert(task_card_bm->size() == _card_bm.size(), "size mismatch"); + return task_card_bm; + } + + // Returns the array containing the marked bytes for each region, + // for the given worker or task id. + size_t* count_marked_bytes_array_for(uint worker_id) { + assert(0 <= worker_id && worker_id < _max_task_num, "oob"); + assert(_count_marked_bytes != NULL, "uninitialized"); + size_t* marked_bytes_array = _count_marked_bytes[worker_id]; + assert(marked_bytes_array != NULL, "uninitialized"); + return marked_bytes_array; + } + + // Returns the index in the liveness accounting card table bitmap + // for the given address + inline BitMap::idx_t card_bitmap_index_for(HeapWord* addr); + + // Counts the size of the given memory region in the the given + // marked_bytes array slot for the given HeapRegion. + // Sets the bits in the given card bitmap that are associated with the + // cards that are spanned by the memory region. + inline void count_region(MemRegion mr, HeapRegion* hr, + size_t* marked_bytes_array, + BitMap* task_card_bm); + + // Counts the given memory region in the task/worker counting + // data structures for the given worker id. + inline void count_region(MemRegion mr, uint worker_id); + + // Counts the given object in the given task/worker counting + // data structures. + inline void count_object(oop obj, HeapRegion* hr, + size_t* marked_bytes_array, + BitMap* task_card_bm); + + // Counts the given object in the task/worker counting data + // structures for the given worker id. + inline void count_object(oop obj, HeapRegion* hr, uint worker_id); + + // Attempts to mark the given object and, if successful, counts + // the object in the given task/worker counting structures. + inline bool par_mark_and_count(oop obj, HeapRegion* hr, + size_t* marked_bytes_array, + BitMap* task_card_bm); + + // Attempts to mark the given object and, if successful, counts + // the object in the task/worker counting structures for the + // given worker id. + inline bool par_mark_and_count(oop obj, HeapRegion* hr, uint worker_id); + + // Similar to the above routine but we don't know the heap region that + // contains the object to be marked/counted, which this routine looks up. + inline bool par_mark_and_count(oop obj, uint worker_id); + + // Similar to the above routine but there are times when we cannot + // safely calculate the size of obj due to races and we, therefore, + // pass the size in as a parameter. It is the caller's reponsibility + // to ensure that the size passed in for obj is valid. + inline bool par_mark_and_count(oop obj, size_t word_size, uint worker_id); + + // Unconditionally mark the given object, and unconditinally count + // the object in the counting structures for worker id 0. + // Should *not* be called from parallel code. + inline bool mark_and_count(oop obj, HeapRegion* hr); + + // Similar to the above routine but we don't know the heap region that + // contains the object to be marked/counted, which this routine looks up. + // Should *not* be called from parallel code. + inline bool mark_and_count(oop obj); + +protected: + // Clear all the per-task bitmaps and arrays used to store the + // counting data. + void clear_all_count_data(); + + // Aggregates the counting data for each worker/task + // that was constructed while marking. Also sets + // the amount of marked bytes for each region and + // the top at concurrent mark count. + void aggregate_count_data(); + + // Verification routine + void verify_count_data(); }; // A class representing a marking task. @@ -1031,6 +1148,12 @@ private: TruncatedSeq _marking_step_diffs_ms; + // Counting data structures. Embedding the task's marked_bytes_array + // and card bitmap into the actual task saves having to go through + // the ConcurrentMark object. + size_t* _marked_bytes_array; + BitMap* _card_bm; + // LOTS of statistics related with this task #if _MARKING_STATS_ NumberSeq _all_clock_intervals_ms; @@ -1196,6 +1319,7 @@ public: } CMTask(int task_num, ConcurrentMark *cm, + size_t* marked_bytes, BitMap* card_bm, CMTaskQueue* task_queue, CMTaskQueueSet* task_queues); // it prints statistics associated with this task diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp index fde69c4ab32..84a0af566be 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp @@ -28,6 +28,159 @@ #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +// Returns the index in the liveness accounting card bitmap +// for the given address +inline BitMap::idx_t ConcurrentMark::card_bitmap_index_for(HeapWord* addr) { + // Below, the term "card num" means the result of shifting an address + // by the card shift -- address 0 corresponds to card number 0. One + // must subtract the card num of the bottom of the heap to obtain a + // card table index. + + intptr_t card_num = intptr_t(uintptr_t(addr) >> CardTableModRefBS::card_shift); + return card_num - heap_bottom_card_num(); +} + +// Counts the given memory region in the given task/worker +// counting data structures. +inline void ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, + size_t* marked_bytes_array, + BitMap* task_card_bm) { + G1CollectedHeap* g1h = _g1h; + HeapWord* start = mr.start(); + HeapWord* last = mr.last(); + size_t region_size_bytes = mr.byte_size(); + size_t index = hr->hrs_index(); + + assert(!hr->continuesHumongous(), "should not be HC region"); + assert(hr == g1h->heap_region_containing(start), "sanity"); + assert(hr == g1h->heap_region_containing(mr.last()), "sanity"); + assert(marked_bytes_array != NULL, "pre-condition"); + assert(task_card_bm != NULL, "pre-condition"); + + // Add to the task local marked bytes for this region. + marked_bytes_array[index] += region_size_bytes; + + BitMap::idx_t start_idx = card_bitmap_index_for(start); + BitMap::idx_t last_idx = card_bitmap_index_for(last); + + // The card bitmap is task/worker specific => no need to use 'par' routines. + // Set bits in the inclusive bit range [start_idx, last_idx]. + // + // For small ranges use a simple loop; otherwise use set_range + // The range are the cards that are spanned by the object/region + // so 8 cards will allow objects/regions up to 4K to be handled + // using the loop. + if ((last_idx - start_idx) <= 8) { + for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) { + task_card_bm->set_bit(i); + } + } else { + assert(last_idx < task_card_bm->size(), "sanity"); + // Note: BitMap::set_range() is exclusive. + task_card_bm->set_range(start_idx, last_idx+1); + } +} + +// Counts the given memory region, which may be a single object, in the +// task/worker counting data structures for the given worker id. +inline void ConcurrentMark::count_region(MemRegion mr, uint worker_id) { + size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); + BitMap* task_card_bm = count_card_bitmap_for(worker_id); + HeapWord* addr = mr.start(); + HeapRegion* hr = _g1h->heap_region_containing_raw(addr); + count_region(mr, hr, marked_bytes_array, task_card_bm); +} + +// Counts the given object in the given task/worker counting data structures. +inline void ConcurrentMark::count_object(oop obj, + HeapRegion* hr, + size_t* marked_bytes_array, + BitMap* task_card_bm) { + MemRegion mr((HeapWord*)obj, obj->size()); + count_region(mr, hr, marked_bytes_array, task_card_bm); +} + +// Counts the given object in the task/worker counting data +// structures for the given worker id. +inline void ConcurrentMark::count_object(oop obj, HeapRegion* hr, uint worker_id) { + size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); + BitMap* task_card_bm = count_card_bitmap_for(worker_id); + HeapWord* addr = (HeapWord*) obj; + count_object(obj, hr, marked_bytes_array, task_card_bm); +} + +// Attempts to mark the given object and, if successful, counts +// the object in the given task/worker counting structures. +inline bool ConcurrentMark::par_mark_and_count(oop obj, + HeapRegion* hr, + size_t* marked_bytes_array, + BitMap* task_card_bm) { + HeapWord* addr = (HeapWord*)obj; + if (_nextMarkBitMap->parMark(addr)) { + // Update the task specific count data for the object. + count_object(obj, hr, marked_bytes_array, task_card_bm); + return true; + } + return false; +} + +// Attempts to mark the given object and, if successful, counts +// the object in the task/worker counting structures for the +// given worker id. +inline bool ConcurrentMark::par_mark_and_count(oop obj, + HeapRegion* hr, + uint worker_id) { + HeapWord* addr = (HeapWord*)obj; + if (_nextMarkBitMap->parMark(addr)) { + // Update the task specific count data for the object. + count_object(obj, hr, worker_id); + return true; + } + return false; +} + +// As above - but we don't know the heap region containing the +// object and so have to supply it. +inline bool ConcurrentMark::par_mark_and_count(oop obj, uint worker_id) { + HeapWord* addr = (HeapWord*)obj; + HeapRegion* hr = _g1h->heap_region_containing_raw(addr); + return par_mark_and_count(obj, hr, worker_id); +} + +// Similar to the above routine but we already know the size, in words, of +// the object that we wish to mark/count +inline bool ConcurrentMark::par_mark_and_count(oop obj, + size_t word_size, + uint worker_id) { + HeapWord* addr = (HeapWord*)obj; + if (_nextMarkBitMap->parMark(addr)) { + // Update the task specific count data for the object. + MemRegion mr(addr, word_size); + count_region(mr, worker_id); + return true; + } + return false; +} + +// Unconditionally mark the given object, and unconditinally count +// the object in the counting structures for worker id 0. +// Should *not* be called from parallel code. +inline bool ConcurrentMark::mark_and_count(oop obj, HeapRegion* hr) { + HeapWord* addr = (HeapWord*)obj; + _nextMarkBitMap->mark(addr); + // Update the task specific count data for the object. + count_object(obj, hr, 0 /* worker_id */); + return true; +} + +// As above - but we don't have the heap region containing the +// object, so we have to supply it. +inline bool ConcurrentMark::mark_and_count(oop obj) { + HeapWord* addr = (HeapWord*)obj; + HeapRegion* hr = _g1h->heap_region_containing_raw(addr); + return mark_and_count(obj, hr); +} + inline bool CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { HeapWord* start_addr = MAX2(startWord(), mr.start()); HeapWord* end_addr = MIN2(endWord(), mr.end()); @@ -113,7 +266,7 @@ inline void CMTask::deal_with_reference(oop obj) { HeapWord* objAddr = (HeapWord*) obj; assert(obj->is_oop_or_null(true /* ignore mark word */), "Error"); - if (_g1h->is_in_g1_reserved(objAddr)) { + if (_g1h->is_in_g1_reserved(objAddr)) { assert(obj != NULL, "null check is implicit"); if (!_nextMarkBitMap->isMarked(objAddr)) { // Only get the containing region if the object is not marked on the @@ -127,9 +280,9 @@ inline void CMTask::deal_with_reference(oop obj) { } // we need to mark it first - if (_nextMarkBitMap->parMark(objAddr)) { + if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) { // No OrderAccess:store_load() is needed. It is implicit in the - // CAS done in parMark(objAddr) above + // CAS done in CMBitMap::parMark() call in the routine above. HeapWord* global_finger = _cm->finger(); #if _CHECK_BOTH_FINGERS_ @@ -189,12 +342,7 @@ inline void ConcurrentMark::markPrev(oop p) { ((CMBitMap*)_prevMarkBitMap)->mark((HeapWord*) p); } -inline void ConcurrentMark::markNext(oop p) { - assert(!_nextMarkBitMap->isMarked((HeapWord*) p), "sanity"); - _nextMarkBitMap->mark((HeapWord*) p); -} - -inline void ConcurrentMark::grayRoot(oop obj, size_t word_size) { +inline void ConcurrentMark::grayRoot(oop obj, size_t word_size, uint worker_id) { HeapWord* addr = (HeapWord*) obj; // Currently we don't do anything with word_size but we will use it @@ -220,7 +368,7 @@ inline void ConcurrentMark::grayRoot(oop obj, size_t word_size) { #endif // ASSERT if (!_nextMarkBitMap->isMarked(addr)) { - _nextMarkBitMap->parMark(addr); + par_mark_and_count(obj, word_size, worker_id); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp index e6d3c70b3c0..bf1cd89e85e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,9 +44,7 @@ ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) : _started(false), _in_progress(false), _vtime_accum(0.0), - _vtime_mark_accum(0.0), - _vtime_count_accum(0.0) -{ + _vtime_mark_accum(0.0) { create_and_start(); } @@ -148,36 +146,12 @@ void ConcurrentMarkThread::run() { } } while (cm()->restart_for_overflow()); - double counting_start_time = os::elapsedVTime(); - if (!cm()->has_aborted()) { - double count_start_sec = os::elapsedTime(); - if (PrintGC) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print_cr("[GC concurrent-count-start]"); - } - - _sts.join(); - _cm->calcDesiredRegions(); - _sts.leave(); - - if (!cm()->has_aborted()) { - double count_end_sec = os::elapsedTime(); - if (PrintGC) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print_cr("[GC concurrent-count-end, %1.7lf]", - count_end_sec - count_start_sec); - } - } - } - double end_time = os::elapsedVTime(); - _vtime_count_accum += (end_time - counting_start_time); // Update the total virtual time before doing this, since it will try // to measure it to get the vtime for this marking. We purposely // neglect the presumably-short "completeCleanup" phase here. _vtime_accum = (end_time - _vtime_start); + if (!cm()->has_aborted()) { if (g1_policy->adaptive_young_list_length()) { double now = os::elapsedTime(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp index 84bdb590ea2..5f3d9ee451a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,6 @@ class ConcurrentMarkThread: public ConcurrentGCThread { double _vtime_accum; // Accumulated virtual time. double _vtime_mark_accum; - double _vtime_count_accum; public: virtual void run(); @@ -69,8 +68,6 @@ class ConcurrentMarkThread: public ConcurrentGCThread { double vtime_accum(); // Marking virtual time so far double vtime_mark_accum(); - // Counting virtual time so far. - double vtime_count_accum() { return _vtime_count_accum; } ConcurrentMark* cm() { return _cm; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index bbe89aa5876..dfda7ab2ed5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4200,7 +4200,7 @@ HeapWord* G1CollectedHeap::par_allocate_during_gc(GCAllocPurpose purpose, G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) : ParGCAllocBuffer(gclab_word_size), _retired(false) { } -G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num) +G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num) : _g1h(g1h), _refs(g1h->task_queue(queue_num)), _dcq(&g1h->dirty_card_queue_set()), @@ -4321,6 +4321,7 @@ G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), _par_scan_state(par_scan_state), + _worker_id(par_scan_state->queue_num()), _during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()), _mark_in_progress(_g1->mark_in_progress()) { } @@ -4332,7 +4333,7 @@ void G1ParCopyHelper::mark_object(oop obj) { #endif // ASSERT // We know that the object is not moving so it's safe to read its size. - _cm->grayRoot(obj, (size_t) obj->size()); + _cm->grayRoot(obj, (size_t) obj->size(), _worker_id); } void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { @@ -4354,7 +4355,7 @@ void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { // worker so we cannot trust that its to-space image is // well-formed. So we have to read its size from its from-space // image which we know should not be changing. - _cm->grayRoot(to_obj, (size_t) from_obj->size()); + _cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id); } oop G1ParCopyHelper::copy_to_survivor_space(oop old) { @@ -4444,6 +4445,8 @@ void G1ParCopyClosure assert(barrier != G1BarrierRS || obj != NULL, "Precondition: G1BarrierRS implies obj is non-NULL"); + assert(_worker_id == _par_scan_state->queue_num(), "sanity"); + // here the null check is implicit in the cset_fast_test() test if (_g1->in_cset_fast_test(obj)) { oop forwardee; @@ -4462,7 +4465,7 @@ void G1ParCopyClosure // When scanning the RS, we only care about objs in CS. if (barrier == G1BarrierRS) { - _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); + _par_scan_state->update_rs(_from, p, _worker_id); } } else { // The object is not in collection set. If we're a root scanning @@ -4474,7 +4477,7 @@ void G1ParCopyClosure } if (barrier == G1BarrierEvac && obj != NULL) { - _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); + _par_scan_state->update_rs(_from, p, _worker_id); } if (do_gen_barrier && obj != NULL) { @@ -5704,16 +5707,6 @@ void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) { // And the region is empty. assert(!used_mr.is_empty(), "Should not have empty regions in a CS."); - - // If marking is in progress then clear any objects marked in - // the current region. Note mark_in_progress() returns false, - // even during an initial mark pause, until the set_marking_started() - // call which takes place later in the pause. - if (mark_in_progress()) { - assert(!g1_policy()->during_initial_mark_pause(), "sanity"); - _cm->nextMarkBitMap()->clearRange(used_mr); - } - free_region(cur, &pre_used, &local_free_list, false /* par */); } else { cur->uninstall_surv_rate_group(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 3971535ff2c..10e03431549 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1909,7 +1909,7 @@ protected: G1ParScanPartialArrayClosure* _partial_scan_cl; int _hash_seed; - int _queue_num; + uint _queue_num; size_t _term_attempts; @@ -1953,7 +1953,7 @@ protected: } public: - G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num); + G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num); ~G1ParScanThreadState() { FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base); @@ -2045,7 +2045,7 @@ public: } int* hash_seed() { return &_hash_seed; } - int queue_num() { return _queue_num; } + uint queue_num() { return _queue_num; } size_t term_attempts() const { return _term_attempts; } void note_term_attempt() { _term_attempts++; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp index 37c30431410..1dd8cc765f5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp @@ -70,16 +70,20 @@ private: OopsInHeapRegionClosure *_update_rset_cl; bool _during_initial_mark; bool _during_conc_mark; + uint _worker_id; + public: RemoveSelfForwardPtrObjClosure(G1CollectedHeap* g1, ConcurrentMark* cm, HeapRegion* hr, OopsInHeapRegionClosure* update_rset_cl, bool during_initial_mark, - bool during_conc_mark) : + bool during_conc_mark, + uint worker_id) : _g1(g1), _cm(cm), _hr(hr), _marked_bytes(0), _update_rset_cl(update_rset_cl), _during_initial_mark(during_initial_mark), - _during_conc_mark(during_conc_mark) { } + _during_conc_mark(during_conc_mark), + _worker_id(worker_id) { } size_t marked_bytes() { return _marked_bytes; } @@ -123,7 +127,7 @@ public: // explicitly and all objects in the CSet are considered // (implicitly) live. So, we won't mark them explicitly and // we'll leave them over NTAMS. - _cm->markNext(obj); + _cm->grayRoot(obj, obj_size, _worker_id); } _marked_bytes += (obj_size * HeapWordSize); obj->set_mark(markOopDesc::prototype()); @@ -155,12 +159,14 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; ConcurrentMark* _cm; OopsInHeapRegionClosure *_update_rset_cl; + uint _worker_id; public: RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h, - OopsInHeapRegionClosure* update_rset_cl) : + OopsInHeapRegionClosure* update_rset_cl, + uint worker_id) : _g1h(g1h), _update_rset_cl(update_rset_cl), - _cm(_g1h->concurrent_mark()) { } + _worker_id(worker_id), _cm(_g1h->concurrent_mark()) { } bool doHeapRegion(HeapRegion *hr) { bool during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause(); @@ -173,7 +179,8 @@ public: if (hr->evacuation_failed()) { RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, _update_rset_cl, during_initial_mark, - during_conc_mark); + during_conc_mark, + _worker_id); MemRegion mr(hr->bottom(), hr->end()); // We'll recreate the prev marking info so we'll first clear @@ -226,7 +233,7 @@ public: update_rset_cl = &immediate_update; } - RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, update_rset_cl); + RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, update_rset_cl, worker_id); HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id); _g1h->collection_set_iterate_from(hr, &rsfp_cl); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index fc28d9611b9..0930d2d4dd8 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -51,6 +51,7 @@ protected: G1RemSet* _g1_rem; ConcurrentMark* _cm; G1ParScanThreadState* _par_scan_state; + uint _worker_id; bool _during_initial_mark; bool _mark_in_progress; public: diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index ad1599c5ab8..a324d5f3516 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -374,7 +374,9 @@ class HeapRegion: public G1OffsetTableContigSpace { ParVerifyClaimValue = 4, RebuildRSClaimValue = 5, CompleteMarkCSetClaimValue = 6, - ParEvacFailureClaimValue = 7 + ParEvacFailureClaimValue = 7, + AggregateCountClaimValue = 8, + VerifyCountClaimValue = 9 }; inline HeapWord* par_allocate_no_bot_updates(size_t word_size) { From 8b5551f1ebd9bbe668e831b12cbc8a9b24c23089 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Thu, 12 Jan 2012 03:39:37 -0800 Subject: [PATCH 29/96] 7106773: 512 bits RSA key cannot work with SHA384 and SHA512 Reviewed-by: weijun --- .../sun/security/pkcs11/P11Cipher.java | 4 +- .../classes/sun/security/pkcs11/P11Key.java | 11 +- .../sun/security/pkcs11/P11RSACipher.java | 6 +- .../sun/security/pkcs11/P11Signature.java | 8 +- .../sun/security/ssl/ClientHandshaker.java | 5 +- .../sun/security/ssl/ServerHandshaker.java | 24 +- .../ssl/SignatureAndHashAlgorithm.java | 91 +++- .../util/DisabledAlgorithmConstraints.java | 40 +- .../classes/sun/security/util/KeyLength.java | 91 ++++ .../classes/sun/security/util/Length.java | 43 ++ .../classes/sun/security/mscapi/Key.java | 9 +- .../sun/security/mscapi/RSACipher.java | 8 +- .../sun/security/mscapi/RSASignature.java | 4 +- .../sun/security/mscapi/ShortRSAKey1024.sh | 85 ++++ .../sun/security/mscapi/ShortRSAKey512.sh | 86 ++++ .../sun/security/mscapi/ShortRSAKey768.sh | 85 ++++ .../security/mscapi/ShortRSAKeyWithinTLS.java | 355 +++++++++++++++ .../security/pkcs11/KeyStore/ClientAuth.java | 25 +- .../security/pkcs11/KeyStore/ClientAuth.sh | 27 +- .../ssl/javax/net/ssl/SSLContextVersion.java | 6 +- .../javax/net/ssl/TLSv12/ShortRSAKey512.java | 414 ++++++++++++++++++ 21 files changed, 1334 insertions(+), 93 deletions(-) create mode 100644 jdk/src/share/classes/sun/security/util/KeyLength.java create mode 100644 jdk/src/share/classes/sun/security/util/Length.java create mode 100644 jdk/test/sun/security/mscapi/ShortRSAKey1024.sh create mode 100644 jdk/test/sun/security/mscapi/ShortRSAKey512.sh create mode 100644 jdk/test/sun/security/mscapi/ShortRSAKey768.sh create mode 100644 jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java create mode 100644 jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java index b6e37882484..8179dc01682 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -870,7 +870,7 @@ final class P11Cipher extends CipherSpi { @Override protected int engineGetKeySize(Key key) throws InvalidKeyException { int n = P11SecretKeyFactory.convertKey - (token, key, keyAlgorithm).keyLength(); + (token, key, keyAlgorithm).length(); return n; } diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java index bbce8982e90..acc35f2a80f 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import sun.security.util.DerValue; +import sun.security.util.Length; /** * Key implementation classes. @@ -61,7 +62,7 @@ import sun.security.util.DerValue; * @author Andreas Sterbenz * @since 1.5 */ -abstract class P11Key implements Key { +abstract class P11Key implements Key, Length { private final static String PUBLIC = "public"; private final static String PRIVATE = "private"; @@ -212,7 +213,11 @@ abstract class P11Key implements Key { return s1; } - int keyLength() { + /** + * Return bit length of the key. + */ + @Override + public int length() { return keyLength; } diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java index d9dc4e77ef7..61cc1b33f7b 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -216,7 +216,7 @@ final class P11RSACipher extends CipherSpi { } else { throw new InvalidKeyException("Unknown key type: " + p11Key); } - int n = (p11Key.keyLength() + 7) >> 3; + int n = (p11Key.length() + 7) >> 3; outputSize = n; buffer = new byte[n]; maxInputSize = ((padType == PAD_PKCS1 && encrypt) ? @@ -495,7 +495,7 @@ final class P11RSACipher extends CipherSpi { // see JCE spec protected int engineGetKeySize(Key key) throws InvalidKeyException { - int n = P11KeyFactory.convertKey(token, key, algorithm).keyLength(); + int n = P11KeyFactory.convertKey(token, key, algorithm).length(); return n; } } diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java b/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java index 009c263895d..70a79e46bdf 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -272,7 +272,7 @@ final class P11Signature extends SignatureSpi { if (keyAlgorithm.equals("DSA")) { signature = new byte[40]; } else { - signature = new byte[(p11Key.keyLength() + 7) >> 3]; + signature = new byte[(p11Key.length() + 7) >> 3]; } if (type == T_UPDATE) { token.p11.C_VerifyFinal(session.id(), signature); @@ -357,7 +357,7 @@ final class P11Signature extends SignatureSpi { if (keyAlgorithm.equals("RSA") && publicKey != p11Key) { int keyLen; if (publicKey instanceof P11Key) { - keyLen = ((P11Key) publicKey).keyLength(); + keyLen = ((P11Key) publicKey).length(); } else { keyLen = ((RSAKey) publicKey).getModulus().bitLength(); } @@ -618,7 +618,7 @@ final class P11Signature extends SignatureSpi { private byte[] pkcs1Pad(byte[] data) { try { - int len = (p11Key.keyLength() + 7) >> 3; + int len = (p11Key.length() + 7) >> 3; RSAPadding padding = RSAPadding.getInstance (RSAPadding.PAD_BLOCKTYPE_1, len); byte[] padded = padding.pad(data); diff --git a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java index fbf23196aba..9ebeb75c5aa 100644 --- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -957,7 +957,8 @@ final class ClientHandshaker extends Handshaker { if (protocolVersion.v >= ProtocolVersion.TLS12.v) { preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm( - peerSupportedSignAlgs, signingKey.getAlgorithm()); + peerSupportedSignAlgs, signingKey.getAlgorithm(), + signingKey); if (preferableSignatureAlgorithm == null) { throw new SSLHandshakeException( diff --git a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java index 125de5f3f50..223494cf700 100644 --- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1024,37 +1024,39 @@ final class ServerHandshaker extends Handshaker { } break; case K_DHE_RSA: + // need RSA certs for authentication + if (setupPrivateKeyAndChain("RSA") == false) { + return false; + } + // get preferable peer signature algorithm for server key exchange if (protocolVersion.v >= ProtocolVersion.TLS12.v) { preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm( - supportedSignAlgs, "RSA"); + supportedSignAlgs, "RSA", privateKey); if (preferableSignatureAlgorithm == null) { return false; } } - // need RSA certs for authentication - if (setupPrivateKeyAndChain("RSA") == false) { - return false; - } setupEphemeralDHKeys(suite.exportable); break; case K_ECDHE_RSA: + // need RSA certs for authentication + if (setupPrivateKeyAndChain("RSA") == false) { + return false; + } + // get preferable peer signature algorithm for server key exchange if (protocolVersion.v >= ProtocolVersion.TLS12.v) { preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm( - supportedSignAlgs, "RSA"); + supportedSignAlgs, "RSA", privateKey); if (preferableSignatureAlgorithm == null) { return false; } } - // need RSA certs for authentication - if (setupPrivateKeyAndChain("RSA") == false) { - return false; - } if (setupEphemeralECDHKeys() == false) { return false; } diff --git a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java index dad0781aaf8..d1bc65393bb 100644 --- a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java +++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package sun.security.ssl; import java.security.AlgorithmConstraints; import java.security.CryptoPrimitive; +import java.security.PrivateKey; import java.util.Set; import java.util.HashSet; @@ -37,6 +38,8 @@ import java.util.Collection; import java.util.Collections; import java.util.ArrayList; +import sun.security.util.KeyLength; + /** * Signature and hash algorithm. * @@ -231,6 +234,14 @@ final class SignatureAndHashAlgorithm { static SignatureAndHashAlgorithm getPreferableAlgorithm( Collection algorithms, String expected) { + return SignatureAndHashAlgorithm.getPreferableAlgorithm( + algorithms, expected, null); + } + + static SignatureAndHashAlgorithm getPreferableAlgorithm( + Collection algorithms, + String expected, PrivateKey signingKey) { + if (expected == null && !algorithms.isEmpty()) { for (SignatureAndHashAlgorithm sigAlg : algorithms) { if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) { @@ -241,17 +252,58 @@ final class SignatureAndHashAlgorithm { return null; // no supported algorithm } + if (expected == null ) { + return null; // no expected algorithm, no supported algorithm + } + + /* + * Need to check RSA key length to match the length of hash value + */ + int maxDigestLength = Integer.MAX_VALUE; + if (signingKey != null && + "rsa".equalsIgnoreCase(signingKey.getAlgorithm()) && + expected.equalsIgnoreCase("rsa")) { + /* + * RSA keys of 512 bits have been shown to be practically + * breakable, it does not make much sense to use the strong + * hash algorithm for keys whose key size less than 512 bits. + * So it is not necessary to caculate the required max digest + * length exactly. + * + * If key size is greater than or equals to 768, there is no max + * digest length limitation in currect implementation. + * + * If key size is greater than or equals to 512, but less than + * 768, the digest length should be less than or equal to 32 bytes. + * + * If key size is less than 512, the digest length should be + * less than or equal to 20 bytes. + */ + int keySize = KeyLength.getKeySize(signingKey); + if (keySize >= 768) { + maxDigestLength = HashAlgorithm.SHA512.length; + } else if ((keySize >= 512) && (keySize < 768)) { + maxDigestLength = HashAlgorithm.SHA256.length; + } else if ((keySize > 0) && (keySize < 512)) { + maxDigestLength = HashAlgorithm.SHA1.length; + } // Otherwise, cannot determine the key size, prefer the most + // perferable hash algorithm. + } for (SignatureAndHashAlgorithm algorithm : algorithms) { int signValue = algorithm.id & 0xFF; - if ((expected.equalsIgnoreCase("dsa") && - signValue == SignatureAlgorithm.DSA.value) || - (expected.equalsIgnoreCase("rsa") && - signValue == SignatureAlgorithm.RSA.value) || - (expected.equalsIgnoreCase("ecdsa") && - signValue == SignatureAlgorithm.ECDSA.value) || - (expected.equalsIgnoreCase("ec") && - signValue == SignatureAlgorithm.ECDSA.value)) { + if (expected.equalsIgnoreCase("rsa") && + signValue == SignatureAlgorithm.RSA.value) { + if (algorithm.hash.length <= maxDigestLength) { + return algorithm; + } + } else if ( + (expected.equalsIgnoreCase("dsa") && + signValue == SignatureAlgorithm.DSA.value) || + (expected.equalsIgnoreCase("ecdsa") && + signValue == SignatureAlgorithm.ECDSA.value) || + (expected.equalsIgnoreCase("ec") && + signValue == SignatureAlgorithm.ECDSA.value)) { return algorithm; } } @@ -260,25 +312,28 @@ final class SignatureAndHashAlgorithm { } static enum HashAlgorithm { - UNDEFINED("undefined", "", -1), - NONE( "none", "NONE", 0), - MD5( "md5", "MD5", 1), - SHA1( "sha1", "SHA-1", 2), - SHA224( "sha224", "SHA-224", 3), - SHA256( "sha256", "SHA-256", 4), - SHA384( "sha384", "SHA-384", 5), - SHA512( "sha512", "SHA-512", 6); + UNDEFINED("undefined", "", -1, -1), + NONE( "none", "NONE", 0, -1), + MD5( "md5", "MD5", 1, 16), + SHA1( "sha1", "SHA-1", 2, 20), + SHA224( "sha224", "SHA-224", 3, 28), + SHA256( "sha256", "SHA-256", 4, 32), + SHA384( "sha384", "SHA-384", 5, 48), + SHA512( "sha512", "SHA-512", 6, 64); final String name; // not the standard signature algorithm name // except the UNDEFINED, other names are defined // by TLS 1.2 protocol final String standardName; // the standard MessageDigest algorithm name final int value; + final int length; // digest length in bytes, -1 means not applicable - private HashAlgorithm(String name, String standardName, int value) { + private HashAlgorithm(String name, String standardName, + int value, int length) { this.name = name; this.standardName = standardName; this.value = value; + this.length = length; } static HashAlgorithm valueOf(int value) { diff --git a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index a537c554854..103c3d4b463 100644 --- a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,11 +33,6 @@ import java.security.Key; import java.security.Security; import java.security.PrivilegedAction; import java.security.AccessController; -import java.security.interfaces.ECKey; -import java.security.interfaces.RSAKey; -import java.security.interfaces.DSAKey; -import javax.crypto.SecretKey; -import javax.crypto.interfaces.DHKey; import java.util.Locale; import java.util.Set; @@ -443,40 +438,15 @@ public class DisabledAlgorithmConstraints implements AlgorithmConstraints { // Does this key constraint disable the specified key? public boolean disables(Key key) { - int size = -1; - - // it is a SecretKey - if (key instanceof SecretKey) { - SecretKey sk = (SecretKey)key; - if (sk.getFormat().equals("RAW") && sk.getEncoded() != null) { - size = sk.getEncoded().length * 8; - - } - } - - // it is an asymmetric key - if (key instanceof RSAKey) { - RSAKey pubk = (RSAKey)key; - size = pubk.getModulus().bitLength(); - } else if (key instanceof ECKey) { - ECKey pubk = (ECKey)key; - size = pubk.getParams().getOrder().bitLength(); - } else if (key instanceof DSAKey) { - DSAKey pubk = (DSAKey)key; - size = pubk.getParams().getP().bitLength(); - } else if (key instanceof DHKey) { - DHKey pubk = (DHKey)key; - size = pubk.getParams().getP().bitLength(); - } // else, it is not a key we know. + int size = KeyLength.getKeySize(key); if (size == 0) { return true; // we don't allow any key of size 0. - } - - if (size >= 0) { + } else if (size > 0) { return ((size < minSize) || (size > maxSize) || (prohibitedSize == size)); - } + } // Otherwise, the key size is not accessible. Conservatively, + // please don't disable such keys. return false; } diff --git a/jdk/src/share/classes/sun/security/util/KeyLength.java b/jdk/src/share/classes/sun/security/util/KeyLength.java new file mode 100644 index 00000000000..3ffbac3f30f --- /dev/null +++ b/jdk/src/share/classes/sun/security/util/KeyLength.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +import java.security.Key; +import java.security.PrivilegedAction; +import java.security.AccessController; +import java.security.interfaces.ECKey; +import java.security.interfaces.RSAKey; +import java.security.interfaces.DSAKey; +import javax.crypto.SecretKey; +import javax.crypto.interfaces.DHKey; + +/** + * A utility class to get key length + */ +public final class KeyLength { + + /** + * Returns the key size of the given key object in bits. + * + * @param key the key object, cannot be null + * @return the key size of the given key object in bits, or -1 if the + * key size is not accessible + */ + final public static int getKeySize(Key key) { + int size = -1; + + if (key instanceof Length) { + try { + Length ruler = (Length)key; + size = ruler.length(); + } catch (UnsupportedOperationException usoe) { + // ignore the exception + } + + if (size >= 0) { + return size; + } + } + + // try to parse the length from key specification + if (key instanceof SecretKey) { + SecretKey sk = (SecretKey)key; + String format = sk.getFormat(); + if ("RAW".equals(format) && sk.getEncoded() != null) { + size = (sk.getEncoded().length * 8); + } // Otherwise, it may be a unextractable key of PKCS#11, or + // a key we are not able to handle. + } else if (key instanceof RSAKey) { + RSAKey pubk = (RSAKey)key; + size = pubk.getModulus().bitLength(); + } else if (key instanceof ECKey) { + ECKey pubk = (ECKey)key; + size = pubk.getParams().getOrder().bitLength(); + } else if (key instanceof DSAKey) { + DSAKey pubk = (DSAKey)key; + size = pubk.getParams().getP().bitLength(); + } else if (key instanceof DHKey) { + DHKey pubk = (DHKey)key; + size = pubk.getParams().getP().bitLength(); + } // Otherwise, it may be a unextractable key of PKCS#11, or + // a key we are not able to handle. + + return size; + } +} + diff --git a/jdk/src/share/classes/sun/security/util/Length.java b/jdk/src/share/classes/sun/security/util/Length.java new file mode 100644 index 00000000000..1207e577f41 --- /dev/null +++ b/jdk/src/share/classes/sun/security/util/Length.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +/** + * The Length interface defines the length of an object + */ +public interface Length { + + /** + * Gets the length of this object + *

    + * Note that if a class of java.security.Key implements this interfaces, + * the length should be measured in bits. + * + * @return the length of this object + * @throws UnsupportedOperationException if the operation is not supported + */ + public int length(); +} diff --git a/jdk/src/windows/classes/sun/security/mscapi/Key.java b/jdk/src/windows/classes/sun/security/mscapi/Key.java index 9a548bf8b40..6fa195acfed 100644 --- a/jdk/src/windows/classes/sun/security/mscapi/Key.java +++ b/jdk/src/windows/classes/sun/security/mscapi/Key.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package sun.security.mscapi; +import sun.security.util.Length; + /** * The handle for an RSA or DSA key using the Microsoft Crypto API. * @@ -35,7 +37,7 @@ package sun.security.mscapi; * @since 1.6 * @author Stanley Man-Kit Ho */ -abstract class Key implements java.security.Key +abstract class Key implements java.security.Key, Length { // Native handle @@ -81,7 +83,8 @@ abstract class Key implements java.security.Key /** * Return bit length of the key. */ - public int bitLength() + @Override + public int length() { return keyLength; } diff --git a/jdk/src/windows/classes/sun/security/mscapi/RSACipher.java b/jdk/src/windows/classes/sun/security/mscapi/RSACipher.java index 4b146539caf..7ab29629a18 100644 --- a/jdk/src/windows/classes/sun/security/mscapi/RSACipher.java +++ b/jdk/src/windows/classes/sun/security/mscapi/RSACipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -235,12 +235,12 @@ public final class RSACipher extends CipherSpi { mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY; publicKey = (sun.security.mscapi.Key)key; privateKey = null; - outputSize = publicKey.bitLength() / 8; + outputSize = publicKey.length() / 8; } else if (key instanceof PrivateKey) { mode = encrypt ? MODE_SIGN : MODE_DECRYPT; privateKey = (sun.security.mscapi.Key)key; publicKey = null; - outputSize = privateKey.bitLength() / 8; + outputSize = privateKey.length() / 8; } else { throw new InvalidKeyException("Unknown key type: " + key); } @@ -395,7 +395,7 @@ public final class RSACipher extends CipherSpi { protected int engineGetKeySize(Key key) throws InvalidKeyException { if (key instanceof sun.security.mscapi.Key) { - return ((sun.security.mscapi.Key) key).bitLength(); + return ((sun.security.mscapi.Key) key).length(); } else if (key instanceof RSAKey) { return ((RSAKey) key).getModulus().bitLength(); diff --git a/jdk/src/windows/classes/sun/security/mscapi/RSASignature.java b/jdk/src/windows/classes/sun/security/mscapi/RSASignature.java index 3154173dbfd..488c2365b00 100644 --- a/jdk/src/windows/classes/sun/security/mscapi/RSASignature.java +++ b/jdk/src/windows/classes/sun/security/mscapi/RSASignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -290,7 +290,7 @@ abstract class RSASignature extends java.security.SignatureSpi // Check against the local and global values to make sure // the sizes are ok. Round up to nearest byte. - RSAKeyFactory.checkKeyLengths(((privateKey.bitLength() + 7) & ~7), + RSAKeyFactory.checkKeyLengths(((privateKey.length() + 7) & ~7), null, RSAKeyPairGenerator.KEY_SIZE_MIN, RSAKeyPairGenerator.KEY_SIZE_MAX); diff --git a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh new file mode 100644 index 00000000000..b446143ecb1 --- /dev/null +++ b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh @@ -0,0 +1,85 @@ +#!/bin/sh + +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + + +# @test +# @bug 7106773 +# @summary 512 bits RSA key cannot work with SHA384 and SHA512 +# @run shell ShortRSAKey1024.sh + +# set a few environment variables so that the shell-script can run stand-alone +# in the source directory +if [ "${TESTSRC}" = "" ] ; then + TESTSRC="." +fi + +if [ "${TESTCLASSES}" = "" ] ; then + TESTCLASSES="." +fi + +if [ "${TESTJAVA}" = "" ] ; then + echo "TESTJAVA not set. Test cannot execute." + echo "FAILED!!!" + exit 1 +fi + +OS=`uname -s` +case "$OS" in + Windows* | CYGWIN* ) + + echo "Creating a temporary RSA keypair in the Windows-My store..." + ${TESTJAVA}/bin/keytool \ + -genkeypair \ + -storetype Windows-My \ + -keyalg RSA \ + -alias 7106773.1024 \ + -keysize 1024 \ + -dname "cn=localhost,c=US" \ + -noprompt + + echo + echo "Running the test..." + ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\ShortRSAKeyWithinTLS.java + ${TESTJAVA}/bin/java ShortRSAKeyWithinTLS 7106773.1024 1024 \ + TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA + + rc=$? + + echo + echo "Removing the temporary RSA keypair from the Windows-My store..." + ${TESTJAVA}/bin/keytool \ + -delete \ + -storetype Windows-My \ + -alias 7106773.1024 + + echo done. + exit $rc + ;; + + * ) + echo "This test is not intended for '$OS' - passing test" + exit 0 + ;; +esac diff --git a/jdk/test/sun/security/mscapi/ShortRSAKey512.sh b/jdk/test/sun/security/mscapi/ShortRSAKey512.sh new file mode 100644 index 00000000000..e4cae406383 --- /dev/null +++ b/jdk/test/sun/security/mscapi/ShortRSAKey512.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + + +# @test +# @bug 7106773 +# @summary 512 bits RSA key cannot work with SHA384 and SHA512 +# @run shell ShortRSAKey512.sh + +# set a few environment variables so that the shell-script can run stand-alone +# in the source directory +if [ "${TESTSRC}" = "" ] ; then + TESTSRC="." +fi + +if [ "${TESTCLASSES}" = "" ] ; then + TESTCLASSES="." +fi + +if [ "${TESTJAVA}" = "" ] ; then + echo "TESTJAVA not set. Test cannot execute." + echo "FAILED!!!" + exit 1 +fi + +OS=`uname -s` +case "$OS" in + Windows* | CYGWIN* ) + + echo "Creating a temporary RSA keypair in the Windows-My store..." + ${TESTJAVA}/bin/keytool \ + -genkeypair \ + -storetype Windows-My \ + -keyalg RSA \ + -alias 7106773.512 \ + -keysize 512 \ + -dname "cn=localhost,c=US" \ + -noprompt + + echo + echo "Running the test..." + ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\ShortRSAKeyWithinTLS.java + ${TESTJAVA}/bin/java ShortRSAKeyWithinTLS 7106773.512 512 \ + TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA + + + rc=$? + + echo + echo "Removing the temporary RSA keypair from the Windows-My store..." + ${TESTJAVA}/bin/keytool \ + -delete \ + -storetype Windows-My \ + -alias 7106773.512 + + echo done. + exit $rc + ;; + + * ) + echo "This test is not intended for '$OS' - passing test" + exit 0 + ;; +esac diff --git a/jdk/test/sun/security/mscapi/ShortRSAKey768.sh b/jdk/test/sun/security/mscapi/ShortRSAKey768.sh new file mode 100644 index 00000000000..a81903b818c --- /dev/null +++ b/jdk/test/sun/security/mscapi/ShortRSAKey768.sh @@ -0,0 +1,85 @@ +#!/bin/sh + +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + + +# @test +# @bug 7106773 +# @summary 512 bits RSA key cannot work with SHA384 and SHA512 +# @run shell ShortRSAKey768.sh + +# set a few environment variables so that the shell-script can run stand-alone +# in the source directory +if [ "${TESTSRC}" = "" ] ; then + TESTSRC="." +fi + +if [ "${TESTCLASSES}" = "" ] ; then + TESTCLASSES="." +fi + +if [ "${TESTJAVA}" = "" ] ; then + echo "TESTJAVA not set. Test cannot execute." + echo "FAILED!!!" + exit 1 +fi + +OS=`uname -s` +case "$OS" in + Windows* | CYGWIN* ) + + echo "Creating a temporary RSA keypair in the Windows-My store..." + ${TESTJAVA}/bin/keytool \ + -genkeypair \ + -storetype Windows-My \ + -keyalg RSA \ + -alias 7106773.768 \ + -keysize 768 \ + -dname "cn=localhost,c=US" \ + -noprompt + + echo + echo "Running the test..." + ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\ShortRSAKeyWithinTLS.java + ${TESTJAVA}/bin/java ShortRSAKeyWithinTLS 7106773.768 768 \ + TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA + + rc=$? + + echo + echo "Removing the temporary RSA keypair from the Windows-My store..." + ${TESTJAVA}/bin/keytool \ + -delete \ + -storetype Windows-My \ + -alias 7106773.768 + + echo done. + exit $rc + ;; + + * ) + echo "This test is not intended for '$OS' - passing test" + exit 0 + ;; +esac diff --git a/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java b/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java new file mode 100644 index 00000000000..e4f7eb1a773 --- /dev/null +++ b/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.net.*; +import java.util.*; +import java.security.*; +import javax.net.*; +import javax.net.ssl.*; +import java.lang.reflect.*; + +import sun.security.util.KeyLength; + +public class ShortRSAKeyWithinTLS { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + static boolean separateServerThread = false; + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doServerSide() throws Exception { + + // load the key store + KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); + ks.load(null, null); + System.out.println("Loaded keystore: Windows-MY"); + + // check key size + checkKeySize(ks); + + // initialize the SSLContext + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, null); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ks); + + SSLContext ctx = SSLContext.getInstance("TLS"); + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + ServerSocketFactory ssf = ctx.getServerSocketFactory(); + SSLServerSocket sslServerSocket = (SSLServerSocket) + ssf.createServerSocket(serverPort); + sslServerSocket.setNeedClientAuth(true); + serverPort = sslServerSocket.getLocalPort(); + System.out.println("serverPort = " + serverPort); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + + sslSocket.close(); + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + // load the key store + KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); + ks.load(null, null); + System.out.println("Loaded keystore: Windows-MY"); + + // initialize the SSLContext + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, null); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ks); + + SSLContext ctx = SSLContext.getInstance("TLS"); + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + SSLSocketFactory sslsf = ctx.getSocketFactory(); + SSLSocket sslSocket = (SSLSocket) + sslsf.createSocket("localhost", serverPort); + + if (clientProtocol != null) { + sslSocket.setEnabledProtocols(new String[] {clientProtocol}); + } + + if (clientCiperSuite != null) { + sslSocket.setEnabledCipherSuites(new String[] {clientCiperSuite}); + } + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + + sslSocket.close(); + } + + private void checkKeySize(KeyStore ks) throws Exception { + PrivateKey privateKey = null; + PublicKey publicKey = null; + + if (ks.containsAlias(keyAlias)) { + System.out.println("Loaded entry: " + keyAlias); + privateKey = (PrivateKey)ks.getKey(keyAlias, null); + publicKey = (PublicKey)ks.getCertificate(keyAlias).getPublicKey(); + + int privateKeySize = KeyLength.getKeySize(privateKey); + if (privateKeySize != keySize) { + throw new Exception("Expected key size is " + keySize + + ", but the private key size is " + privateKeySize); + } + + int publicKeySize = KeyLength.getKeySize(publicKey); + if (publicKeySize != keySize) { + throw new Exception("Expected key size is " + keySize + + ", but the public key size is " + publicKeySize); + } + } + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + volatile int serverPort = 0; + + volatile Exception serverException = null; + volatile Exception clientException = null; + + private static String keyAlias; + private static int keySize; + private static String clientProtocol = null; + private static String clientCiperSuite = null; + + private static void parseArguments(String[] args) { + keyAlias = args[0]; + keySize = Integer.parseInt(args[1]); + + if (args.length > 2) { + clientProtocol = args[2]; + } + + if (args.length > 3) { + clientCiperSuite = args[3]; + } + } + + public static void main(String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + // Get the customized arguments. + parseArguments(args); + + new ShortRSAKeyWithinTLS(); + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + ShortRSAKeyWithinTLS() throws Exception { + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + // swallow for now. Show later + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + serverThread.join(); + } else { + clientThread.join(); + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + String whichRemote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + whichRemote = "server"; + } else { + remote = clientException; + local = serverException; + whichRemote = "client"; + } + + /* + * If both failed, return the curthread's exception, but also + * print the remote side Exception + */ + if ((local != null) && (remote != null)) { + System.out.println(whichRemote + " also threw:"); + remote.printStackTrace(); + System.out.println(); + throw local; + } + + if (remote != null) { + throw remote; + } + + if (local != null) { + throw local; + } + } + + void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} + diff --git a/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.java b/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.java index 734bd74c5d5..b1174cd1522 100644 --- a/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.java +++ b/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -155,6 +155,14 @@ public class ClientAuth extends PKCS11Test { SSLSocket sslSocket = (SSLSocket) sslsf.createSocket("localhost", serverPort); + if (clientProtocol != null) { + sslSocket.setEnabledProtocols(new String[] {clientProtocol}); + } + + if (clientCiperSuite != null) { + sslSocket.setEnabledCipherSuites(new String[] {clientCiperSuite}); + } + InputStream sslIS = sslSocket.getInputStream(); OutputStream sslOS = sslSocket.getOutputStream(); @@ -176,7 +184,22 @@ public class ClientAuth extends PKCS11Test { volatile Exception serverException = null; volatile Exception clientException = null; + private static String clientProtocol = null; + private static String clientCiperSuite = null; + + private static void parseArguments(String[] args) { + if (args.length > 0) { + clientProtocol = args[0]; + } + + if (args.length > 1) { + clientCiperSuite = args[1]; + } + } + public static void main(String[] args) throws Exception { + // Get the customized arguments. + parseArguments(args); main(new ClientAuth()); } diff --git a/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh b/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh index eda8177e43c..0593ddf144c 100644 --- a/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh +++ b/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,9 @@ # # @test -# @bug 4938185 +# @bug 4938185 7106773 # @summary KeyStore support for NSS cert/key databases +# 512 bits RSA key cannot work with SHA384 and SHA512 # # @run shell ClientAuth.sh @@ -126,6 +127,7 @@ ${TESTJAVA}${FS}bin${FS}javac \ ${TESTSRC}${FS}ClientAuth.java # run test +echo "Run ClientAuth ..." ${TESTJAVA}${FS}bin${FS}java \ -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \ -DDIR=${TESTSRC}${FS}ClientAuthData${FS} \ @@ -140,5 +142,26 @@ ${TESTJAVA}${FS}bin${FS}java \ # save error status status=$? +# return if failed +if [ "${status}" != "0" ] ; then + exit $status +fi + +# run test with specified TLS protocol and cipher suite +echo "Run ClientAuth TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA" +${TESTJAVA}${FS}bin${FS}java \ + -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \ + -DDIR=${TESTSRC}${FS}ClientAuthData${FS} \ + -DCUSTOM_DB_DIR=${TESTCLASSES} \ + -DCUSTOM_P11_CONFIG=${TESTSRC}${FS}ClientAuthData${FS}p11-nss.txt \ + -DNO_DEFAULT=true \ + -DNO_DEIMOS=true \ + -Dtest.src=${TESTSRC} \ + -Dtest.classes=${TESTCLASSES} \ + ClientAuth TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA + +# save error status +status=$? + # return exit $status diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/SSLContextVersion.java b/jdk/test/sun/security/ssl/javax/net/ssl/SSLContextVersion.java index 2480b2f0c9e..003c3ab17da 100644 --- a/jdk/test/sun/security/ssl/javax/net/ssl/SSLContextVersion.java +++ b/jdk/test/sun/security/ssl/javax/net/ssl/SSLContextVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,7 +91,7 @@ public class SSLContextVersion { ciphers = parameters.getCipherSuites(); if (protocols.length == 0 || ciphers.length == 0) { - throw new Exception("No default protocols or cipher suites"); + throw new Exception("No supported protocols or cipher suites"); } isMatch = false; @@ -104,7 +104,7 @@ public class SSLContextVersion { } if (!isMatch) { - throw new Exception("No matched default protocol"); + throw new Exception("No matched supported protocol"); } System.out.println("\t... Success"); } diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java new file mode 100644 index 00000000000..a3fb2b0cb15 --- /dev/null +++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7106773 + * @summary 512 bits RSA key cannot work with SHA384 and SHA512 + * + * SunJSSE does not support dynamic system properties, no way to re-use + * system properties in samevm/agentvm mode. + * @run main/othervm ShortRSAKey512 PKIX + * @run main/othervm ShortRSAKey512 SunX509 + */ + +import java.net.*; +import java.util.*; +import java.io.*; +import javax.net.ssl.*; +import java.security.KeyStore; +import java.security.KeyFactory; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.*; +import java.security.interfaces.*; +import sun.misc.BASE64Decoder; + + +public class ShortRSAKey512 { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + static boolean separateServerThread = false; + + /* + * Where do we find the keystores? + */ + // Certificates and key used in the test. + static String trustedCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTEwODE5MDE1MjE5WhcNMzIwNzI5MDE1MjE5WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + + "KoZIhvcNAQEBBQADgY0AMIGJAoGBAM8orG08DtF98TMSscjGsidd1ZoN4jiDpi8U\n" + + "ICz+9dMm1qM1d7O2T+KH3/mxyox7Rc2ZVSCaUD0a3CkhPMnlAx8V4u0H+E9sqso6\n" + + "iDW3JpOyzMExvZiRgRG/3nvp55RMIUV4vEHOZ1QbhuqG4ebN0Vz2DkRft7+flthf\n" + + "vDld6f5JAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLl81dnfp0wDrv0OJ1sxlWzH83Xh\n" + + "MGMGA1UdIwRcMFqAFLl81dnfp0wDrv0OJ1sxlWzH83XhoT+kPTA7MQswCQYDVQQG\n" + + "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + + "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" + + "BQADgYEALlgaH1gWtoBZ84EW8Hu6YtGLQ/L9zIFmHonUPZwn3Pr//icR9Sqhc3/l\n" + + "pVTxOINuFHLRz4BBtEylzRIOPzK3tg8XwuLb1zd0db90x3KBCiAL6E6cklGEPwLe\n" + + "XYMHDn9eDsaq861Tzn6ZwzMgw04zotPMoZN0mVd/3Qca8UJFucE=\n" + + "-----END CERTIFICATE-----"; + + static String targetCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICNDCCAZ2gAwIBAgIBDDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTExMTA3MTM1NTUyWhcNMzEwNzI1MTM1NTUyWjBPMQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" + + "BAMTCWxvY2FsaG9zdDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC3Pb49OSPfOD2G\n" + + "HSXFCFx1GJEZfqG9ZUf7xuIi/ra5dLjPGAaoY5QF2QOa8VnOriQCXDfyXHxsuRnE\n" + + "OomxL7EVAgMBAAGjeDB2MAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUXNCJK3/dtCIc\n" + + "xb+zlA/JINlvs/MwHwYDVR0jBBgwFoAUuXzV2d+nTAOu/Q4nWzGVbMfzdeEwJwYD\n" + + "VR0lBCAwHgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAzANBgkqhkiG9w0B\n" + + "AQQFAAOBgQB2qIDUxA2caMPpGtUACZAPRUtrGssCINIfItETXJZCx/cRuZ5sP4D9\n" + + "N1acoNDn0hCULe3lhXAeTC9NZ97680yJzregQMV5wATjo1FGsKY30Ma+sc/nfzQW\n" + + "+h/7RhYtoG0OTsiaDCvyhI6swkNJzSzrAccPY4+ZgU8HiDLzZTmM3Q==\n" + + "-----END CERTIFICATE-----"; + + // Private key in the format of PKCS#8, key size is 512 bits. + static String targetPrivateKey = + "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAtz2+PTkj3zg9hh0l\n" + + "xQhcdRiRGX6hvWVH+8biIv62uXS4zxgGqGOUBdkDmvFZzq4kAlw38lx8bLkZxDqJ\n" + + "sS+xFQIDAQABAkByx/5Oo2hQ/w2q4L8z+NTRlJ3vdl8iIDtC/4XPnfYfnGptnpG6\n" + + "ZThQRvbMZiai0xHQPQMszvAHjZVme1eDl3EBAiEA3aKJHynPVCEJhpfCLWuMwX5J\n" + + "1LntwJO7NTOyU5m8rPECIQDTpzn5X44r2rzWBDna/Sx7HW9IWCxNgUD2Eyi2nA7W\n" + + "ZQIgJerEorw4aCAuzQPxiGu57PB6GRamAihEAtoRTBQlH0ECIQDN08FgTtnesgCU\n" + + "DFYLLcw1CiHvc7fZw4neBDHCrC8NtQIgA8TOUkGnpCZlQ0KaI8KfKWI+vxFcgFnH\n" + + "3fnqsTgaUs4="; + + static char passphrase[] = "passphrase".toCharArray(); + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doServerSide() throws Exception { + SSLContext context = generateSSLContext(null, targetCertStr, + targetPrivateKey); + SSLServerSocketFactory sslssf = context.getServerSocketFactory(); + SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(serverPort); + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept(); + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write('A'); + sslOS.flush(); + + sslSocket.close(); + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLContext context = generateSSLContext(trustedCertStr, null, null); + SSLSocketFactory sslsf = context.getSocketFactory(); + + SSLSocket sslSocket = + (SSLSocket)sslsf.createSocket("localhost", serverPort); + + // enable TLSv1.2 only + sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"}); + + // enable a block cipher + sslSocket.setEnabledCipherSuites( + new String[] {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"}); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write('B'); + sslOS.flush(); + sslIS.read(); + + sslSocket.close(); + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + private static String tmAlgorithm; // trust manager + + private static void parseArguments(String[] args) { + tmAlgorithm = args[0]; + } + + private static SSLContext generateSSLContext(String trustedCertStr, + String keyCertStr, String keySpecStr) throws Exception { + + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + // create a key store + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(null, null); + + // import the trused cert + Certificate trusedCert = null; + ByteArrayInputStream is = null; + if (trustedCertStr != null) { + is = new ByteArrayInputStream(trustedCertStr.getBytes()); + trusedCert = cf.generateCertificate(is); + is.close(); + + ks.setCertificateEntry("RSA Export Signer", trusedCert); + } + + if (keyCertStr != null) { + // generate the private key. + PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( + new BASE64Decoder().decodeBuffer(keySpecStr)); + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKey priKey = + (RSAPrivateKey)kf.generatePrivate(priKeySpec); + + // generate certificate chain + is = new ByteArrayInputStream(keyCertStr.getBytes()); + Certificate keyCert = cf.generateCertificate(is); + is.close(); + + Certificate[] chain = null; + if (trusedCert != null) { + chain = new Certificate[2]; + chain[0] = keyCert; + chain[1] = trusedCert; + } else { + chain = new Certificate[1]; + chain[0] = keyCert; + } + + // import the key entry. + ks.setKeyEntry("Whatever", priKey, passphrase, chain); + } + + // create SSL context + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); + tmf.init(ks); + + SSLContext ctx = SSLContext.getInstance("TLS"); + if (keyCertStr != null && !keyCertStr.isEmpty()) { + KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); + kmf.init(ks, passphrase); + + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + ks = null; + } else { + ctx.init(null, tmf.getTrustManagers(), null); + } + + return ctx; + } + + + // use any free port by default + volatile int serverPort = 0; + + volatile Exception serverException = null; + volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + if (debug) + System.setProperty("javax.net.debug", "all"); + + /* + * Get the customized arguments. + */ + parseArguments(args); + + /* + * Start the tests. + */ + new ShortRSAKey512(); + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + ShortRSAKey512() throws Exception { + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + // swallow for now. Show later + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + serverThread.join(); + } else { + clientThread.join(); + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + String whichRemote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + whichRemote = "server"; + } else { + remote = clientException; + local = serverException; + whichRemote = "client"; + } + + /* + * If both failed, return the curthread's exception, but also + * print the remote side Exception + */ + if ((local != null) && (remote != null)) { + System.out.println(whichRemote + " also threw:"); + remote.printStackTrace(); + System.out.println(); + throw local; + } + + if (remote != null) { + throw remote; + } + + if (local != null) { + throw local; + } + } + + void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} From 1b000de1866fbf19a2217b1148d548d920fd084e Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Thu, 12 Jan 2012 15:28:34 +0000 Subject: [PATCH 30/96] 7123100: javac fails with java.lang.StackOverflowError Inference of under-constrained type-variables creates erroneous recursive wildcard types Reviewed-by: jjg --- .../classes/com/sun/tools/javac/comp/Infer.java | 14 +++++++++----- .../test/tools/javac/cast/7123100/T7123100a.java | 16 ++++++++++++++++ .../test/tools/javac/cast/7123100/T7123100a.out | 4 ++++ .../test/tools/javac/cast/7123100/T7123100b.java | 12 ++++++++++++ .../test/tools/javac/cast/7123100/T7123100b.out | 4 ++++ .../test/tools/javac/cast/7123100/T7123100c.java | 16 ++++++++++++++++ .../test/tools/javac/cast/7123100/T7123100c.out | 4 ++++ .../test/tools/javac/cast/7123100/T7123100d.java | 16 ++++++++++++++++ .../test/tools/javac/cast/7123100/T7123100d.out | 4 ++++ 9 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 langtools/test/tools/javac/cast/7123100/T7123100a.java create mode 100644 langtools/test/tools/javac/cast/7123100/T7123100a.out create mode 100644 langtools/test/tools/javac/cast/7123100/T7123100b.java create mode 100644 langtools/test/tools/javac/cast/7123100/T7123100b.out create mode 100644 langtools/test/tools/javac/cast/7123100/T7123100c.java create mode 100644 langtools/test/tools/javac/cast/7123100/T7123100c.out create mode 100644 langtools/test/tools/javac/cast/7123100/T7123100d.java create mode 100644 langtools/test/tools/javac/cast/7123100/T7123100d.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java index 00564d9e5f7..17ce35af2c1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -332,25 +332,29 @@ public class Infer { //replace uninferred type-vars targs = types.subst(targs, that.tvars, - instaniateAsUninferredVars(undetvars, that.tvars)); + instantiateAsUninferredVars(undetvars, that.tvars)); } return chk.checkType(warn.pos(), that.inst(targs, types), to); } //where - private List instaniateAsUninferredVars(List undetvars, List tvars) { + private List instantiateAsUninferredVars(List undetvars, List tvars) { + Assert.check(undetvars.length() == tvars.length()); ListBuffer new_targs = ListBuffer.lb(); - //step 1 - create syntethic captured vars + //step 1 - create synthetic captured vars for (Type t : undetvars) { UndetVar uv = (UndetVar)t; Type newArg = new CapturedType(t.tsym.name, t.tsym, uv.inst, syms.botType, null); new_targs = new_targs.append(newArg); } //step 2 - replace synthetic vars in their bounds + List formals = tvars; for (Type t : new_targs.toList()) { CapturedType ct = (CapturedType)t; ct.bound = types.subst(ct.bound, tvars, new_targs.toList()); - WildcardType wt = new WildcardType(ct.bound, BoundKind.EXTENDS, syms.boundClass); + WildcardType wt = new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass); + wt.bound = (TypeVar)formals.head; ct.wildcard = wt; + formals = formals.tail; } return new_targs.toList(); } diff --git a/langtools/test/tools/javac/cast/7123100/T7123100a.java b/langtools/test/tools/javac/cast/7123100/T7123100a.java new file mode 100644 index 00000000000..1fbee2c2cfb --- /dev/null +++ b/langtools/test/tools/javac/cast/7123100/T7123100a.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7123100 + * @summary javac fails with java.lang.StackOverflowError + * @compile/fail/ref=T7123100a.out -Werror -Xlint:unchecked -XDrawDiagnostics T7123100a.java + */ + +class T7123100a { + > E m() { + return null; + } + + void test() { + Z z = (Z)m(); + } +} diff --git a/langtools/test/tools/javac/cast/7123100/T7123100a.out b/langtools/test/tools/javac/cast/7123100/T7123100a.out new file mode 100644 index 00000000000..a816314f5b5 --- /dev/null +++ b/langtools/test/tools/javac/cast/7123100/T7123100a.out @@ -0,0 +1,4 @@ +T7123100a.java:14:19: compiler.warn.prob.found.req: (compiler.misc.unchecked.cast.to.type), compiler.misc.type.captureof: 1, ?, Z +- compiler.err.warnings.and.werror +1 error +1 warning diff --git a/langtools/test/tools/javac/cast/7123100/T7123100b.java b/langtools/test/tools/javac/cast/7123100/T7123100b.java new file mode 100644 index 00000000000..6a96afa270d --- /dev/null +++ b/langtools/test/tools/javac/cast/7123100/T7123100b.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7123100 + * @summary javac fails with java.lang.StackOverflowError + * @compile/fail/ref=T7123100b.out -Werror -Xlint:unchecked -XDrawDiagnostics T7123100b.java + */ + +class T7123100b { + void test(Enum e) { + Z z = (Z)e; + } +} diff --git a/langtools/test/tools/javac/cast/7123100/T7123100b.out b/langtools/test/tools/javac/cast/7123100/T7123100b.out new file mode 100644 index 00000000000..7c3c1d689e5 --- /dev/null +++ b/langtools/test/tools/javac/cast/7123100/T7123100b.out @@ -0,0 +1,4 @@ +T7123100b.java:10:18: compiler.warn.prob.found.req: (compiler.misc.unchecked.cast.to.type), java.lang.Enum, Z +- compiler.err.warnings.and.werror +1 error +1 warning diff --git a/langtools/test/tools/javac/cast/7123100/T7123100c.java b/langtools/test/tools/javac/cast/7123100/T7123100c.java new file mode 100644 index 00000000000..cb8816174dd --- /dev/null +++ b/langtools/test/tools/javac/cast/7123100/T7123100c.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7123100 + * @summary javac fails with java.lang.StackOverflowError + * @compile/fail/ref=T7123100c.out -Werror -Xlint:unchecked -XDrawDiagnostics T7123100c.java + */ + +class T7123100c { + E m(E e) { + return null; + } + + void test(Enum e) { + Z z = (Z)m(e); + } +} diff --git a/langtools/test/tools/javac/cast/7123100/T7123100c.out b/langtools/test/tools/javac/cast/7123100/T7123100c.out new file mode 100644 index 00000000000..9af9357e551 --- /dev/null +++ b/langtools/test/tools/javac/cast/7123100/T7123100c.out @@ -0,0 +1,4 @@ +T7123100c.java:14:19: compiler.warn.prob.found.req: (compiler.misc.unchecked.cast.to.type), java.lang.Enum, Z +- compiler.err.warnings.and.werror +1 error +1 warning diff --git a/langtools/test/tools/javac/cast/7123100/T7123100d.java b/langtools/test/tools/javac/cast/7123100/T7123100d.java new file mode 100644 index 00000000000..90002d3be4b --- /dev/null +++ b/langtools/test/tools/javac/cast/7123100/T7123100d.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7123100 + * @summary javac fails with java.lang.StackOverflowError + * @compile/fail/ref=T7123100d.out -Werror -Xlint:unchecked -XDrawDiagnostics T7123100d.java + */ + +class T7123100d { + > E m(Enum e) { + return null; + } + + void test(Enum e) { + Z z = (Z)m(e); + } +} diff --git a/langtools/test/tools/javac/cast/7123100/T7123100d.out b/langtools/test/tools/javac/cast/7123100/T7123100d.out new file mode 100644 index 00000000000..52a9ce31750 --- /dev/null +++ b/langtools/test/tools/javac/cast/7123100/T7123100d.out @@ -0,0 +1,4 @@ +T7123100d.java:14:19: compiler.warn.prob.found.req: (compiler.misc.unchecked.cast.to.type), compiler.misc.type.captureof: 1, ?, Z +- compiler.err.warnings.and.werror +1 error +1 warning From eafb7ad68ce4df744960b9bb342e9cc6d670a24e Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Thu, 12 Jan 2012 16:04:03 -0800 Subject: [PATCH 31/96] 7088989: Improve the performance for T4 by utilizing the newly provided crypto APIs Added the OracleUcrypto provider for utilizing the Solaris ucrypto API. Reviewed-by: weijun --- jdk/make/com/oracle/Makefile | 27 +- jdk/make/com/oracle/net/Makefile | 40 ++ jdk/make/com/oracle/nio/Makefile | 40 ++ .../com/oracle/security/ucrypto/FILES_c.gmk | 30 ++ jdk/make/com/oracle/security/ucrypto/Makefile | 270 +++++++++++ .../com/oracle/security/ucrypto/mapfile-vers | 69 +++ jdk/make/com/oracle/util/Makefile | 40 ++ .../share/lib/security/java.security-solaris | 21 +- jdk/test/Makefile | 3 +- .../com/oracle/security/ucrypto/TestAES.java | 339 ++++++++++++++ .../oracle/security/ucrypto/TestDigest.java | 127 ++++++ .../com/oracle/security/ucrypto/TestRSA.java | 421 ++++++++++++++++++ .../oracle/security/ucrypto/UcryptoTest.java | 65 +++ .../java/security/Provider/DefaultPKCS11.java | 7 +- 14 files changed, 1477 insertions(+), 22 deletions(-) create mode 100644 jdk/make/com/oracle/net/Makefile create mode 100644 jdk/make/com/oracle/nio/Makefile create mode 100644 jdk/make/com/oracle/security/ucrypto/FILES_c.gmk create mode 100644 jdk/make/com/oracle/security/ucrypto/Makefile create mode 100644 jdk/make/com/oracle/security/ucrypto/mapfile-vers create mode 100644 jdk/make/com/oracle/util/Makefile create mode 100644 jdk/test/com/oracle/security/ucrypto/TestAES.java create mode 100644 jdk/test/com/oracle/security/ucrypto/TestDigest.java create mode 100644 jdk/test/com/oracle/security/ucrypto/TestRSA.java create mode 100644 jdk/test/com/oracle/security/ucrypto/UcryptoTest.java diff --git a/jdk/make/com/oracle/Makefile b/jdk/make/com/oracle/Makefile index e6c6aed61a7..c83cf8026b1 100644 --- a/jdk/make/com/oracle/Makefile +++ b/jdk/make/com/oracle/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,15 +25,24 @@ BUILDDIR = ../.. PRODUCT = oracle +#SUBDIRS_MAKEFLAGS += JAVAC_MAX_WARNINGS=true +#SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true +#SUBDIRS_MAKEFLAGS += JAVAC_LINT_OPTIONS=-Xlint:all,-deprecation,-path include $(BUILDDIR)/common/Defs.gmk -# -# Files to compile -# -AUTO_FILES_JAVA_DIRS = com/oracle +# build com/oracle/security/ucrypto on Solaris platform for non-OpenJDK builds +UCRYPTO = +ifndef OPENJDK + ifeq ($(PLATFORM), solaris) + UCRYPTO = security/ucrypto + endif +endif -# -# Rules -# -include $(BUILDDIR)/common/Classes.gmk + +SUBDIRS = net nio util $(UCRYPTO) + +include $(BUILDDIR)/common/Subdirs.gmk + +all build clean clobber:: + $(SUBDIRS-loop) diff --git a/jdk/make/com/oracle/net/Makefile b/jdk/make/com/oracle/net/Makefile new file mode 100644 index 00000000000..657a35158c6 --- /dev/null +++ b/jdk/make/com/oracle/net/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +BUILDDIR = ../../.. +PACKAGE = com.oracle.net +PRODUCT = oracle +include $(BUILDDIR)/common/Defs.gmk + +# +# Files +# +AUTO_FILES_JAVA_DIRS = com/oracle/net + +# +# Rules +# +include $(BUILDDIR)/common/Classes.gmk + diff --git a/jdk/make/com/oracle/nio/Makefile b/jdk/make/com/oracle/nio/Makefile new file mode 100644 index 00000000000..41d841ab038 --- /dev/null +++ b/jdk/make/com/oracle/nio/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +BUILDDIR = ../../.. +PACKAGE = com.oracle.nio +PRODUCT = oracle +include $(BUILDDIR)/common/Defs.gmk + +# +# Files +# +AUTO_FILES_JAVA_DIRS = com/oracle/nio + +# +# Rules +# +include $(BUILDDIR)/common/Classes.gmk + diff --git a/jdk/make/com/oracle/security/ucrypto/FILES_c.gmk b/jdk/make/com/oracle/security/ucrypto/FILES_c.gmk new file mode 100644 index 00000000000..0c69755c2a3 --- /dev/null +++ b/jdk/make/com/oracle/security/ucrypto/FILES_c.gmk @@ -0,0 +1,30 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +ifndef OPENJDK +FILES_c = \ + nativeFunc.c \ + nativeCrypto.c +endif diff --git a/jdk/make/com/oracle/security/ucrypto/Makefile b/jdk/make/com/oracle/security/ucrypto/Makefile new file mode 100644 index 00000000000..8ea7a749a7b --- /dev/null +++ b/jdk/make/com/oracle/security/ucrypto/Makefile @@ -0,0 +1,270 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# +# Makefile for building ucrypto.jar and its native libraries. +# +# This file was modified from make/sun/security/pkcs11/Makefile. +# +# +# (The terms "OpenJDK" and "JDK" below refer to OpenJDK and Oracle +# JDK builds respectively.) +# +# This Makefile does the "real" build of the Ucrypto provider files. +# Since the sources are unavailable for OpenJDK, this Makefile is only +# useful for JDK. +# +# +# Main Targets (JDK on Solaris): +# +# all The usual, ucrypto.jar plus the native libraries. +# builds and installs the prebuilt/signed jar. +# +# clobber/clean Cleans up the temp directory, ucrypto.jar, the +# native libraries, and the config file from the +# build area +# +# jar Builds, signs and installs ucrypto.jar +# (Can only be done on machines with access to +# the signing keystore) +# +# Other lesser-used Targets (JDK on Solaris): +# +# build-jar Builds ucrypto.jar (no sign/install) +# +# sign Builds/signs ucrypto.jar (no install) +# +# release Builds all targets in preparation +# for workspace integration. +# (Can only be done on machines with access to +# the signing keystore) +# +# install-prebuilt Installs the pre-built jar files +# +# NOTE: None of the above target will update the prebuilt provider binary +# under the closed workspace. To update it, you must explicitly copy the +# binary from either the tmp/signed or lib/ext directory. +# +# This makefile was written to support parallel target execution. +# + +BUILDDIR = ../../../.. + +include $(BUILDDIR)/common/Defs.gmk + +ifndef OPENJDK + ifneq ($(PLATFORM), solaris) + all: + else + PACKAGE = com.oracle.security.ucrypto + LIBRARY = j2ucrypto + PRODUCT = oracle + + # + # The following is for when we need to do postprocessing + # (signing/obfuscation) against a read-only build. If the OUTPUTDIR + # isn't writable, the build currently crashes out. + # + ifdef ALT_JCE_BUILD_DIR + # ===================================================== + # Where to place the output, in case we're building from a read-only + # build area. (e.g. a release engineering build.) + JCE_BUILD_DIR=${ALT_JCE_BUILD_DIR} + IGNORE_WRITABLE_OUTPUTDIR_TEST=true + else + JCE_BUILD_DIR=${TEMPDIR} + endif + + JAVAC_MAX_WARNINGS=false + JAVAC_LINT_OPTIONS=-Xlint:all,-deprecation + JAVAC_WARNINGS_FATAL=true + + # + # C and Java Files + # + include FILES_c.gmk + + # + # Subdirectories of these are automatically included. + # + AUTO_FILES_JAVA_DIRS = com/oracle/security/ucrypto + + # + # Java files that define native methods + # + FILES_export = \ + com/oracle/security/ucrypto/UcryptoProvider.java \ + com/oracle/security/ucrypto/NativeCipher.java \ + com/oracle/security/ucrypto/NativeDigest.java \ + com/oracle/security/ucrypto/NativeKey.java \ + com/oracle/security/ucrypto/NativeRSASignature.java \ + com/oracle/security/ucrypto/NativeRSACipher.java + + # + # Find native code + # + vpath %.c \ + $(CLOSED_PLATFORM_SRC)/native/com/oracle/security/ucrypto + + # + # Find include files + # + OTHER_INCLUDES += \ + -I$(CLOSED_PLATFORM_SRC)/native/com/oracle/security/ucrypto + + # + # Rules + # + CLASSDESTDIR = $(TEMPDIR)/classes + JAVAHFLAGS = -bootclasspath \ + "$(CLASSDESTDIR)$(CLASSPATH_SEPARATOR)$(CLASSBINDIR)" + + include $(BUILDDIR)/common/Mapfile-vers.gmk + include $(BUILDDIR)/common/Library.gmk + + # + # Libraries to link + # + OTHER_LDLIBS = -ldl + + # Default config file + UCRYPTO_CFG_SRC = $(CLOSED_SRC)/share/lib/security/ucrypto-solaris.cfg + UCRYPTO_CFG_BUILD = $(LIBDIR)/security/ucrypto-solaris.cfg + + # + # We use a variety of subdirectories in the $(TEMPDIR) depending on what + # part of the build we're doing. Build is initially done in the unsigned + # area and when files are signed, they will be placed in the appropriate area. + # + UNSIGNED_DIR = $(TEMPDIR)/unsigned + + # + # Rules + # + all: ucrypto-cfg build-jar install-prebuilt + $(build-warning) + + ucrypto-cfg: $(UCRYPTO_CFG_BUILD) + + $(UCRYPTO_CFG_BUILD): $(UCRYPTO_CFG_SRC) + $(install-file) + + include $(BUILDDIR)/javax/crypto/Defs-jce.gmk + + + # ===================================================== + # Build the unsigned ucrypto.jar file. + # + + JAR_DESTFILE = $(EXTDIR)/ucrypto.jar + + # + # The ucrypto.jar needs to be in the extension class directory, + # therefore none of its classes can appear in $(CLASSBINDIR). + # Currently no one is using any of the internals, so these files + # should not have been built. + # + + # + # Since the -C option to jar is used below, each directory entry must be + # preceded with the appropriate directory to "cd" into. + # + JAR_DIRS = $(patsubst %, -C $(CLASSDESTDIR) %, $(AUTO_FILES_JAVA_DIRS)) + + build-jar: $(UNSIGNED_DIR)/ucrypto.jar + + # + # Build ucrypto.jar. + # + $(UNSIGNED_DIR)/ucrypto.jar: build + $(prep-target) + $(BOOT_JAR_CMD) cf $@ $(JAR_DIRS) \ + $(BOOT_JAR_JFLAGS) + @$(java-vm-cleanup) + + # + # Sign ucrypto.jar + # + SIGNED_DIR = $(JCE_BUILD_DIR)/signed + + sign: $(SIGNED_DIR)/ucrypto.jar + + ifndef ALT_JCE_BUILD_DIR + $(SIGNED_DIR)/ucrypto.jar: $(UNSIGNED_DIR)/ucrypto.jar + else + # + # We have to remove the build dependency, otherwise, we'll try to rebuild it + # which we can't do on a read-only filesystem. + # + $(SIGNED_DIR)/ucrypto.jar: + @if [ ! -r $(UNSIGNED_DIR)/ucrypto.jar ] ; then \ + $(ECHO) "Couldn't find $(UNSIGNED_DIR)/ucrypto.jar"; \ + exit 1; \ + fi + endif + $(call sign-file, $(UNSIGNED_DIR)/ucrypto.jar) + + + # ===================================================== + # Create the Release Engineering files. Signed builds, etc. + # + + release: $(SIGNED_DIR)/ucrypto.jar + $(RM) $(JCE_BUILD_DIR)/release/ucrypto.jar + $(MKDIR) -p $(JCE_BUILD_DIR)/release + $(CP) $(SIGNED_DIR)/ucrypto.jar $(JCE_BUILD_DIR)/release + $(release-warning) + + + # ===================================================== + # Install routines. + # + + # + # Install ucrypto.jar, depending on which type is requested. + # + jar: $(JAR_DESTFILE) + $(release-warning) + + $(JAR_DESTFILE): $(SIGNED_DIR)/ucrypto.jar + $(install-file) + + install-prebuilt: + @$(ECHO) "\n>>>Installing prebuilt OracleUcrypto provider..." + $(RM) $(JAR_DESTFILE) + $(CP) $(PREBUILT_DIR)/ucrypto/ucrypto.jar $(JAR_DESTFILE) + + + # ===================================================== + # Support routines. + # + clobber clean:: + $(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR) + $(RM) -r $(UCRYPTO_CFG_BUILD) + + .PHONY: build-jar jar sign release install-prebuilt + + endif #ifneq ($(PLATFORM), solaris) +endif #ifndef OPENJDK diff --git a/jdk/make/com/oracle/security/ucrypto/mapfile-vers b/jdk/make/com/oracle/security/ucrypto/mapfile-vers new file mode 100644 index 00000000000..1891d777c5b --- /dev/null +++ b/jdk/make/com/oracle/security/ucrypto/mapfile-vers @@ -0,0 +1,69 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Define public interface. + +SUNWprivate_1.1 { + global: + JNI_OnLoad; + Java_com_oracle_security_ucrypto_UcryptoProvider_loadLibraries; + Java_com_oracle_security_ucrypto_UcryptoProvider_getMechList; + Java_com_oracle_security_ucrypto_NativeDigest_nativeInit; + Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate; + Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest; + Java_com_oracle_security_ucrypto_NativeDigest_nativeClone; + Java_com_oracle_security_ucrypto_NativeDigest_nativeFree; + Java_com_oracle_security_ucrypto_NativeCipher_nativeInit; + Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate; + Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal; + Java_com_oracle_security_ucrypto_NativeKey_nativeFree; + Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit; + Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit; + Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit; + Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII; + Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI; + Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal; + Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic; + + JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit; + JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate; + JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest; + JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone; + JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree; + JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit; + JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate; + JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeFinal; + JavaCritical_com_oracle_security_ucrypto_NativeKey_nativeFree; + JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit; + JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit; + JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit; + JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII; + JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI; + JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal; + JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic; + + local: + *; +}; diff --git a/jdk/make/com/oracle/util/Makefile b/jdk/make/com/oracle/util/Makefile new file mode 100644 index 00000000000..f4022ba2c1b --- /dev/null +++ b/jdk/make/com/oracle/util/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +BUILDDIR = ../../.. +PACKAGE = com.oracle.util +PRODUCT = oracle +include $(BUILDDIR)/common/Defs.gmk + +# +# Files +# +AUTO_FILES_JAVA_DIRS = com/oracle/util + +# +# Rules +# +include $(BUILDDIR)/common/Classes.gmk + diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index 1a19f44d231..d01cfdafa1c 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -43,16 +43,17 @@ # # List of providers and their preference orders (see above): # -security.provider.1=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/sunpkcs11-solaris.cfg -security.provider.2=sun.security.provider.Sun -security.provider.3=sun.security.rsa.SunRsaSign -security.provider.4=sun.security.ec.SunEC -security.provider.5=com.sun.net.ssl.internal.ssl.Provider -security.provider.6=com.sun.crypto.provider.SunJCE -security.provider.7=sun.security.jgss.SunProvider -security.provider.8=com.sun.security.sasl.Provider -security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI -security.provider.10=sun.security.smartcardio.SunPCSC +security.provider.1=com.oracle.security.ucrypto.UcryptoProvider ${java.home}/lib/security/ucrypto-solaris.cfg +security.provider.2=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/sunpkcs11-solaris.cfg +security.provider.3=sun.security.provider.Sun +security.provider.4=sun.security.rsa.SunRsaSign +security.provider.5=sun.security.ec.SunEC +security.provider.6=com.sun.net.ssl.internal.ssl.Provider +security.provider.7=com.sun.crypto.provider.SunJCE +security.provider.8=sun.security.jgss.SunProvider +security.provider.9=com.sun.security.sasl.Provider +security.provider.10=org.jcp.xml.dsig.internal.dom.XMLDSigRI +security.provider.11=sun.security.smartcardio.SunPCSC # # Select the source of seed data for SecureRandom. By default an diff --git a/jdk/test/Makefile b/jdk/test/Makefile index e94a561695e..2ebaf24867b 100644 --- a/jdk/test/Makefile +++ b/jdk/test/Makefile @@ -555,7 +555,8 @@ jdk_security2: $(call TestDirs, javax/crypto javax/xml/crypto com/sun/crypto) # Stable agentvm testruns (minus items from PROBLEM_LIST) JDK_ALL_TARGETS += jdk_security3 jdk_security3: $(call TestDirs, com/sun/security lib/security javax/security \ - sun/security com/sun/org/apache/xml/internal/security) + sun/security com/sun/org/apache/xml/internal/security \ + com/oracle/secrity/ucrypto) $(call SharedLibraryPermissions,sun/security) $(call RunAgentvmBatch) diff --git a/jdk/test/com/oracle/security/ucrypto/TestAES.java b/jdk/test/com/oracle/security/ucrypto/TestAES.java new file mode 100644 index 00000000000..9f280aea04d --- /dev/null +++ b/jdk/test/com/oracle/security/ucrypto/TestAES.java @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7088989 + * @summary Ensure the AES ciphers of OracleUcrypto provider works correctly + */ +import java.io.*; +import java.security.*; +import java.security.spec.*; +import java.util.*; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class TestAES extends UcryptoTest { + + private static final String[] PADDEDCIPHER_ALGOS = { + "AES/ECB/PKCS5Padding", + "AES/CBC/PKCS5Padding", + "AES/CFB128/PKCS5Padding" + }; + + private static final String[] CIPHER_ALGOS = { + "AES/ECB/NoPadding", + "AES/CBC/NoPadding", + "AES/CFB128/NoPadding", + "AES/CTR/NoPadding", + }; + + private static final SecretKey CIPHER_KEY = + new SecretKeySpec(new byte[16], "AES"); + + public static void main(String[] args) throws Exception { + main(new TestAES(), null); + } + + public void doTest(Provider prov) throws Exception { + // Provider for testing Interoperability + Provider sunJCEProv = Security.getProvider("SunJCE"); + + testCipherInterop(CIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv); + testCipherInterop(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv); + + testCipherOffset(CIPHER_ALGOS, CIPHER_KEY, prov); + testCipherOffset(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov); + + testCipherKeyWrapping(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv); + testCipherGCM(CIPHER_KEY, prov); + } + + private static void testCipherInterop(String[] algos, SecretKey key, + Provider p, + Provider interopP) { + boolean testPassed = true; + byte[] in = new byte[32]; + (new SecureRandom()).nextBytes(in); + + for (String algo : algos) { + try { + // check ENC + Cipher c; + try { + c = Cipher.getInstance(algo, p); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skipping Unsupported CIP algo: " + algo); + continue; + } + c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null); + byte[] eout = c.doFinal(in, 0, in.length); + + AlgorithmParameters params = c.getParameters(); + Cipher c2 = Cipher.getInstance(algo, interopP); + c2.init(Cipher.ENCRYPT_MODE, key, params, null); + byte[] eout2 = c2.doFinal(in, 0, in.length); + + if (!Arrays.equals(eout, eout2)) { + System.out.println(algo + ": DIFF FAILED"); + testPassed = false; + } else { + System.out.println(algo + ": ENC Passed"); + } + + // check DEC + c.init(Cipher.DECRYPT_MODE, key, params, null); + byte[] dout = c.doFinal(eout); + c2.init(Cipher.DECRYPT_MODE, key, params, null); + byte[] dout2 = c2.doFinal(eout2); + + if (!Arrays.equals(dout, dout2)) { + System.out.println(algo + ": DIFF FAILED"); + testPassed = false; + } else { + System.out.println(algo + ": DEC Passed"); + } + } catch(Exception ex) { + System.out.println("Unexpected Exception: " + algo); + ex.printStackTrace(); + testPassed = false; + } + } + + if (!testPassed) { + throw new RuntimeException("One or more CIPHER test failed!"); + } else { + System.out.println("CIPHER Interop Tests Passed"); + } + } + + private static void testCipherOffset(String[] algos, SecretKey key, + Provider p) { + boolean testPassed = true; + byte[] in = new byte[16]; + (new SecureRandom()).nextBytes(in); + int blockSize = 16; + + for (int j = 1; j < (in.length - 1); j++) { + System.out.println("Input offset size: " + j); + for (int i = 0; i < algos.length; i++) { + try { + // check ENC + Cipher c; + try { + c = Cipher.getInstance(algos[i], p); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skip Unsupported CIP algo: " + algos[i]); + continue; + } + c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null); + byte[] eout = new byte[c.getOutputSize(in.length)]; + int firstPartLen = in.length - j - 1; + //System.out.print("1st UPDATE: " + firstPartLen); + int k = c.update(in, 0, firstPartLen, eout, 0); + k += c.update(in, firstPartLen, 1, eout, k); + k += c.doFinal(in, firstPartLen+1, j, eout, k); + + AlgorithmParameters params = c.getParameters(); + + Cipher c2 = Cipher.getInstance(algos[i], p); + c2.init(Cipher.ENCRYPT_MODE, key, params, null); + byte[] eout2 = new byte[c2.getOutputSize(in.length)]; + int k2 = c2.update(in, 0, j, eout2, 0); + k2 += c2.update(in, j, 1, eout2, k2); + k2 += c2.doFinal(in, j+1, firstPartLen, eout2, k2); + + if (!checkArrays(eout, k, eout2, k2)) testPassed = false; + + // check DEC + c.init(Cipher.DECRYPT_MODE, key, params, null); + byte[] dout = new byte[c.getOutputSize(eout.length)]; + k = c.update(eout, 0, firstPartLen, dout, 0); + k += c.update(eout, firstPartLen, 1, dout, k); + k += c.doFinal(eout, firstPartLen+1, eout.length - firstPartLen - 1, dout, k); + if (!checkArrays(in, in.length, dout, k)) testPassed = false; + } catch(Exception ex) { + System.out.println("Unexpected Exception: " + algos[i]); + ex.printStackTrace(); + testPassed = false; + } + } + } + if (!testPassed) { + throw new RuntimeException("One or more CIPHER test failed!"); + } else { + System.out.println("CIPHER Offset Tests Passed"); + } + } + + private static void testCipherKeyWrapping(String[] algos, SecretKey key, + Provider p, Provider interopP) + throws NoSuchAlgorithmException { + boolean testPassed = true; + + // Test SecretKey, PrivateKey and PublicKey + Key[] tbwKeys = new Key[3]; + int[] tbwKeyTypes = { Cipher.SECRET_KEY, Cipher.PRIVATE_KEY, Cipher.PUBLIC_KEY }; + tbwKeys[0] = new SecretKeySpec(new byte[20], "Blowfish"); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(1024); + KeyPair kp = kpg.generateKeyPair(); + tbwKeys[1] = kp.getPrivate(); + tbwKeys[2] = kp.getPublic(); + + for (int i = 0; i < algos.length; i++) { + try { + System.out.println(algos[i] + " - Native WRAP/Java UNWRAP"); + + Cipher c1; + try { + c1 = Cipher.getInstance(algos[i], p); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skipping Unsupported CIP algo: " + algos[i]); + continue; + } + c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null); + AlgorithmParameters params = c1.getParameters(); + Cipher c2 = Cipher.getInstance(algos[i], interopP); + c2.init(Cipher.UNWRAP_MODE, key, params, null); + + for (int j = 0; j < tbwKeys.length ; j++) { + byte[] wrappedKey = c1.wrap(tbwKeys[j]); + Key recovered = c2.unwrap(wrappedKey, + tbwKeys[j].getAlgorithm(), tbwKeyTypes[j]); + if (!checkKeys(tbwKeys[j], recovered)) testPassed = false; + } + + System.out.println(algos[i] + " - Java WRAP/Native UNWRAP"); + c1 = Cipher.getInstance(algos[i], interopP); + c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null); + params = c1.getParameters(); + c2 = Cipher.getInstance(algos[i], p); + c2.init(Cipher.UNWRAP_MODE, key, params, null); + + for (int j = 0; j < tbwKeys.length ; j++) { + byte[] wrappedKey = c1.wrap(tbwKeys[j]); + Key recovered = c2.unwrap(wrappedKey, + tbwKeys[j].getAlgorithm(), tbwKeyTypes[j]); + if (!checkKeys(tbwKeys[j], recovered)) testPassed = false; + } + + } catch(Exception ex) { + System.out.println("Unexpected Exception: " + algos[i]); + ex.printStackTrace(); + testPassed = false; + } + } + if (!testPassed) { + throw new RuntimeException("One or more CIPHER test failed!"); + } else { + System.out.println("CIPHER KeyWrapping Tests Passed"); + } + } + + + private static void testCipherGCM(SecretKey key, + Provider p) { + boolean testPassed = true; + byte[] in = new byte[16]; + (new SecureRandom()).nextBytes(in); + + byte[] iv = new byte[16]; + (new SecureRandom()).nextBytes(iv); + + + String algo = "AES/GCM/NoPadding"; + int tagLen[] = { 128, 120, 112, 104, 96, 64, 32 }; + + try { + Cipher c; + try { + c = Cipher.getInstance(algo, p); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skipping Unsupported CIP algo: " + algo); + return; + } + for (int i = 0; i < tagLen.length; i++) { + AlgorithmParameterSpec paramSpec = new GCMParameterSpec(tagLen[i], iv); + // check ENC + c.init(Cipher.ENCRYPT_MODE, key, paramSpec, null); + c.updateAAD(iv); + byte[] eout = c.doFinal(in, 0, in.length); + + AlgorithmParameters param = c.getParameters(); + // check DEC + c.init(Cipher.DECRYPT_MODE, key, param, null); + c.updateAAD(iv); + byte[] dout = c.doFinal(eout, 0, eout.length); + + if (!Arrays.equals(dout, in)) { + System.out.println(algo + ": PT and RT DIFF FAILED"); + testPassed = false; + } else { + System.out.println(algo + ": tagLen " + tagLen[i] + " done"); + } + } + } catch(Exception ex) { + System.out.println("Unexpected Exception: " + algo); + ex.printStackTrace(); + testPassed = false; + } + if (!testPassed) { + throw new RuntimeException("One or more CIPHER test failed!"); + } else { + System.out.println("CIPHER GCM Tests Passed"); + } + } + + private static boolean checkArrays(byte[] a1, int a1Len, byte[] a2, int a2Len) { + boolean equal = true; + if (a1Len != a2Len) { + System.out.println("DIFFERENT OUT LENGTH"); + equal = false; + } else { + for (int p = 0; p < a1Len; p++) { + if (a1[p] != a2[p]) { + System.out.println("DIFF FAILED"); + equal = false; + break; + } + } + } + return equal; + } + + private static boolean checkKeys(Key k1, Key k2) { + boolean equal = true; + if (!k1.getAlgorithm().equalsIgnoreCase(k2.getAlgorithm())) { + System.out.println("DIFFERENT Key Algorithm"); + equal = false; + } else if (!k1.getFormat().equalsIgnoreCase(k2.getFormat())) { + System.out.println("DIFFERENT Key Format"); + equal = false; + } else if (!Arrays.equals(k1.getEncoded(), k2.getEncoded())) { + System.out.println("DIFFERENT Key Encoding"); + equal = false; + } + return equal; + } +} diff --git a/jdk/test/com/oracle/security/ucrypto/TestDigest.java b/jdk/test/com/oracle/security/ucrypto/TestDigest.java new file mode 100644 index 00000000000..3bc85dc2316 --- /dev/null +++ b/jdk/test/com/oracle/security/ucrypto/TestDigest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7088989 + * @summary Ensure the various message digests works correctly + */ +import java.io.*; +import java.security.*; +import java.security.spec.*; +import java.util.*; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class TestDigest extends UcryptoTest { + + private static final String[] MD_ALGOS = { + "MD5", + "SHA", + "SHA-256", + "SHA-384", + "SHA-512" + }; + + public static void main(String[] args) throws Exception { + main(new TestDigest(), null); + } + + public void doTest(Provider p) { + boolean testPassed = true; + byte[] msg = new byte[200]; + (new SecureRandom()).nextBytes(msg); + String interopProvName = "SUN"; + + for (String a : MD_ALGOS) { + try { + MessageDigest md, md2; + try { + md = MessageDigest.getInstance(a, p); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skipping Unsupported MD algo: " + a); + continue; + } + md2 = MessageDigest.getInstance(a, interopProvName); + // Test Interoperability for update+digest calls + for (int i = 0; i < 3; i++) { + md.update(msg); + byte[] digest = md.digest(); + md2.update(msg); + byte[] digest2 = md2.digest(); + if (!Arrays.equals(digest, digest2)) { + System.out.println("DIFF1 FAILED for: " + a + " at iter " + i); + testPassed = false; + } + } + + // Test Interoperability for digest calls + md = MessageDigest.getInstance(a, p); + md2 = MessageDigest.getInstance(a, interopProvName); + + for (int i = 0; i < 3; i++) { + byte[] digest = md.digest(); + byte[] digest2 = md2.digest(); + if (!Arrays.equals(digest, digest2)) { + System.out.println("DIFF2 FAILED for: " + a + " at iter " + i); + testPassed = false; + } + } + + // Test Cloning functionality + md = MessageDigest.getInstance(a, p); + md2 = (MessageDigest) md.clone(); // clone right after construction + byte[] digest = md.digest(); + byte[] digest2 = md2.digest(); + if (!Arrays.equals(digest, digest2)) { + System.out.println("DIFF-3.1 FAILED for: " + a); + testPassed = false; + } + md.update(msg); + md2 = (MessageDigest) md.clone(); // clone again after update call + digest = md.digest(); + digest2 = md2.digest(); + if (!Arrays.equals(digest, digest2)) { + System.out.println("DIFF-3.2 FAILED for: " + a); + testPassed = false; + } + md2 = (MessageDigest) md.clone(); // clone after digest + digest = md.digest(); + digest2 = md2.digest(); + if (!Arrays.equals(digest, digest2)) { + System.out.println("DIFF-3.3 FAILED for: " + a); + testPassed = false; + } + } catch(Exception ex) { + System.out.println("Unexpected Exception: " + a); + ex.printStackTrace(); + testPassed = false; + } + } + if (!testPassed) { + throw new RuntimeException("One or more MD test failed!"); + } else { + System.out.println("MD Tests Passed"); + } + } +} diff --git a/jdk/test/com/oracle/security/ucrypto/TestRSA.java b/jdk/test/com/oracle/security/ucrypto/TestRSA.java new file mode 100644 index 00000000000..3f4364e27e8 --- /dev/null +++ b/jdk/test/com/oracle/security/ucrypto/TestRSA.java @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7088989 + * @summary Ensure the RSA ciphers and signatures works correctly + */ +import java.io.*; +import java.security.*; +import java.security.spec.*; +import java.util.*; +import java.math.*; +import javax.crypto.*; + +public class TestRSA extends UcryptoTest { + + // KAT + private static final byte PLAINTEXT[] = Arrays.copyOf + (new String("Known plaintext message utilized" + + "for RSA Encryption & Decryption" + + "block, SHA1, SHA256, SHA384 and" + + "SHA512 RSA Signature KAT tests.").getBytes(), 128); + + private static final byte MOD[] = { + (byte)0xd5, (byte)0x84, (byte)0x95, (byte)0x07, (byte)0xf4, (byte)0xd0, + (byte)0x1f, (byte)0x82, (byte)0xf3, (byte)0x79, (byte)0xf4, (byte)0x99, + (byte)0x48, (byte)0x10, (byte)0xe1, (byte)0x71, (byte)0xa5, (byte)0x62, + (byte)0x22, (byte)0xa3, (byte)0x4b, (byte)0x00, (byte)0xe3, (byte)0x5b, + (byte)0x3a, (byte)0xcc, (byte)0x10, (byte)0x83, (byte)0xe0, (byte)0xaf, + (byte)0x61, (byte)0x13, (byte)0x54, (byte)0x6a, (byte)0xa2, (byte)0x6a, + (byte)0x2c, (byte)0x5e, (byte)0xb3, (byte)0xcc, (byte)0xa3, (byte)0x71, + (byte)0x9a, (byte)0xb2, (byte)0x3e, (byte)0x78, (byte)0xec, (byte)0xb5, + (byte)0x0e, (byte)0x6e, (byte)0x31, (byte)0x3b, (byte)0x77, (byte)0x1f, + (byte)0x6e, (byte)0x94, (byte)0x41, (byte)0x60, (byte)0xd5, (byte)0x6e, + (byte)0xd9, (byte)0xc6, (byte)0xf9, (byte)0x29, (byte)0xc3, (byte)0x40, + (byte)0x36, (byte)0x25, (byte)0xdb, (byte)0xea, (byte)0x0b, (byte)0x07, + (byte)0xae, (byte)0x76, (byte)0xfd, (byte)0x99, (byte)0x29, (byte)0xf4, + (byte)0x22, (byte)0xc1, (byte)0x1a, (byte)0x8f, (byte)0x05, (byte)0xfe, + (byte)0x98, (byte)0x09, (byte)0x07, (byte)0x05, (byte)0xc2, (byte)0x0f, + (byte)0x0b, (byte)0x11, (byte)0x83, (byte)0x39, (byte)0xca, (byte)0xc7, + (byte)0x43, (byte)0x63, (byte)0xff, (byte)0x33, (byte)0x80, (byte)0xe7, + (byte)0xc3, (byte)0x78, (byte)0xae, (byte)0xf1, (byte)0x73, (byte)0x52, + (byte)0x98, (byte)0x1d, (byte)0xde, (byte)0x5c, (byte)0x53, (byte)0x6e, + (byte)0x01, (byte)0x73, (byte)0x0d, (byte)0x12, (byte)0x7e, (byte)0x77, + (byte)0x03, (byte)0xf1, (byte)0xef, (byte)0x1b, (byte)0xc8, (byte)0xa8, + (byte)0x0f, (byte)0x97 + }; + + private static final byte PUB_EXP[] = {(byte)0x01, (byte)0x00, (byte)0x01}; + + private static final byte PRIV_EXP[] = { + (byte)0x85, (byte)0x27, (byte)0x47, (byte)0x61, (byte)0x4c, (byte)0xd4, + (byte)0xb5, (byte)0xb2, (byte)0x0e, (byte)0x70, (byte)0x91, (byte)0x8f, + (byte)0x3d, (byte)0x97, (byte)0xf9, (byte)0x5f, (byte)0xcc, (byte)0x09, + (byte)0x65, (byte)0x1c, (byte)0x7c, (byte)0x5b, (byte)0xb3, (byte)0x6d, + (byte)0x63, (byte)0x3f, (byte)0x7b, (byte)0x55, (byte)0x22, (byte)0xbb, + (byte)0x7c, (byte)0x48, (byte)0x77, (byte)0xae, (byte)0x80, (byte)0x56, + (byte)0xc2, (byte)0x10, (byte)0xd5, (byte)0x03, (byte)0xdb, (byte)0x31, + (byte)0xaf, (byte)0x8d, (byte)0x54, (byte)0xd4, (byte)0x48, (byte)0x99, + (byte)0xa8, (byte)0xc4, (byte)0x23, (byte)0x43, (byte)0xb8, (byte)0x48, + (byte)0x0b, (byte)0xc7, (byte)0xbc, (byte)0xf5, (byte)0xcc, (byte)0x64, + (byte)0x72, (byte)0xbf, (byte)0x59, (byte)0x06, (byte)0x04, (byte)0x1c, + (byte)0x32, (byte)0xf5, (byte)0x14, (byte)0x2e, (byte)0x6e, (byte)0xe2, + (byte)0x0f, (byte)0x5c, (byte)0xde, (byte)0x36, (byte)0x3c, (byte)0x6e, + (byte)0x7c, (byte)0x4d, (byte)0xcc, (byte)0xd3, (byte)0x00, (byte)0x6e, + (byte)0xe5, (byte)0x45, (byte)0x46, (byte)0xef, (byte)0x4d, (byte)0x25, + (byte)0x46, (byte)0x6d, (byte)0x7f, (byte)0xed, (byte)0xbb, (byte)0x4f, + (byte)0x4d, (byte)0x9f, (byte)0xda, (byte)0x87, (byte)0x47, (byte)0x8f, + (byte)0x74, (byte)0x44, (byte)0xb7, (byte)0xbe, (byte)0x9d, (byte)0xf5, + (byte)0xdd, (byte)0xd2, (byte)0x4c, (byte)0xa5, (byte)0xab, (byte)0x74, + (byte)0xe5, (byte)0x29, (byte)0xa1, (byte)0xd2, (byte)0x45, (byte)0x3b, + (byte)0x33, (byte)0xde, (byte)0xd5, (byte)0xae, (byte)0xf7, (byte)0x03, + (byte)0x10, (byte)0x21 + }; + + private static final byte PRIME_P[] = { + (byte)0xf9, (byte)0x74, (byte)0x8f, (byte)0x16, (byte)0x02, (byte)0x6b, + (byte)0xa0, (byte)0xee, (byte)0x7f, (byte)0x28, (byte)0x97, (byte)0x91, + (byte)0xdc, (byte)0xec, (byte)0xc0, (byte)0x7c, (byte)0x49, (byte)0xc2, + (byte)0x85, (byte)0x76, (byte)0xee, (byte)0x66, (byte)0x74, (byte)0x2d, + (byte)0x1a, (byte)0xb8, (byte)0xf7, (byte)0x2f, (byte)0x11, (byte)0x5b, + (byte)0x36, (byte)0xd8, (byte)0x46, (byte)0x33, (byte)0x3b, (byte)0xd8, + (byte)0xf3, (byte)0x2d, (byte)0xa1, (byte)0x03, (byte)0x83, (byte)0x2b, + (byte)0xec, (byte)0x35, (byte)0x43, (byte)0x32, (byte)0xff, (byte)0xdd, + (byte)0x81, (byte)0x7c, (byte)0xfd, (byte)0x65, (byte)0x13, (byte)0x04, + (byte)0x7c, (byte)0xfc, (byte)0x03, (byte)0x97, (byte)0xf0, (byte)0xd5, + (byte)0x62, (byte)0xdc, (byte)0x0d, (byte)0xbf + }; + + private static final byte PRIME_Q[] = { + (byte)0xdb, (byte)0x1e, (byte)0xa7, (byte)0x3d, (byte)0xe7, (byte)0xfa, + (byte)0x8b, (byte)0x04, (byte)0x83, (byte)0x48, (byte)0xf3, (byte)0xa5, + (byte)0x31, (byte)0x9d, (byte)0x35, (byte)0x5e, (byte)0x4d, (byte)0x54, + (byte)0x77, (byte)0xcc, (byte)0x84, (byte)0x09, (byte)0xf3, (byte)0x11, + (byte)0x0d, (byte)0x54, (byte)0xed, (byte)0x85, (byte)0x39, (byte)0xa9, + (byte)0xca, (byte)0xa8, (byte)0xea, (byte)0xae, (byte)0x19, (byte)0x9c, + (byte)0x75, (byte)0xdb, (byte)0x88, (byte)0xb8, (byte)0x04, (byte)0x8d, + (byte)0x54, (byte)0xc6, (byte)0xa4, (byte)0x80, (byte)0xf8, (byte)0x93, + (byte)0xf0, (byte)0xdb, (byte)0x19, (byte)0xef, (byte)0xd7, (byte)0x87, + (byte)0x8a, (byte)0x8f, (byte)0x5a, (byte)0x09, (byte)0x2e, (byte)0x54, + (byte)0xf3, (byte)0x45, (byte)0x24, (byte)0x29 + }; + + private static final byte EXP_P[] = { + (byte)0x6a, (byte)0xd1, (byte)0x25, (byte)0x80, (byte)0x18, (byte)0x33, + (byte)0x3c, (byte)0x2b, (byte)0x44, (byte)0x19, (byte)0xfe, (byte)0xa5, + (byte)0x40, (byte)0x03, (byte)0xc4, (byte)0xfc, (byte)0xb3, (byte)0x9c, + (byte)0xef, (byte)0x07, (byte)0x99, (byte)0x58, (byte)0x17, (byte)0xc1, + (byte)0x44, (byte)0xa3, (byte)0x15, (byte)0x7d, (byte)0x7b, (byte)0x22, + (byte)0x22, (byte)0xdf, (byte)0x03, (byte)0x58, (byte)0x66, (byte)0xf5, + (byte)0x24, (byte)0x54, (byte)0x52, (byte)0x91, (byte)0x2d, (byte)0x76, + (byte)0xfe, (byte)0x63, (byte)0x64, (byte)0x4e, (byte)0x0f, (byte)0x50, + (byte)0x2b, (byte)0x65, (byte)0x79, (byte)0x1f, (byte)0xf1, (byte)0xbf, + (byte)0xc7, (byte)0x41, (byte)0x26, (byte)0xcc, (byte)0xc6, (byte)0x1c, + (byte)0xa9, (byte)0x83, (byte)0x6f, (byte)0x03 + }; + + private static final byte EXP_Q[] = { + (byte)0x12, (byte)0x84, (byte)0x1a, (byte)0x99, (byte)0xce, (byte)0x9a, + (byte)0x8b, (byte)0x58, (byte)0xcc, (byte)0x47, (byte)0x43, (byte)0xdf, + (byte)0x77, (byte)0xbb, (byte)0xd3, (byte)0x20, (byte)0xae, (byte)0xe4, + (byte)0x2e, (byte)0x63, (byte)0x67, (byte)0xdc, (byte)0xf7, (byte)0x5f, + (byte)0x3f, (byte)0x83, (byte)0x27, (byte)0xb7, (byte)0x14, (byte)0x52, + (byte)0x56, (byte)0xbf, (byte)0xc3, (byte)0x65, (byte)0x06, (byte)0xe1, + (byte)0x03, (byte)0xcc, (byte)0x93, (byte)0x57, (byte)0x09, (byte)0x7b, + (byte)0x6f, (byte)0xe8, (byte)0x81, (byte)0x4a, (byte)0x2c, (byte)0xb7, + (byte)0x43, (byte)0xa9, (byte)0x20, (byte)0x1d, (byte)0xf6, (byte)0x56, + (byte)0x8b, (byte)0xcc, (byte)0xe5, (byte)0x4c, (byte)0xd5, (byte)0x4f, + (byte)0x74, (byte)0x67, (byte)0x29, (byte)0x51 + }; + + private static final byte CRT_COEFF[] = { + (byte)0x23, (byte)0xab, (byte)0xf4, (byte)0x03, (byte)0x2f, (byte)0x29, + (byte)0x95, (byte)0x74, (byte)0xac, (byte)0x1a, (byte)0x33, (byte)0x96, + (byte)0x62, (byte)0xed, (byte)0xf7, (byte)0xf6, (byte)0xae, (byte)0x07, + (byte)0x2a, (byte)0x2e, (byte)0xe8, (byte)0xab, (byte)0xfb, (byte)0x1e, + (byte)0xb9, (byte)0xb2, (byte)0x88, (byte)0x1e, (byte)0x85, (byte)0x05, + (byte)0x42, (byte)0x64, (byte)0x03, (byte)0xb2, (byte)0x8b, (byte)0xc1, + (byte)0x81, (byte)0x75, (byte)0xd7, (byte)0xba, (byte)0xaa, (byte)0xd4, + (byte)0x31, (byte)0x3c, (byte)0x8a, (byte)0x96, (byte)0x23, (byte)0x9d, + (byte)0x3f, (byte)0x06, (byte)0x3e, (byte)0x44, (byte)0xa9, (byte)0x62, + (byte)0x2f, (byte)0x61, (byte)0x5a, (byte)0x51, (byte)0x82, (byte)0x2c, + (byte)0x04, (byte)0x85, (byte)0x73, (byte)0xd1 + }; + + private static KeyPair genRSAKey(int keyLength) throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(keyLength); + return kpg.generateKeyPair(); + } + + private static KeyPair genPredefinedRSAKeyPair() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + BigInteger mod = new BigInteger(MOD); + BigInteger pub = new BigInteger(PUB_EXP); + + PrivateKey privKey = kf.generatePrivate + (new RSAPrivateCrtKeySpec + (mod, pub, new BigInteger(PRIV_EXP), + new BigInteger(PRIME_P), new BigInteger(PRIME_Q), + new BigInteger(EXP_P), new BigInteger(EXP_Q), + new BigInteger(CRT_COEFF))); + PublicKey pubKey = kf.generatePublic(new RSAPublicKeySpec(mod, pub)); + return new KeyPair(pubKey, privKey); + } + + private static final String CIP_ALGOS[] = { + "RSA/ECB/NoPadding", + "RSA/ECB/PKCS1Padding" + }; + private static final int INPUT_SIZE_REDUCTION[] = { + 0, + 11, + }; + private static final String SIG_ALGOS[] = { + "MD5WithRSA", + "SHA1WithRSA", + "SHA256WithRSA", + "SHA384WithRSA", + "SHA512WithRSA" + }; + + private static KeyPair kp[] = null; + + public static void main(String argv[]) throws Exception { + main(new TestRSA(), null); + } + + public void doTest(Provider prov) throws Exception { + // first test w/ predefine KeyPair + KeyPair pkp = genPredefinedRSAKeyPair(); + System.out.println("Test against Predefined RSA Key Pair"); + testCipher(pkp, 128, true, prov); + testSignature(pkp, true, prov); + + for (int i = 0; i < 10; i++) { + // then test w/ various key lengths + int keyLens[] = { 1024, 2048 }; + kp = new KeyPair[keyLens.length]; + + testCipher(keyLens, false, prov); + testSignature(keyLens, false, prov); + } + } + + + private static void testCipher(KeyPair kp, int inputSizeInBytes, + boolean checkInterop, Provider prov) + throws Exception { + Cipher c1, c2; + for (int i = 0; i < CIP_ALGOS.length; i++) { + String algo = CIP_ALGOS[i]; + try { + c1 = Cipher.getInstance(algo, prov); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skip unsupported Cipher algo: " + algo); + continue; + } + + if (checkInterop) { + c2 = Cipher.getInstance(algo, "SunJCE"); + } else { + c2 = Cipher.getInstance(algo, prov); + } + byte[] data = Arrays.copyOf + (PLAINTEXT, inputSizeInBytes - INPUT_SIZE_REDUCTION[i]); + + testEncryption(c1, c2, kp, data); + } + } + + private static void testCipher(int keyLens[], boolean checkInterop, + Provider prov) + throws Exception { + // RSA CipherText will always differ due to the random nonce in padding + // so we check whether both + // 1) Java Encrypt/C Decrypt + // 2) C Encrypt/Java Decrypt + // works + Cipher c1, c2; + for (int i = 0; i < CIP_ALGOS.length; i++) { + String algo = CIP_ALGOS[i]; + try { + c1 = Cipher.getInstance(algo, prov); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skip unsupported Cipher algo: " + algo); + continue; + } + + if (checkInterop) { + c2 = Cipher.getInstance(algo, "SunJCE"); + } else { + c2 = Cipher.getInstance(algo, prov); + } + + for (int h = 0; h < keyLens.length; h++) { + // Defer key pair generation until now when it'll soon be used. + if (kp[h] == null) { + kp[h] = genRSAKey(keyLens[h]); + } + System.out.println("\tTesting Cipher " + algo + " w/ KeySize " + keyLens[h]); + byte[] data = Arrays.copyOf + (PLAINTEXT, keyLens[h]/8 - INPUT_SIZE_REDUCTION[i]); + testEncryption(c1, c2, kp[h], data); + } + } + } + + private static void testEncryption(Cipher c1, Cipher c2, KeyPair kp, byte[] data) + throws Exception { + // C1 Encrypt + C2 Decrypt + byte[] out1 = null; + byte[] recoveredText = null; + try { + c1.init(Cipher.ENCRYPT_MODE, kp.getPublic()); + out1 = c1.doFinal(data); + c2.init(Cipher.DECRYPT_MODE, kp.getPrivate()); + recoveredText = c2.doFinal(out1); + } catch (Exception ex) { + System.out.println("\tDEC ERROR: unexpected exception"); + ex.printStackTrace(); + throw ex; + } + if(!Arrays.equals(recoveredText, data)) { + throw new RuntimeException("\tDEC ERROR: different PT bytes!"); + } + // C2 Encrypt + C1 Decrypt + byte[] cipherText = null; + try { + c2.init(Cipher.ENCRYPT_MODE, kp.getPublic()); + cipherText = c2.doFinal(data); + c1.init(Cipher.DECRYPT_MODE, kp.getPrivate()); + try { + out1 = c1.doFinal(cipherText); + } catch (Exception ex) { + System.out.println("\tENC ERROR: invalid encrypted output"); + ex.printStackTrace(); + throw ex; + } + } catch (Exception ex) { + System.out.println("\tENC ERROR: unexpected exception"); + ex.printStackTrace(); + throw ex; + } + if (!Arrays.equals(out1, data)) { + throw new RuntimeException("\tENC ERROR: Decrypted result DIFF!"); + } + System.out.println("\t=> PASS"); + } + + private static void testSignature(KeyPair kp, boolean checkInterop, + Provider prov) throws Exception { + byte[] data = PLAINTEXT; + Signature sig1, sig2; + for (int i = 0; i < SIG_ALGOS.length; i++) { + String algo = SIG_ALGOS[i]; + try { + sig1 = Signature.getInstance(algo, prov); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skip unsupported Signature algo: " + algo); + continue; + } + + if (checkInterop) { + sig2 = Signature.getInstance(algo, "SunRsaSign"); + } else { + sig2 = Signature.getInstance(algo, prov); + } + testSigning(sig1, sig2, kp, data); + } + } + + private static void testSignature(int keyLens[], boolean checkInterop, + Provider prov) throws Exception { + byte[] data = PLAINTEXT; + Signature sig1, sig2; + for (int i = 0; i < SIG_ALGOS.length; i++) { + String algo = SIG_ALGOS[i]; + try { + sig1 = Signature.getInstance(algo, prov); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skip unsupported Signature algo: " + algo); + continue; + } + + if (checkInterop) { + sig2 = Signature.getInstance(algo, "SunRsaSign"); + } else { + sig2 = Signature.getInstance(algo, prov); + } + + for (int h = 0; h < keyLens.length; h++) { + // Defer key pair generation until now when it'll soon be used. + if (kp[h] == null) { + kp[h] = genRSAKey(keyLens[h]); + } + System.out.println("\tTesting Signature " + algo + " w/ KeySize " + keyLens[h]); + + testSigning(sig1, sig2, kp[h], data); + } + } + } + + private static void testSigning(Signature sig1, Signature sig2, KeyPair kp, byte[] data) + throws Exception { + boolean sameSig = false; + byte[] out = null; + try { + sig1.initSign(kp.getPrivate()); + sig1.update(data); + out = sig1.sign(); + } catch (Exception ex) { + System.out.println("\tSIGN ERROR: unexpected exception!"); + ex.printStackTrace(); + } + + sig2.initSign(kp.getPrivate()); + sig2.update(data); + byte[] out2 = sig2.sign(); + if (!Arrays.equals(out2, out)) { + throw new RuntimeException("\tSIGN ERROR: Signature DIFF!"); + } + + boolean verify = false; + try { + System.out.println("\tVERIFY1 using native out"); + sig1.initVerify(kp.getPublic()); + sig1.update(data); + verify = sig1.verify(out); + if (!verify) { + throw new RuntimeException("VERIFY1 FAIL!"); + } + } catch (Exception ex) { + System.out.println("\tVERIFY1 ERROR: unexpected exception!"); + ex.printStackTrace(); + throw ex; + } + System.out.println("\t=> PASS"); + } +} diff --git a/jdk/test/com/oracle/security/ucrypto/UcryptoTest.java b/jdk/test/com/oracle/security/ucrypto/UcryptoTest.java new file mode 100644 index 00000000000..c2343c9963f --- /dev/null +++ b/jdk/test/com/oracle/security/ucrypto/UcryptoTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +// common infrastructure for OracleUcrypto provider tests + +import java.io.*; +import java.util.*; +import java.lang.reflect.*; + +import java.security.*; + +public abstract class UcryptoTest { + + protected static final boolean hasUcrypto; + static { + hasUcrypto = (Security.getProvider("OracleUcrypto") != null); + } + + private static Provider getCustomizedUcrypto(String config) throws Exception { + Class clazz = Class.forName("com.oracle.security.ucrypto.OracleUcrypto"); + Constructor cons = clazz.getConstructor(new Class[] {String.class}); + Object obj = cons.newInstance(new Object[] {config}); + return (Provider)obj; + } + + public abstract void doTest(Provider p) throws Exception; + + public static void main(UcryptoTest test, String config) throws Exception { + Provider prov = null; + if (hasUcrypto) { + if (config != null) { + prov = getCustomizedUcrypto(config); + } else { + prov = Security.getProvider("OracleUcrypto"); + } + } + if (prov == null) { + // un-available, skip testing... + System.out.println("No OracleUcrypto provider found, skipping test"); + return; + } + test.doTest(prov); + } +} diff --git a/jdk/test/java/security/Provider/DefaultPKCS11.java b/jdk/test/java/security/Provider/DefaultPKCS11.java index 8bfd14192d3..46b82dd35bd 100644 --- a/jdk/test/java/security/Provider/DefaultPKCS11.java +++ b/jdk/test/java/security/Provider/DefaultPKCS11.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,10 @@ public class DefaultPKCS11 { System.out.println("Test only applies to Solaris 10 and later, skipping"); return; } - if (ps[0].getName().equals("SunPKCS11-Solaris") == false) { + // SunPKCS11-Solaris provider should be either the first one or + // the second one + if (ps[0].getName().equals("SunPKCS11-Solaris") == false && + ps[1].getName().equals("SunPKCS11-Solaris") == false) { throw new Exception("SunPKCS11-Solaris provider not installed"); } System.out.println("OK"); From c4f77e41b61787b7b8565876e0c427ecdf7b2539 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 13 Jan 2012 09:50:19 +0800 Subject: [PATCH 32/96] 7090565: Move test/closed/javax/security/auth/x500/X500Principal/Parse.java to open tests Reviewed-by: mullan --- .../auth/x500/X500Principal/NameFormat.java | 213 ++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 jdk/test/javax/security/auth/x500/X500Principal/NameFormat.java diff --git a/jdk/test/javax/security/auth/x500/X500Principal/NameFormat.java b/jdk/test/javax/security/auth/x500/X500Principal/NameFormat.java new file mode 100644 index 00000000000..6d08a8fd0cf --- /dev/null +++ b/jdk/test/javax/security/auth/x500/X500Principal/NameFormat.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4505980 5109882 7049963 7090565 + * @summary X500Principal input name parsing issues and wrong exception thrown + * @run main/othervm -Djava.security.debug=x509,ava NameFormat + * + * The debug=ava above must be set in order to check for escaped hex chars. + */ +import javax.security.auth.x500.X500Principal; + +public class NameFormat { + + public static void main(String[] args) throws Exception { + + // tests for leading/trailing escaped/non-escaped spaces + + testName("cn=\\ duke ", "RFC1779", "CN=\" duke\"", 1); + testName("cn=\\ duke ", "RFC2253", "CN=\\ duke", 2); + testName("cn=\\ duke ", "CANONICAL", "cn=duke", 3); + testName("cn=\\ duke ", "toString", "CN=\" duke\"", 4); + + testName("cn= duke", "RFC1779", "CN=duke", 5); + testName("cn= duke", "RFC2253", "CN=duke", 6); + testName("cn= duke", "CANONICAL", "cn=duke", 7); + testName("cn= duke", "toString", "CN=duke", 8); + + testName("cn=duke\\ ", "RFC1779", "CN=\"duke \"", 9); + testName("cn=duke\\ ", "RFC2253", "CN=duke\\ ", 10); + testName("cn=duke\\ ", "CANONICAL", "cn=duke", 11); + testName("cn=duke\\ ", "toString", "CN=\"duke \"", 12); + + testName("cn=duke\\ , ou= sun\\ ", "RFC1779", + "CN=\"duke \", OU=\"sun \"", 13); + testName("cn=duke\\ , ou= sun\\ ", "RFC2253", + "CN=duke\\ ,OU=sun\\ ", 14); + testName("cn=duke\\ , ou= sun\\ ", "CANONICAL", + "cn=duke,ou=sun", 15); + testName("cn=duke\\ , ou= sun\\ ", "toString", + "CN=\"duke \", OU=\"sun \"", 16); + + // tests for trailing escaped backslash + + testName("cn=duke \\\\\\,test,O=java", "CANONICAL", + "cn=duke \\\\\\,test,o=java", 17); + + testName("cn=duke\\\\, o=java", "CANONICAL", + "cn=duke\\\\,o=java", 18); + + X500Principal p = new X500Principal("cn=duke \\\\\\,test,o=java"); + X500Principal p2 = new X500Principal(p.getName("CANONICAL")); + if (p.getName("CANONICAL").equals(p2.getName("CANONICAL"))) { + System.out.println("test 19 succeeded"); + } else { + throw new SecurityException("test 19 failed\n" + + p.getName("CANONICAL") + " not equal to " + + p2.getName("CANONICAL")); + } + + try { + p = new X500Principal("cn=duke \\\\,test,o=java"); + throw new SecurityException("test 19.5 failed:\n" + + p.getName("CANONICAL")); + } catch (IllegalArgumentException iae) { + System.out.println("test 19.5 succeeded"); + iae.printStackTrace(); + } + + // tests for wrong exception thrown + try { + byte[] encoding = { + (byte)0x17, (byte)0x80, (byte)0x70, (byte)0x41, + (byte)0x6b, (byte)0x15, (byte)0xdc, (byte)0x84, + (byte)0xef, (byte)0x58, (byte)0xac, (byte)0x88, + (byte)0xae, (byte)0xb0, (byte)0x19, (byte)0x7c, + (byte)0x6f, (byte)0xea, (byte)0xf5, (byte)0x56, + }; + p = new X500Principal(new java.io.DataInputStream + (new java.io.ByteArrayInputStream(encoding))); + } catch (IllegalArgumentException iae) { + System.out.println("test 20 succeeded"); + iae.printStackTrace(); + } catch (Exception e) { + System.out.println("test 20 failed"); + throw e; + } + + // tests for escaping '+' in canonical form + + testName("cn=se\\+an, ou= sun\\ ", "CANONICAL", + "cn=se\\+an,ou=sun", 21); + + // tests for embedded hex pairs + + testName("CN=Before\\0dAfter,DC=example,DC=net", "toString", + "CN=Before\\0DAfter, DC=example, DC=net", 22); + testName("CN=Before\\0dAfter,DC=example,DC=net", "RFC1779", + "CN=Before\\0DAfter, " + + "OID.0.9.2342.19200300.100.1.25=example, " + + "OID.0.9.2342.19200300.100.1.25=net", 23); + testName("CN=Before\\0dAfter,DC=example,DC=net", "RFC2253", + "CN=Before\\0DAfter,DC=example,DC=net", 24); + testName("CN=Before\\0dAfter,DC=example,DC=net", "CANONICAL", + "cn=before\\0dafter,dc=#16076578616d706c65,dc=#16036e6574", 25); + + testName("CN=Lu\\C4\\8Di\\C4\\87", "toString", + "CN=Lu\\C4\\8Di\\C4\\87", 26); + testName("CN=Lu\\C4\\8Di\\C4\\87", "RFC1779", + "CN=Lu\\C4\\8Di\\C4\\87", 27); + testName("CN=Lu\\C4\\8Di\\C4\\87", "RFC2253", + "CN=Lu\\C4\\8Di\\C4\\87", 28); + testName("CN=Lu\\C4\\8Di\\C4\\87", "CANONICAL", + "cn=lu\\c4\\8di\\c4\\87", 29); + + try { + p = new X500Principal("cn=\\gg"); + throw new SecurityException("test 30 failed"); + } catch (IllegalArgumentException iae) { + System.out.println("test 30 succeeded"); + } + + // tests for invalid escaped chars + + try { + p = new X500Principal("cn=duke \\test"); + throw new SecurityException("test 31 failed"); + } catch (IllegalArgumentException iae) { + System.out.println("test 31 succeeded"); + } + + try { + p = new X500Principal("cn=duke \\?test"); + throw new SecurityException("test 32 failed"); + } catch (IllegalArgumentException iae) { + System.out.println("test 32 succeeded"); + } + + // tests for X500Name using RFC2253 as format + + try { + // invalid non-escaped leading space + sun.security.x509.X500Name name = + new sun.security.x509.X500Name("cn= duke test", "RFC2253"); + throw new SecurityException("test 33 failed"); + } catch (java.io.IOException ioe) { + ioe.printStackTrace(); + System.out.println("test 33 succeeded"); + } + + try { + // invalid non-escaped trailing space + sun.security.x509.X500Name name = + new sun.security.x509.X500Name("cn=duke test ", "RFC2253"); + throw new SecurityException("test 34 failed"); + } catch (java.io.IOException ioe) { + System.out.println("test 34 succeeded"); + } + + testName("CN=SPECIAL CHARS,OU=\\#\\\"\\,\\<\\>\\+\\;,O=foo, " + + "L=bar, ST=baz, C=JP", "RFC1779", + "CN=SPECIAL CHARS, OU=\"#\\\",<>+;\", O=foo, L=bar, " + + "ST=baz, C=JP", 35); + + // test that double-quoted string is not escaped in RFC 1779 format + testName("CN=\"\\\"Duke\\\"\"", "RFC1779", "CN=\"Duke\"", 36); + } + + public static void testName(String in, String outFormat, + String expect, int n) + throws Exception { + + X500Principal p = new X500Principal(in); + if (outFormat.equalsIgnoreCase("toString")) { + if (p.toString().equals(expect)) { + System.out.println("test " + n + " succeeded"); + } else { + throw new SecurityException("test " + n + " failed:\n" + + "expected '" + expect + "'\n" + + "got '" + p.toString() + "'"); + } + } else { + if (p.getName(outFormat).equals(expect)) { + System.out.println("test " + n + " succeeded"); + } else { + throw new SecurityException("test " + n + " failed:\n" + + "expected '" + expect + "'\n" + + "got '" + p.getName(outFormat) + "'"); + } + } + } +} From 30f7f59109d3607cdf33dea956f53c68e6fc021f Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Fri, 13 Jan 2012 12:39:23 +0400 Subject: [PATCH 33/96] 7121765: closed/javax/swing/JTextArea/4697612/bug4697612.java fails on MacOS on Aqua L&F Reviewed-by: rupashka --- .../swing/JTextArea/4697612/bug4697612.java | 208 ++++++++++++++++ .../swing/JTextArea/4697612/bug4697612.txt | 223 ++++++++++++++++++ 2 files changed, 431 insertions(+) create mode 100644 jdk/test/javax/swing/JTextArea/4697612/bug4697612.java create mode 100644 jdk/test/javax/swing/JTextArea/4697612/bug4697612.txt diff --git a/jdk/test/javax/swing/JTextArea/4697612/bug4697612.java b/jdk/test/javax/swing/JTextArea/4697612/bug4697612.java new file mode 100644 index 00000000000..54cd12cb225 --- /dev/null +++ b/jdk/test/javax/swing/JTextArea/4697612/bug4697612.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4697612 6244705 + * @author Peter Zhelezniakov + * @library ../../regtesthelpers + * @build Util + * @run main bug4697612 + */ +import java.io.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +import javax.swing.text.BadLocationException; +import sun.awt.SunToolkit; + +public class bug4697612 { + + static final int FRAME_WIDTH = 300; + static final int FRAME_HEIGHT = 300; + static final int FONT_HEIGHT = 16; + private static volatile int frameHeight; + private static volatile int fontHeight; + private static JFrame frame; + private static JTextArea text; + private static JScrollPane scroller; + + public static void main(String[] args) throws Throwable { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(100); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + text.requestFocus(); + } + }); + + toolkit.realSync(); + + // 4697612: pressing PgDn + PgUp should not alter caret position + Util.hitKeys(robot, KeyEvent.VK_HOME); + Util.hitKeys(robot, KeyEvent.VK_PAGE_DOWN); + + + int pos0 = getTextCaretPosition(); + int caretHeight = getTextCaretHeight(); + fontHeight = FONT_HEIGHT; + + // iterate two times, for different (even and odd) font height + for (int i = 0; i < 2; i++) { + + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + text.setFont(text.getFont().deriveFont(fontHeight)); + } + }); + + frameHeight = FRAME_HEIGHT; + + for (int j = 0; j < caretHeight; j++) { + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + frame.setSize(FRAME_WIDTH, frameHeight); + } + }); + + toolkit.realSync(); + + Util.hitKeys(robot, KeyEvent.VK_PAGE_DOWN); + Util.hitKeys(robot, KeyEvent.VK_PAGE_UP); + toolkit.realSync(); + + int pos = getTextCaretPosition(); + if (pos0 != pos) { + throw new RuntimeException("Failed 4697612: PgDn & PgUp keys scroll by different amounts"); + } + frameHeight++; + } + fontHeight++; + } + + + // 6244705: pressing PgDn at the very bottom should not scroll + LookAndFeel laf = UIManager.getLookAndFeel(); + if (laf.getID().equals("Aqua")) { + Util.hitKeys(robot, KeyEvent.VK_END); + } else { + Util.hitKeys(robot, KeyEvent.VK_CONTROL, KeyEvent.VK_END); + } + + toolkit.realSync(); + + pos0 = getScrollerViewPosition(); + Util.hitKeys(robot, KeyEvent.VK_PAGE_DOWN); + toolkit.realSync(); + + int pos = getScrollerViewPosition(); + + if (pos0 != pos) { + throw new RuntimeException("Failed 6244705: PgDn at the bottom causes scrolling"); + } + } + + private static int getTextCaretPosition() throws Exception { + final int[] result = new int[1]; + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + result[0] = text.getCaretPosition(); + } + }); + + return result[0]; + } + + private static int getTextCaretHeight() throws Exception { + final int[] result = new int[1]; + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + int pos0 = text.getCaretPosition(); + Rectangle dotBounds = text.modelToView(pos0); + result[0] = dotBounds.height; + } catch (BadLocationException ex) { + throw new RuntimeException(ex); + } + } + }); + + return result[0]; + } + + private static int getScrollerViewPosition() throws Exception { + final int[] result = new int[1]; + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + result[0] = scroller.getViewport().getViewPosition().y; + } + }); + + return result[0]; + } + + private static void createAndShowGUI() { + frame = new JFrame(); + frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + text = new JTextArea(); + try { + InputStream is = + bug4697612.class.getResourceAsStream("bug4697612.txt"); + text.read(new InputStreamReader(is), null); + } catch (IOException e) { + throw new Error(e); + } + + scroller = new JScrollPane(text); + + frame.getContentPane().add(scroller); + + frame.pack(); + frame.setVisible(true); + } +} diff --git a/jdk/test/javax/swing/JTextArea/4697612/bug4697612.txt b/jdk/test/javax/swing/JTextArea/4697612/bug4697612.txt new file mode 100644 index 00000000000..55641054e54 --- /dev/null +++ b/jdk/test/javax/swing/JTextArea/4697612/bug4697612.txt @@ -0,0 +1,223 @@ + README + + Java(TM) 2 SDK, Standard Edition + Version 1.4.2 Beta + + For a more extensive HTML version of this file, see README.html. + +Contents + + * Introduction + * Release Notes + * Bug Reports and Feedback + * Java 2 SDK Documentation + * Redistribution + * Web Pages + + +Introduction + + Thank you for downloading this release of the Java(TM) 2 SDK, + Standard Edition. The Java 2 SDK is a development environment for + building applications, applets, and components that can be + deployed on the Java platform. + + The Java 2 SDK software includes tools useful for developing and + testing programs written in the Java programming language and + running on the Java platform. These tools are designed to be used + from the command line. Except for appletviewer, these tools do not + provide a graphical user interface. + + +Release Notes + + See the Release Notes on the Java Software web site for additional + information pertaining to this release. + + http://java.sun.com/j2se/1.4.2/relnotes.html + + The on-line release notes will be updated as needed, so you should + check it occasionally for the latest information. + + +Bug Reports and Feedback + + The Bug Parade Web Page on the Java Developer Connection(SM) web + site lets you search for and examine existing bug reports, submit + your own bug reports, and tell us which bug fixes matter most to you. + + http://java.sun.com/jdc/bugParade/ + + To directly submit a bug or request a feature, fill out this form: + + http://java.sun.com/cgi-bin/bugreport.cgi + + You can also send comments directly to Java Software engineering + team email addresses. + + http://java.sun.com/mail/ + + +Java 2 SDK Documentation + + The on-line Java 2 SDK Documentation contains API specifications, + feature descriptions, developer guides, tool reference pages, demos, + and links to related information. It is located at + + http://java.sun.com/j2se/1.4.2/docs/ + + The Java 2 SDK documentation is also available in a download bundle + which you can install locally on your machine. See the + Java 2 SDK download page: + + http://java.sun.com/j2se/1.4.2/download.html + + +Redistribution + + The term "vendors" used here refers to licensees, developers, + and independent software vendors (ISVs) who license and + distribute the Java 2 Runtime Environment with their programs. + Vendors must follow the terms of the Java 2 SDK, Standard + Edition, Binary Code License agreement. + Required vs. Optional Files + + The files that make up the Java 2 SDK, Standard Edition, are + divided into two categories: required and optional. Optional + files may be excluded from redistributions of the Java 2 SDK + at the vendor's discretion. The following section contains a + list of the files and directories that may optionally be + omitted from redistributions of the Java 2 SDK. All files not + in these lists of optional files must be included in + redistributions of the Java 2 SDK. + + Optional Files and Directories + + The following files may be optionally excluded from + redistributions: + + jre/lib/charsets.jar + Character conversion classes + jre/lib/ext/ + sunjce_provider.jar - the SunJCE provider for Java + Cryptography APIs + localedata.jar - contains many of the resources + needed for non US English locales + ldapsec.jar - contains security features supported + by the LDAP service provider + dnsns.jar - for the InetAddress wrapper of JNDI DNS + provider + bin/rmid and jre/bin/rmid + Java RMI Activation System Daemon + bin/rmiregistry and jre/bin/rmiregistry + Java Remote Object Registry + bin/tnameserv and jre/bin/tnameserv + Java IDL Name Server + bin/keytool and jre/bin/keytool + Key and Certificate Management Tool + bin/kinit and jre/bin/kinit + Used to obtain and cache Kerberos ticket-granting tickets + bin/klist and jre/bin/klist + Kerberos display entries in credentials cache and keytab + bin/ktab and jre/bin/ktab + Kerberos key table manager + bin/policytool and jre/bin/policytool + Policy File Creation and Management Tool + bin/orbd and jre/bin/orbd + Object Request Broker Daemon + bin/servertool and jre/bin/servertool + Java IDL Server Tool + src.zip + Archive of source files + + In addition, the Java Web Start product may be excluded from + redistributions. The Java Web Start product is contained in a + file named javaws-1_2-solaris-sparc-i.zip, + javaws-1_2-solaris-i586-i.zip, + javaws-1_2-linux-i586-i.zip, or + javaws-1_2-windows-i586-i.exe, depending on the platform. + + + Unlimited Strength Java Cryptography Extension + + Due to import control restrictions for some countries, the + Java Cryptography Extension (JCE) policy files shipped with + the Java 2 SDK, Standard Edition and the Java 2 Runtime + Environment allow strong but limited cryptography to be + used. These files are located at + + /lib/security/local_policy.jar + /lib/security/US_export_policy.jar + + where is the jre directory of the Java 2 + SDK or the top-level directory of the Java 2 Runtime + Environment. + + An unlimited strength version of these files indicating + no restrictions on cryptographic strengths is available + on the Java 2 SDK web site for those living in eligible + countries. Those living in eligible countries may download + the unlimited strength version and replace the strong + cryptography jar files with the unlimited strength files. + + + Endorsed Standards Override Mechanism + + An endorsed standard is a Java API defined through a standards + process other than the Java Community Process(SM) (JCP(SM)). + Because endorsed standards are defined outside the JCP, it is + anticipated that such standards will be revised between + releases of the Java 2 Platform. In order to take advantage of + new revisions to endorsed standards, developers and software + vendors may use the Endorsed Standards Override Mechanism to + provide newer versions of an endorsed standard than those + included in the Java 2 Platform as released by Sun Microsystems. + + For more information on the Endorsed Standards Override + Mechanism, including the list of platform packages that it may + be used to override, see + + http://java.sun.com/j2se/1.4.2/docs/guide/standards/ + + Classes in the packages listed on that web page may be replaced + only by classes implementing a more recent version of the API + as defined by the appropriate standards body. + + In addition to the packages listed in the document at the above + URL, which are part of the Java 2 Platform, Standard Edition + (J2SE(TM)) specification, redistributors of Sun's J2SE + Reference Implementation are allowed to override classes whose + sole purpose is to implement the functionality provided by + public APIs defined in these Endorsed Standards packages. + Redistributors may also override classes in the org.w3c.dom.* + packages, or other classes whose sole purpose is to implement + these APIs. + + +Sun Java Web Pages + + For additional information, refer to these Sun Microsystems pages + on the World Wide Web: + + http://java.sun.com/ + The Java Software web site, with the latest information on + Java technology, product information, news, and features. + http://java.sun.com/docs + Java Platform Documentation provides access to white papers, + the Java Tutorial and other documents. + http://java.sun.com/jdc + The Java Developer Connection(SM) web site. (Free registration + required.) Additional technical information, news, and + features; user forums; support information, and much more. + http://java.sun.com/products/ + Java Technology Products & API + + +------------------------------------------------------------------------ +The Java 2 SDK, Standard Edition, is a product of Sun Microsystems(TM), +Inc. This product includes code licensed from RSA Security. + +Copyright 2003 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +California 95054, U.S.A. All rights reserved. + + From 5c8b083c663667fd307cd3590adfa46cb9248cc9 Mon Sep 17 00:00:00 2001 From: Charles Lee Date: Fri, 13 Jan 2012 13:20:02 +0000 Subject: [PATCH 34/96] 7129029: (fs) Unix file system provider should be buildable on platforms that don't support O_NOFOLLOW Reviewed-by: alanb --- .../classes/sun/nio/fs/UnixChannelFactory.java | 15 +++++++++++---- .../sun/nio/fs/UnixFileSystemProvider.java | 2 +- .../classes/sun/nio/fs/UnixNativeDispatcher.java | 4 ++++ jdk/src/solaris/classes/sun/nio/fs/UnixPath.java | 5 ++++- .../solaris/native/sun/nio/fs/genUnixConstants.c | 5 +++++ 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java b/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java index 963e3777bdf..d7a1f8b0310 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java @@ -36,8 +36,6 @@ import sun.nio.ch.SimpleAsynchronousFileChannelImpl; import sun.misc.SharedSecrets; import sun.misc.JavaIOFileDescriptorAccess; -import com.sun.nio.file.ExtendedOpenOption; - import static sun.nio.fs.UnixNativeDispatcher.*; import static sun.nio.fs.UnixConstants.*; @@ -86,13 +84,13 @@ class UnixChannelFactory { } continue; } - if (option == LinkOption.NOFOLLOW_LINKS) { + if (option == LinkOption.NOFOLLOW_LINKS && supportsNoFollowLinks()) { flags.noFollowLinks = true; continue; } if (option == null) throw new NullPointerException(); - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException(option + " not supported"); } return flags; } @@ -220,6 +218,15 @@ class UnixChannelFactory { // follow links by default boolean followLinks = true; if (!flags.createNew && (flags.noFollowLinks || flags.deleteOnClose)) { + if (flags.deleteOnClose && !supportsNoFollowLinks()) { + try { + if (UnixFileAttributes.get(path, false).isSymbolicLink()) + throw new UnixException("DELETE_ON_CLOSE specified and file is a symbolic link"); + } catch (UnixException x) { + if (!flags.create || x.errno() != ENOENT) + throw x; + } + } followLinks = false; oflags |= O_NOFOLLOW; } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java index 0c14ef02e7e..ea9df0c1fdc 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java @@ -395,7 +395,7 @@ public abstract class UnixFileSystemProvider // can't return SecureDirectoryStream on kernels that don't support // openat, etc. - if (!supportsAtSysCalls()) { + if (!supportsAtSysCalls() || !supportsNoFollowLinks()) { try { long ptr = opendir(dir); return new UnixDirectoryStream(dir, ptr, filter); diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java b/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java index 2d037f303ad..88659888566 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -548,6 +548,10 @@ class UnixNativeDispatcher { return hasAtSysCalls; } + static boolean supportsNoFollowLinks() { + return UnixConstants.O_NOFOLLOW != 0; + } + // initialize syscalls and fieldIDs private static native int init(); diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java index 30c4dfe6501..52b88416eb7 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java @@ -767,8 +767,11 @@ class UnixPath // package-private int openForAttributeAccess(boolean followLinks) throws IOException { int flags = O_RDONLY; - if (!followLinks) + if (!followLinks) { + if (!supportsNoFollowLinks()) + throw new IOException("NOFOLLOW_LINKS is not supported on this platform"); flags |= O_NOFOLLOW; + } try { return open(this, flags, 0); } catch (UnixException x) { diff --git a/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c index 56984a7e352..769982859bc 100644 --- a/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c +++ b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c @@ -64,7 +64,12 @@ int main(int argc, const char* argv[]) { DEFX(O_TRUNC); DEFX(O_SYNC); DEFX(O_DSYNC); +#ifdef O_NOFOLLOW DEFX(O_NOFOLLOW); +#else + // not supported (dummy values will not be used at runtime). + emitX("O_NOFOLLOW", 0x0); +#endif // mode masks emitX("S_IAMB", From 3b8a1fee1dfd839a5cc60ae9af3c0f6fe6ba6257 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 13 Jan 2012 13:11:08 -0800 Subject: [PATCH 35/96] 7127827: JRE8: javaws fails to launch on oracle linux due to XRender Reviewed-by: bae, jgodinez --- .../classes/sun/java2d/xr/XRCompositeManager.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java b/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java index b4b8c4c15e0..1264d539611 100644 --- a/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java +++ b/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java @@ -28,6 +28,9 @@ package sun.java2d.xr; import java.awt.*; import java.awt.geom.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + import sun.font.*; import sun.java2d.*; import sun.java2d.jules.*; @@ -83,7 +86,13 @@ public class XRCompositeManager { con = new XRBackendNative(); // con = XRBackendJava.getInstance(); - String gradProp = System.getProperty("sun.java2d.xrgradcache"); + String gradProp = + AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty("sun.java2d.xrgradcache"); + } + }); + enableGradCache = gradProp == null || !(gradProp.equalsIgnoreCase("false") || gradProp.equalsIgnoreCase("f")); From b4dae5f5775334d8ca0ce5ccd0efebd8ab3c6403 Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Sat, 14 Jan 2012 00:52:39 -0800 Subject: [PATCH 36/96] 7129512: new hotspot build - hs23-b11 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 75a0f4c2b14..82956ba6a29 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011 HS_MAJOR_VER=23 HS_MINOR_VER=0 -HS_BUILD_NUMBER=10 +HS_BUILD_NUMBER=11 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From 5cbd245badd10d133a64801e7ea359001966cdda Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 16 Jan 2012 10:10:56 +0800 Subject: [PATCH 37/96] 7118809: rcache deadlock Reviewed-by: valeriep --- .../krb5/internal/rcache/CacheTable.java | 11 +-- .../krb5/internal/rcache/ReplayCache.java | 16 +--- jdk/test/sun/security/krb5/auto/Context.java | 77 +++++++------------ .../sun/security/krb5/auto/ReplayCache.java | 64 +++++++++++++++ 4 files changed, 100 insertions(+), 68 deletions(-) create mode 100644 jdk/test/sun/security/krb5/auto/ReplayCache.java diff --git a/jdk/src/share/classes/sun/security/krb5/internal/rcache/CacheTable.java b/jdk/src/share/classes/sun/security/krb5/internal/rcache/CacheTable.java index e18bc6c4816..ac1879adba7 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/rcache/CacheTable.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/rcache/CacheTable.java @@ -31,8 +31,6 @@ package sun.security.krb5.internal.rcache; import java.util.Hashtable; -import sun.security.krb5.internal.KerberosTime; - /** * This class implements Hashtable to store the replay caches. @@ -60,12 +58,15 @@ public class CacheTable extends Hashtable { } rc = new ReplayCache(principal, this); rc.put(time, currTime); - super.put(principal, rc); + if (!rc.isEmpty()) { + super.put(principal, rc); + } } else { rc.put(time, currTime); - // re-insert the entry, since rc.put could have removed the entry - super.put(principal, rc); + if (rc.isEmpty()) { + super.remove(rc); + } if (DEBUG) { System.out.println("replay cache found."); } diff --git a/jdk/src/share/classes/sun/security/krb5/internal/rcache/ReplayCache.java b/jdk/src/share/classes/sun/security/krb5/internal/rcache/ReplayCache.java index bcb1d46aaa0..97b8efe7c3d 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/rcache/ReplayCache.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/rcache/ReplayCache.java @@ -31,8 +31,6 @@ package sun.security.krb5.internal.rcache; -import sun.security.krb5.KrbException; -import sun.security.krb5.Config; import sun.security.krb5.internal.Krb5; import java.util.LinkedList; import java.util.ListIterator; @@ -48,10 +46,13 @@ public class ReplayCache extends LinkedList { private static final long serialVersionUID = 2997933194993803994L; + // These 3 fields are now useless, keep for serialization compatibility private String principal; private CacheTable table; private int nap = 10 * 60 * 1000; //10 minutes break + private boolean DEBUG = Krb5.DEBUG; + /** * Constructs a ReplayCache for a client principal in specified CacheTable. * @param p client principal name. @@ -125,20 +126,11 @@ public class ReplayCache extends LinkedList { if (DEBUG) { printList(); } - - // if there are no entries in the replay cache, - // remove the replay cache from the table. - if (this.size() == 0) { - table.remove(principal); - } - if (DEBUG) { - printList(); - } } /** - * Printes out the debug message. + * Prints out the debug message. */ private void printList() { Object[] total = toArray(); diff --git a/jdk/test/sun/security/krb5/auto/Context.java b/jdk/test/sun/security/krb5/auto/Context.java index eb2a94a1e7d..c4c0cbcc4e7 100644 --- a/jdk/test/sun/security/krb5/auto/Context.java +++ b/jdk/test/sun/security/krb5/auto/Context.java @@ -76,7 +76,6 @@ public class Context { private Subject s; private ExtendedGSSContext x; - private boolean f; // context established? private String name; private GSSCredential cred; // see static method delegated(). @@ -194,7 +193,6 @@ public class Context { return null; } }, null); - f = false; } /** @@ -228,7 +226,6 @@ public class Context { return null; } }, null); - f = false; } /** @@ -502,6 +499,29 @@ public class Context { return sb.toString(); } + public byte[] take(final byte[] in) throws Exception { + return doAs(new Action() { + @Override + public byte[] run(Context me, byte[] input) throws Exception { + if (me.x.isEstablished()) { + System.out.println(name + " side established"); + if (input != null) { + throw new Exception("Context established but " + + "still receive token at " + name); + } + return null; + } else { + System.out.println(name + " call initSecContext"); + if (me.x.isInitiator()) { + return me.x.initSecContext(input, 0, input.length); + } else { + return me.x.acceptSecContext(input, 0, input.length); + } + } + } + }, in); + } + /** * Handshake (security context establishment process) between two Contexts * @param c the initiator @@ -510,54 +530,9 @@ public class Context { */ static public void handshake(final Context c, final Context s) throws Exception { byte[] t = new byte[0]; - while (!c.f || !s.f) { - t = c.doAs(new Action() { - @Override - public byte[] run(Context me, byte[] input) throws Exception { - if (me.x.isEstablished()) { - me.f = true; - System.out.println(c.name + " side established"); - if (input != null) { - throw new Exception("Context established but " + - "still receive token at " + c.name); - } - return null; - } else { - System.out.println(c.name + " call initSecContext"); - if (usingStream) { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - me.x.initSecContext(new ByteArrayInputStream(input), os); - return os.size() == 0 ? null : os.toByteArray(); - } else { - return me.x.initSecContext(input, 0, input.length); - } - } - } - }, t); - - t = s.doAs(new Action() { - @Override - public byte[] run(Context me, byte[] input) throws Exception { - if (me.x.isEstablished()) { - me.f = true; - System.out.println(s.name + " side established"); - if (input != null) { - throw new Exception("Context established but " + - "still receive token at " + s.name); - } - return null; - } else { - System.out.println(s.name + " called acceptSecContext"); - if (usingStream) { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - me.x.acceptSecContext(new ByteArrayInputStream(input), os); - return os.size() == 0 ? null : os.toByteArray(); - } else { - return me.x.acceptSecContext(input, 0, input.length); - } - } - } - }, t); + while (!c.x.isEstablished() || !s.x.isEstablished()) { + t = c.take(t); + t = s.take(t); } } } diff --git a/jdk/test/sun/security/krb5/auto/ReplayCache.java b/jdk/test/sun/security/krb5/auto/ReplayCache.java new file mode 100644 index 00000000000..1f6411cfdad --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/ReplayCache.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 7118809 + * @run main/othervm ReplayCache + * @summary rcache deadlock + */ + +import org.ietf.jgss.GSSException; +import sun.security.jgss.GSSUtil; +import sun.security.krb5.KrbException; +import sun.security.krb5.internal.Krb5; + +public class ReplayCache { + + public static void main(String[] args) + throws Exception { + + new OneKDC(null).writeJAASConf(); + + Context c, s; + c = Context.fromJAAS("client"); + s = Context.fromJAAS("server"); + + c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + + byte[] first = c.take(new byte[0]); + s.take(first); + + s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + try { + s.take(first); // Replay the last token sent + throw new Exception("This method should fail"); + } catch (GSSException gsse) { + KrbException ke = (KrbException)gsse.getCause(); + if (ke.returnCode() != Krb5.KRB_AP_ERR_REPEAT) { + throw gsse; + } + } + } +} From e6ade0739df107340afb8b9f653374b77b107ed7 Mon Sep 17 00:00:00 2001 From: David Buck Date: Mon, 16 Jan 2012 11:52:51 +0400 Subject: [PATCH 38/96] 7083621: Add fontconfig file for OEL6 and rename RH/O EL 5 file so that it is picked up for all 5.x updates Reviewed-by: bae, prr --- jdk/make/sun/awt/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/make/sun/awt/Makefile b/jdk/make/sun/awt/Makefile index 071c36223cf..099daf17348 100644 --- a/jdk/make/sun/awt/Makefile +++ b/jdk/make/sun/awt/Makefile @@ -367,7 +367,8 @@ else FONTCONFIGS_SRC = $(CLOSED_SRC)/solaris/classes/sun/awt/fontconfigs _FONTCONFIGS = \ fontconfig.properties \ - fontconfig.RedHat.5.5.properties \ + fontconfig.RedHat.5.properties \ + fontconfig.RedHat.6.properties \ fontconfig.Turbo.properties \ fontconfig.SuSE.10.properties \ fontconfig.SuSE.11.properties From e20614ed03a23092e39ab18bc37c04a18ecd1db8 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 16 Jan 2012 18:28:56 +0400 Subject: [PATCH 39/96] 7122740: PropertyDescriptor Performance Slow Reviewed-by: rupashka --- .../classes/com/sun/beans/TypeResolver.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/classes/com/sun/beans/TypeResolver.java b/jdk/src/share/classes/com/sun/beans/TypeResolver.java index 8660213a050..baba362c4bc 100644 --- a/jdk/src/share/classes/com/sun/beans/TypeResolver.java +++ b/jdk/src/share/classes/com/sun/beans/TypeResolver.java @@ -154,7 +154,7 @@ public final class TypeResolver { * @see #resolve(Type) */ public static Type resolve(Type actual, Type formal) { - return new TypeResolver(actual).resolve(formal); + return getTypeResolver(actual).resolve(formal); } /** @@ -169,7 +169,7 @@ public final class TypeResolver { * @see #resolve(Type[]) */ public static Type[] resolve(Type actual, Type[] formals) { - return new TypeResolver(actual).resolve(formals); + return getTypeResolver(actual).resolve(formals); } /** @@ -228,9 +228,20 @@ public final class TypeResolver { return classes; } + public static TypeResolver getTypeResolver(Type type) { + synchronized (CACHE) { + TypeResolver resolver = CACHE.get(type); + if (resolver == null) { + resolver = new TypeResolver(type); + CACHE.put(type, resolver); + } + return resolver; + } + } - private final Map, Type> map - = new HashMap, Type>(); + private static final WeakCache CACHE = new WeakCache<>(); + + private final Map, Type> map = new HashMap<>(); /** * Constructs the type resolver for the given actual type. From 3fc15f302b2a96d11f944e1de741e1b67aab989a Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Mon, 16 Jan 2012 16:30:29 +0000 Subject: [PATCH 40/96] 7130398: ProblemList.txt updates (1/2012) Reviewed-by: chegar --- jdk/test/ProblemList.txt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5e0d3743a01..8ec2737552f 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -195,19 +195,22 @@ java/beans/XMLEncoder/6329581/Test6329581.java generic-all # jdk_lang +# 7123972 +java/lang/annotation/loaderLeak/Main.java generic-all + # 7079093 java/lang/instrument/ManifestTest.sh windows-all -############################################################################ - -# jdk_management - # 6944188 java/lang/management/ThreadMXBean/ThreadStateTest.java generic-all # 7067973 java/lang/management/MemoryMXBean/CollectionUsageThreshold.java generic-all +############################################################################ + +# jdk_management + # Failing, bug was filed: 6959636 javax/management/loading/LibraryLoader/LibraryLoaderTest.java generic-all @@ -289,6 +292,9 @@ javax/management/monitor/AttributeArbitraryDataTypeTest.java generic-all # jdk_misc +# 6988950 +demo/jvmti/compiledMethodLoad/CompiledMethodLoadTest.java generic-all + # Need to be marked othervm, or changed to be samevm safe com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java generic-all From c77eb16a790375c6fa4b712683f2767b3225761d Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Mon, 16 Jan 2012 18:05:29 +0000 Subject: [PATCH 41/96] 7129083: CookieManager does not store cookies if url is read before setting cookie manager Reviewed-by: michaelm --- .../classes/sun/net/www/http/HttpClient.java | 11 +- .../www/protocol/http/HttpURLConnection.java | 4 + .../net/www/protocol/https/HttpsClient.java | 8 - .../http/HttpClient/CookieHttpClientTest.java | 112 +++++++ .../CookieHttpsClientTest.java | 283 ++++++++++++++++++ 5 files changed, 400 insertions(+), 18 deletions(-) create mode 100644 jdk/test/sun/net/www/http/HttpClient/CookieHttpClientTest.java create mode 100644 jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java diff --git a/jdk/src/share/classes/sun/net/www/http/HttpClient.java b/jdk/src/share/classes/sun/net/www/http/HttpClient.java index fa8184f5927..140cc9191f2 100644 --- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java +++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java @@ -47,8 +47,6 @@ public class HttpClient extends NetworkClient { private boolean inCache; - protected CookieHandler cookieHandler; - // Http requests we send MessageHeader requests; @@ -201,14 +199,6 @@ public class HttpClient extends NetworkClient { } setConnectTimeout(to); - // get the cookieHandler if there is any - cookieHandler = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public CookieHandler run() { - return CookieHandler.getDefault(); - } - }); - capture = HttpCapture.getCapture(url); openServer(); } @@ -656,6 +646,7 @@ public class HttpClient extends NetworkClient { // we've finished parsing http headers // check if there are any applicable cookies to set (in cache) + CookieHandler cookieHandler = httpuc.getCookieHandler(); if (cookieHandler != null) { URI uri = ParseUtil.toURI(url); // NOTE: That cast from Map shouldn't be necessary but diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 8e894c7188e..719ddc46a74 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -2903,6 +2903,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection { return readTimeout < 0 ? 0 : readTimeout; } + public CookieHandler getCookieHandler() { + return cookieHandler; + } + String getMethod() { return method; } diff --git a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java index c83860b14c6..fe570d4b9db 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java @@ -36,7 +36,6 @@ import java.net.URL; import java.net.UnknownHostException; import java.net.InetSocketAddress; import java.net.Proxy; -import java.net.CookieHandler; import java.security.Principal; import java.security.cert.*; import java.util.StringTokenizer; @@ -268,13 +267,6 @@ final class HttpsClient extends HttpClient port = getDefaultPort(); } setConnectTimeout(connectTimeout); - // get the cookieHandler if there is any - cookieHandler = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public CookieHandler run() { - return CookieHandler.getDefault(); - } - }); openServer(); } diff --git a/jdk/test/sun/net/www/http/HttpClient/CookieHttpClientTest.java b/jdk/test/sun/net/www/http/HttpClient/CookieHttpClientTest.java new file mode 100644 index 00000000000..e2c14229302 --- /dev/null +++ b/jdk/test/sun/net/www/http/HttpClient/CookieHttpClientTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7129083 + * @summary Cookiemanager does not store cookies if url is read + * before setting cookiemanager + */ + +import java.net.CookieHandler; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; +import java.io.InputStream; +import java.io.IOException; + +public class CookieHttpClientTest implements Runnable { + final ServerSocket ss; + static final int TIMEOUT = 10 * 1000; + + static final String replyString = "HTTP/1.1 200 OK\r\n" + + "Set-Cookie: name=test\r\n" + + "Content-Length: 10\r\n\r\n" + + "1234567890"; + + // HTTP server, reply with Set-Cookie + @Override + public void run() { + Socket s = null; + try { + s = ss.accept(); + s.setSoTimeout(TIMEOUT); + readOneRequest(s.getInputStream()); + s.getOutputStream().write(replyString.getBytes()); + + readOneRequest(s.getInputStream()); + s.getOutputStream().write(replyString.getBytes()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { if (s != null) { s.close(); } ss.close(); } + catch (IOException unused) { /* gulp!burp! */ } + } + } + + static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n' }; + + // Read until the end of a HTTP request + static void readOneRequest(InputStream is) throws IOException { + int requestEndCount = 0, r; + while ((r = is.read()) != -1) { + if (r == requestEnd[requestEndCount]) { + requestEndCount++; + if (requestEndCount == 4) { + break; + } + } else { + requestEndCount = 0; + } + } + } + + CookieHttpClientTest() throws Exception { + /* start the server */ + ss = new ServerSocket(0); + (new Thread(this)).start(); + + URL url = new URL("http://localhost:" + ss.getLocalPort() +"/"); + + // Run without a CookieHandler first + InputStream in = url.openConnection().getInputStream(); + while (in.read() != -1); // read response body so connection can be reused + + // Set a CookeHandler and retest using the HttpClient from the KAC + CookieManager manager = new CookieManager(null, CookiePolicy.ACCEPT_ALL); + CookieHandler.setDefault(manager); + + in = url.openConnection().getInputStream(); + while (in.read() != -1); + + if (manager.getCookieStore().getCookies().isEmpty()) { + throw new RuntimeException("Failed: No cookies in the cookie Handler."); + } + } + + public static void main(String args[]) throws Exception { + new CookieHttpClientTest(); + } +} diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java new file mode 100644 index 00000000000..6996ca06359 --- /dev/null +++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7129083 + * @summary Cookiemanager does not store cookies if url is read + * before setting cookiemanager + */ + +import java.net.CookieHandler; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.net.URL; +import java.io.InputStream; +import java.io.IOException; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; + +public class CookieHttpsClientTest { + static final int TIMEOUT = 10 * 1000; + + static final String replyString = "HTTP/1.1 200 OK\r\n" + + "Set-Cookie: name=test\r\n" + + "Content-Length: 10\r\n\r\n" + + "1234567890"; + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + static boolean separateServerThread = true; + + /* + * Where do we find the keystores? + */ + static String pathToStores = "../../../../../../etc"; + static String keyStoreFile = "keystore"; + static String trustStoreFile = "truststore"; + static String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + SSLServerSocket sslServerSocket = + (SSLServerSocket) sslssf.createServerSocket(serverPort); + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + SSLSocket sslSocket = null; + try { + sslSocket = (SSLSocket) sslServerSocket.accept(); + sslSocket.setSoTimeout(TIMEOUT); + readOneRequest(sslSocket.getInputStream()); + sslSocket.getOutputStream().write(replyString.getBytes()); + + readOneRequest(sslSocket.getInputStream()); + sslSocket.getOutputStream().write(replyString.getBytes()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (sslSocket != null) { sslSocket.close(); } + sslServerSocket.close(); + } catch (IOException unused) { /* gulp!burp! */ } + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doClientSide() throws Exception { + // Wait for server to get started. + while (!serverReady) { + Thread.sleep(50); + } + + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + }}); + + URL url = new URL("https://localhost:" + serverPort +"/"); + + // Run without a CookieHandler first + InputStream in = url.openConnection().getInputStream(); + while (in.read() != -1); // read response body so connection can be reused + + // Set a CookeHandler and retest using the HttpClient from the KAC + CookieManager manager = new CookieManager(null, CookiePolicy.ACCEPT_ALL); + CookieHandler.setDefault(manager); + + in = url.openConnection().getInputStream(); + while (in.read() != -1); + + if (manager.getCookieStore().getCookies().isEmpty()) { + throw new RuntimeException("Failed: No cookies in the cookie Handler."); + } + } + + static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n' }; + + // Read until the end of a HTTP request + static void readOneRequest(InputStream is) throws IOException { + int requestEndCount = 0, r; + while ((r = is.read()) != -1) { + if (r == requestEnd[requestEndCount]) { + requestEndCount++; + if (requestEndCount == 4) { + break; + } + } else { + requestEndCount = 0; + } + } + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + volatile int serverPort = 0; + + volatile Exception serverException = null; + volatile Exception clientException = null; + + public static void main(String args[]) throws Exception { + String keyFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) + System.setProperty("javax.net.debug", "all"); + + new CookieHttpsClientTest(); + } + + Thread clientThread = null; + Thread serverThread = null; + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + CookieHttpsClientTest() throws Exception { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + serverThread.join(); + } else { + clientThread.join(); + } + + /* + * When we get here, the test is pretty much over. + * + * If the main thread excepted, that propagates back + * immediately. If the other thread threw an exception, we + * should report back. + */ + if (serverException != null) + throw serverException; + if (clientException != null) + throw clientException; + } + + void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + doServerSide(); + } + } + + void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + doClientSide(); + } + } +} From 8d3dc3ed375c5d2c73d272156c37efe1317f2a53 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 17 Jan 2012 14:10:04 +0000 Subject: [PATCH 42/96] 6671616: TEST_BUG: java/io/File/BlockIsDirectory.java fails when /dev/dsk empty (sol) Reviewed-by: alanb --- jdk/test/ProblemList.txt | 3 - jdk/test/java/io/File/BlockIsDirectory.java | 63 --------------------- 2 files changed, 66 deletions(-) delete mode 100644 jdk/test/java/io/File/BlockIsDirectory.java diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 8ec2737552f..2f4d91ee176 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -393,9 +393,6 @@ java/net/PortUnreachableException/OneExceptionOnly.java windows-all # 6962637 java/io/File/MaxPathLength.java windows-all -# 6671616 -java/io/File/BlockIsDirectory.java solaris-all - # 7076644 java/io/File/Basic.java windows-all diff --git a/jdk/test/java/io/File/BlockIsDirectory.java b/jdk/test/java/io/File/BlockIsDirectory.java deleted file mode 100644 index 40d16358f87..00000000000 --- a/jdk/test/java/io/File/BlockIsDirectory.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - @bug 4113217 - @summary Test File.isDirectory on block device - */ - -import java.io.*; -import java.util.*; - -public class BlockIsDirectory { - public static void main( String args[] ) throws Exception { - String osname = System.getProperty("os.name"); - if (osname.equals("SunOS")) { - File dir = new File("/dev/dsk"); - String dirList[] = dir.list(); - - File aFile = new File( "/dev/dsk/" + dirList[0] ); - - boolean result = aFile.isDirectory(); - if (result == true) - throw new RuntimeException( - "IsDirectory returns true for block device."); - } - if (osname.equals("Linux")) { - File dir = new File("/dev/ide0"); - if (dir.exists()) { - boolean result = dir.isDirectory(); - if (result == true) - throw new RuntimeException( - "IsDirectory returns true for block device."); - } - dir = new File("/dev/scd0"); - if (dir.exists()) { - boolean result = dir.isDirectory(); - if (result == true) - throw new RuntimeException( - "IsDirectory returns true for block device."); - } - } - } -} From 36b3d034d2c555204c244588444c739bcefe073b Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Tue, 17 Jan 2012 19:09:32 +0400 Subject: [PATCH 43/96] 7110590: DnDMerlinQLTestsuite_DnDJTextArea test fails with an java.awt.dnd.InvalidDnDOperationException Reviewed-by: art --- jdk/src/share/classes/java/awt/AWTKeyStroke.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/awt/AWTKeyStroke.java b/jdk/src/share/classes/java/awt/AWTKeyStroke.java index 13f6edd81f0..8966d753fb7 100644 --- a/jdk/src/share/classes/java/awt/AWTKeyStroke.java +++ b/jdk/src/share/classes/java/awt/AWTKeyStroke.java @@ -802,8 +802,11 @@ public class AWTKeyStroke implements Serializable { */ protected Object readResolve() throws java.io.ObjectStreamException { synchronized (AWTKeyStroke.class) { - return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease); + if (getClass().equals(getAWTKeyStrokeClass())) { + return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease); + } } + return this; } private static int mapOldModifiers(int modifiers) { From 43bb0877fc1af189ea3472ff6a55545cbccdd824 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Tue, 17 Jan 2012 13:08:52 -0500 Subject: [PATCH 44/96] 7071311: Decoder enhancement Made decoder thread-safe Reviewed-by: coleenp, kamg --- hotspot/src/os/bsd/vm/decoder_machO.cpp | 31 ++++ .../vm/{decoder_bsd.cpp => decoder_machO.hpp} | 46 ++---- hotspot/src/os/linux/vm/decoder_linux.cpp | 5 +- hotspot/src/os/linux/vm/os_linux.cpp | 2 +- hotspot/src/os/solaris/vm/decoder_solaris.cpp | 5 +- hotspot/src/os/solaris/vm/os_solaris.cpp | 4 +- hotspot/src/os/windows/vm/decoder_windows.cpp | 58 ++++---- hotspot/src/os/windows/vm/decoder_windows.hpp | 61 ++++++++ hotspot/src/os/windows/vm/os_windows.cpp | 2 +- hotspot/src/share/vm/utilities/decoder.cpp | 137 +++++++++--------- hotspot/src/share/vm/utilities/decoder.hpp | 113 +++++++-------- .../src/share/vm/utilities/decoder_elf.cpp | 76 ++++++++++ .../src/share/vm/utilities/decoder_elf.hpp | 55 +++++++ hotspot/src/share/vm/utilities/elfFile.cpp | 39 ++--- hotspot/src/share/vm/utilities/elfFile.hpp | 27 ++-- .../src/share/vm/utilities/elfStringTable.cpp | 21 +-- .../src/share/vm/utilities/elfStringTable.hpp | 22 +-- .../src/share/vm/utilities/elfSymbolTable.cpp | 24 +-- .../src/share/vm/utilities/elfSymbolTable.hpp | 16 +- hotspot/src/share/vm/utilities/vmError.cpp | 2 - 20 files changed, 471 insertions(+), 275 deletions(-) create mode 100644 hotspot/src/os/bsd/vm/decoder_machO.cpp rename hotspot/src/os/bsd/vm/{decoder_bsd.cpp => decoder_machO.hpp} (50%) create mode 100644 hotspot/src/os/windows/vm/decoder_windows.hpp create mode 100644 hotspot/src/share/vm/utilities/decoder_elf.cpp create mode 100644 hotspot/src/share/vm/utilities/decoder_elf.hpp diff --git a/hotspot/src/os/bsd/vm/decoder_machO.cpp b/hotspot/src/os/bsd/vm/decoder_machO.cpp new file mode 100644 index 00000000000..d77a32f7edd --- /dev/null +++ b/hotspot/src/os/bsd/vm/decoder_machO.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" + +#ifdef __APPLE__ +#include "decoder_machO.hpp" +#endif + + diff --git a/hotspot/src/os/bsd/vm/decoder_bsd.cpp b/hotspot/src/os/bsd/vm/decoder_machO.hpp similarity index 50% rename from hotspot/src/os/bsd/vm/decoder_bsd.cpp rename to hotspot/src/os/bsd/vm/decoder_machO.hpp index dd959298f17..48d0a9b98e0 100644 --- a/hotspot/src/os/bsd/vm/decoder_bsd.cpp +++ b/hotspot/src/os/bsd/vm/decoder_machO.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,45 +22,21 @@ * */ -#include "prims/jvm.h" -#include "utilities/decoder.hpp" - -#include +#ifndef OS_BSD_VM_DECODER_MACHO_HPP +#define OS_BSD_VM_DECODER_MACHO_HPP #ifdef __APPLE__ -void Decoder::initialize() { - _initialized = true; -} - -void Decoder::uninitialize() { - _initialized = false; -} - -bool Decoder::can_decode_C_frame_in_vm() { - return false; -} - -Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) { - return symbol_not_found; -} +#include "utilities/decoder.hpp" +// Just a placehold for now +class MachODecoder: public NullDecoder { +public: + MachODecoder() { } + ~MachODecoder() { } +}; #endif -bool Decoder::demangle(const char* symbol, char *buf, int buflen) { - int status; - char* result; - size_t size = (size_t)buflen; +#endif // OS_BSD_VM_DECODER_MACHO_HPP - // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small, - // __cxa_demangle will call system "realloc" for additional memory, which - // may use different malloc/realloc mechanism that allocates 'buf'. - if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) { - jio_snprintf(buf, buflen, "%s", result); - // call c library's free - ::free(result); - return true; - } - return false; -} diff --git a/hotspot/src/os/linux/vm/decoder_linux.cpp b/hotspot/src/os/linux/vm/decoder_linux.cpp index 88da33b65b3..e4623969456 100644 --- a/hotspot/src/os/linux/vm/decoder_linux.cpp +++ b/hotspot/src/os/linux/vm/decoder_linux.cpp @@ -23,11 +23,11 @@ */ #include "prims/jvm.h" -#include "utilities/decoder.hpp" +#include "utilities/decoder_elf.hpp" #include -bool Decoder::demangle(const char* symbol, char *buf, int buflen) { +bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) { int status; char* result; size_t size = (size_t)buflen; @@ -43,3 +43,4 @@ bool Decoder::demangle(const char* symbol, char *buf, int buflen) { } return false; } + diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 0946b753eab..f2e1988137b 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1732,7 +1732,7 @@ bool os::dll_address_to_function_name(address addr, char *buf, return true; } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + buf, buflen, offset, dlinfo.dli_fname)) { return true; } } diff --git a/hotspot/src/os/solaris/vm/decoder_solaris.cpp b/hotspot/src/os/solaris/vm/decoder_solaris.cpp index a7b4b51fb6a..d700706a067 100644 --- a/hotspot/src/os/solaris/vm/decoder_solaris.cpp +++ b/hotspot/src/os/solaris/vm/decoder_solaris.cpp @@ -22,10 +22,11 @@ * */ -#include "utilities/decoder.hpp" +#include "utilities/decoder_elf.hpp" #include -bool Decoder::demangle(const char* symbol, char *buf, int buflen) { +bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) { return !cplus_demangle(symbol, buf, (size_t)buflen); } + diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 925152c3bb1..939ef4229d3 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1997,7 +1997,7 @@ bool os::dll_address_to_function_name(address addr, char *buf, } if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + buf, buflen, offset, dlinfo.dli_fname)) { return true; } } @@ -2015,7 +2015,7 @@ bool os::dll_address_to_function_name(address addr, char *buf, return true; } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + buf, buflen, offset, dlinfo.dli_fname)) { return true; } } diff --git a/hotspot/src/os/windows/vm/decoder_windows.cpp b/hotspot/src/os/windows/vm/decoder_windows.cpp index 942f3ec20fa..847e2310840 100644 --- a/hotspot/src/os/windows/vm/decoder_windows.cpp +++ b/hotspot/src/os/windows/vm/decoder_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,22 +24,24 @@ #include "precompiled.hpp" #include "prims/jvm.h" -#include "runtime/os.hpp" -#include "utilities/decoder.hpp" +#include "decoder_windows.hpp" -HMODULE Decoder::_dbghelp_handle = NULL; -bool Decoder::_can_decode_in_vm = false; -pfn_SymGetSymFromAddr64 Decoder::_pfnSymGetSymFromAddr64 = NULL; -pfn_UndecorateSymbolName Decoder::_pfnUndecorateSymbolName = NULL; +WindowsDecoder::WindowsDecoder() { + _dbghelp_handle = NULL; + _can_decode_in_vm = false; + _pfnSymGetSymFromAddr64 = NULL; + _pfnUndecorateSymbolName = NULL; -void Decoder::initialize() { - if (!_initialized) { - _initialized = true; + _decoder_status = no_error; + initialize(); +} - HINSTANCE handle = os::win32::load_Windows_dll("dbghelp.dll", NULL, 0); +void WindowsDecoder::initialize() { + if (!has_error() && _dbghelp_handle == NULL) { + HMODULE handle = ::LoadLibrary("dbghelp.dll"); if (!handle) { _decoder_status = helper_not_found; - return; + return; } _dbghelp_handle = handle; @@ -70,32 +72,29 @@ void Decoder::initialize() { // find out if jvm.dll contains private symbols, by decoding // current function and comparing the result - address addr = (address)Decoder::initialize; + address addr = (address)Decoder::decode; char buf[MAX_PATH]; - if (decode(addr, buf, sizeof(buf), NULL) == no_error) { - _can_decode_in_vm = !strcmp(buf, "Decoder::initialize"); + if (decode(addr, buf, sizeof(buf), NULL)) { + _can_decode_in_vm = !strcmp(buf, "Decoder::decode"); } } } -void Decoder::uninitialize() { - assert(_initialized, "Decoder not yet initialized"); +void WindowsDecoder::uninitialize() { _pfnSymGetSymFromAddr64 = NULL; _pfnUndecorateSymbolName = NULL; if (_dbghelp_handle != NULL) { ::FreeLibrary(_dbghelp_handle); } - _initialized = false; + _dbghelp_handle = NULL; } -bool Decoder::can_decode_C_frame_in_vm() { - initialize(); - return _can_decode_in_vm; +bool WindowsDecoder::can_decode_C_frame_in_vm() const { + return (!has_error() && _can_decode_in_vm); } -Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int *offset) { - assert(_initialized, "Decoder not yet initialized"); +bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath) { if (_pfnSymGetSymFromAddr64 != NULL) { PIMAGEHLP_SYMBOL64 pSymbol; char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)]; @@ -105,19 +104,20 @@ Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int DWORD64 displacement; if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) { if (buf != NULL) { - if (!demangle(pSymbol->Name, buf, buflen)) { + if (demangle(pSymbol->Name, buf, buflen)) { jio_snprintf(buf, buflen, "%s", pSymbol->Name); } } - if (offset != NULL) *offset = (int)displacement; - return no_error; + if(offset != NULL) *offset = (int)displacement; + return true; } } - return helper_not_found; + if (buf != NULL && buflen > 0) buf[0] = '\0'; + if (offset != NULL) *offset = -1; + return false; } -bool Decoder::demangle(const char* symbol, char *buf, int buflen) { - assert(_initialized, "Decoder not yet initialized"); +bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) { return _pfnUndecorateSymbolName != NULL && _pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE); } diff --git a/hotspot/src/os/windows/vm/decoder_windows.hpp b/hotspot/src/os/windows/vm/decoder_windows.hpp new file mode 100644 index 00000000000..8ba488fc58e --- /dev/null +++ b/hotspot/src/os/windows/vm/decoder_windows.hpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_WINDOWS_VM_DECODER_WINDOWS_HPP +#define OS_WINDOWS_VM_DECIDER_WINDOWS_HPP + +#include +#include + +#include "utilities/decoder.hpp" + +// functions needed for decoding symbols +typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD); +typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL); +typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); +typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD); + +class WindowsDecoder: public NullDecoder { + +public: + WindowsDecoder(); + ~WindowsDecoder() { uninitialize(); }; + + bool can_decode_C_frame_in_vm() const; + bool demangle(const char* symbol, char *buf, int buflen); + bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath = NULL); + +private: + void initialize(); + void uninitialize(); + +private: + HMODULE _dbghelp_handle; + bool _can_decode_in_vm; + pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64; + pfn_UndecorateSymbolName _pfnUndecorateSymbolName; +}; + +#endif // OS_WINDOWS_VM_DECODER_WINDOWS_HPP + diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 889faf54010..56d51b6d608 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1391,7 +1391,7 @@ bool os::dll_address_to_library_name(address addr, char* buf, bool os::dll_address_to_function_name(address addr, char *buf, int buflen, int *offset) { - if (Decoder::decode(addr, buf, buflen, offset) == Decoder::no_error) { + if (Decoder::decode(addr, buf, buflen, offset)) { return true; } if (offset != NULL) *offset = -1; diff --git a/hotspot/src/share/vm/utilities/decoder.cpp b/hotspot/src/share/vm/utilities/decoder.cpp index ed156de23da..712c54cc736 100644 --- a/hotspot/src/share/vm/utilities/decoder.cpp +++ b/hotspot/src/share/vm/utilities/decoder.cpp @@ -24,80 +24,85 @@ #include "precompiled.hpp" #include "prims/jvm.h" +#include "runtime/mutexLocker.hpp" #include "utilities/decoder.hpp" -Decoder::decoder_status Decoder::_decoder_status = Decoder::no_error; -bool Decoder::_initialized = false; +#if defined(_WINDOWS) + #include "decoder_windows.hpp" +#elif defined(__APPLE__) + #include "decoder_machO.hpp" +#else + #include "decoder_elf.hpp" +#endif -#if !defined(_WINDOWS) && !defined(__APPLE__) +NullDecoder* Decoder::_decoder = NULL; +NullDecoder Decoder::_do_nothing_decoder; +Mutex* Decoder::_decoder_lock = new Mutex(Mutex::safepoint, + "DecoderLock"); -// Implementation of common functionalities among Solaris and Linux -#include "utilities/elfFile.hpp" +// _decoder_lock should already acquired before enter this method +NullDecoder* Decoder::get_decoder() { + assert(_decoder_lock != NULL && _decoder_lock->owned_by_self(), + "Require DecoderLock to enter"); -ElfFile* Decoder::_opened_elf_files = NULL; + if (_decoder != NULL) { + return _decoder; + } + + // Decoder is a secondary service. Although, it is good to have, + // but we can live without it. +#if defined(_WINDOWS) + _decoder = new (std::nothrow) WindowsDecoder(); +#elif defined (__APPLE__) + _decoder = new (std::nothrow)MachODecoder(); +#else + _decoder = new (std::nothrow)ElfDecoder(); +#endif + + if (_decoder == NULL || _decoder->has_error()) { + if (_decoder != NULL) { + delete _decoder; + } + _decoder = &_do_nothing_decoder; + } + return _decoder; +} + +bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + NullDecoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + + return decoder->decode(addr, buf, buflen, offset, modulepath); +} + +bool Decoder::demangle(const char* symbol, char* buf, int buflen) { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + NullDecoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + return decoder->demangle(symbol, buf, buflen); +} bool Decoder::can_decode_C_frame_in_vm() { - return true; + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + NullDecoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + return decoder->can_decode_C_frame_in_vm(); } -void Decoder::initialize() { - _initialized = true; +// shutdown real decoder and replace it with +// _do_nothing_decoder +void Decoder::shutdown() { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + + if (_decoder != NULL && _decoder != &_do_nothing_decoder) { + delete _decoder; + } + + _decoder = &_do_nothing_decoder; } -void Decoder::uninitialize() { - if (_opened_elf_files != NULL) { - delete _opened_elf_files; - _opened_elf_files = NULL; - } - _initialized = false; -} - -Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) { - if (_decoder_status != no_error) { - return _decoder_status; - } - - ElfFile* file = get_elf_file(filepath); - if (_decoder_status != no_error) { - return _decoder_status; - } - - const char* symbol = file->decode(addr, offset); - if (file->get_status() == out_of_memory) { - _decoder_status = out_of_memory; - return _decoder_status; - } else if (symbol != NULL) { - if (!demangle(symbol, buf, buflen)) { - jio_snprintf(buf, buflen, "%s", symbol); - } - return no_error; - } else { - return symbol_not_found; - } -} - -ElfFile* Decoder::get_elf_file(const char* filepath) { - if (_decoder_status != no_error) { - return NULL; - } - ElfFile* file = _opened_elf_files; - while (file != NULL) { - if (file->same_elf_file(filepath)) { - return file; - } - file = file->m_next; - } - - file = new ElfFile(filepath); - if (file == NULL) { - _decoder_status = out_of_memory; - } - if (_opened_elf_files != NULL) { - file->m_next = _opened_elf_files; - } - - _opened_elf_files = file; - return file; -} - -#endif diff --git a/hotspot/src/share/vm/utilities/decoder.hpp b/hotspot/src/share/vm/utilities/decoder.hpp index 70ffe21977f..82179a6863b 100644 --- a/hotspot/src/share/vm/utilities/decoder.hpp +++ b/hotspot/src/share/vm/utilities/decoder.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,83 +23,78 @@ */ -#ifndef __DECODER_HPP -#define __DECODER_HPP +#ifndef SHARE_VM_UTILITIES_DECODER_HPP +#define SHARE_VM_UTILITIES_DECODER_HPP #include "memory/allocation.hpp" +#include "runtime/mutex.hpp" -#ifdef _WINDOWS -#include -#include - -// functions needed for decoding symbols -typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD); -typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL); -typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); -typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD); - -#elif defined(__APPLE__) - -#else - -class ElfFile; - -#endif // _WINDOWS - - -class Decoder: public StackObj { - - public: +class NullDecoder: public CHeapObj { +public: // status code for decoding native C frame enum decoder_status { - no_error, // successfully decoded frames + not_available = -10, // real decoder is not available + no_error = 0, // successfully decoded frames out_of_memory, // out of memory file_invalid, // invalid elf file file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map helper_not_found, // could not load dbghelp.dll (Windows only) helper_func_error, // decoding functions not found (Windows only) - helper_init_error, // SymInitialize failed (Windows only) - symbol_not_found // could not find the symbol + helper_init_error // SymInitialize failed (Windows only) }; - public: - Decoder() { initialize(); }; - ~Decoder() { uninitialize(); }; + NullDecoder() { + _decoder_status = not_available; + } - static bool can_decode_C_frame_in_vm(); + ~NullDecoder() {}; - static void initialize(); - static void uninitialize(); + virtual bool decode(address pc, char* buf, int buflen, int* offset, + const char* modulepath = NULL) { + return false; + } -#ifdef _WINDOWS - static decoder_status decode(address addr, char *buf, int buflen, int *offset); -#else - static decoder_status decode(address addr, const char* filepath, char *buf, int buflen, int *offset); -#endif + virtual bool demangle(const char* symbol, char* buf, int buflen) { + return false; + } - static bool demangle(const char* symbol, char *buf, int buflen); + virtual bool can_decode_C_frame_in_vm() const { + return false; + } - static decoder_status get_status() { return _decoder_status; }; + virtual decoder_status status() const { + return _decoder_status; + } -#if !defined(_WINDOWS) && !defined(__APPLE__) - private: - static ElfFile* get_elf_file(const char* filepath); -#endif // _WINDOWS + virtual bool has_error() const { + return is_error(_decoder_status); + } + static bool is_error(decoder_status status) { + return (status > 0); + } - private: - static decoder_status _decoder_status; - static bool _initialized; - -#ifdef _WINDOWS - static HMODULE _dbghelp_handle; - static bool _can_decode_in_vm; - static pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64; - static pfn_UndecorateSymbolName _pfnUndecorateSymbolName; -#elif __APPLE__ -#else - static ElfFile* _opened_elf_files; -#endif // _WINDOWS +protected: + decoder_status _decoder_status; }; -#endif // __DECODER_HPP + +class Decoder: AllStatic { +public: + static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL); + static bool demangle(const char* symbol, char* buf, int buflen); + static bool can_decode_C_frame_in_vm(); + + static void shutdown(); +protected: + static NullDecoder* get_decoder(); + +private: + static NullDecoder* _decoder; + static NullDecoder _do_nothing_decoder; + +protected: + static Mutex* _decoder_lock; +}; + +#endif // SHARE_VM_UTILITIES_DECODER_HPP diff --git a/hotspot/src/share/vm/utilities/decoder_elf.cpp b/hotspot/src/share/vm/utilities/decoder_elf.cpp new file mode 100644 index 00000000000..d5733a8735a --- /dev/null +++ b/hotspot/src/share/vm/utilities/decoder_elf.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" + +#if !defined(_WINDOWS) && !defined(__APPLE__) +#include "decoder_elf.hpp" + +ElfDecoder::~ElfDecoder() { + if (_opened_elf_files != NULL) { + delete _opened_elf_files; + _opened_elf_files = NULL; + } +} + +bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* filepath) { + assert(filepath, "null file path"); + assert(buf != NULL && buflen > 0, "Invalid buffer"); + if (has_error()) return false; + ElfFile* file = get_elf_file(filepath); + if (file == NULL) { + return false; + } + + if (!file->decode(addr, buf, buflen, offset)) { + return false; + } + if (buf[0] != '\0') { + demangle(buf, buf, buflen); + } + return true; +} + +ElfFile* ElfDecoder::get_elf_file(const char* filepath) { + ElfFile* file; + + file = _opened_elf_files; + while (file != NULL) { + if (file->same_elf_file(filepath)) { + return file; + } + file = file->next(); + } + + file = new (std::nothrow)ElfFile(filepath); + if (file != NULL) { + if (_opened_elf_files != NULL) { + file->set_next(_opened_elf_files); + } + _opened_elf_files = file; + } + + return file; +} +#endif diff --git a/hotspot/src/share/vm/utilities/decoder_elf.hpp b/hotspot/src/share/vm/utilities/decoder_elf.hpp new file mode 100644 index 00000000000..f0dff753411 --- /dev/null +++ b/hotspot/src/share/vm/utilities/decoder_elf.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_UTILITIES_DECODER_ELF_HPP +#define SHARE_VM_UTILITIES_DECODER_ELF_HPP + +#if !defined(_WINDOWS) && !defined(__APPLE__) + +#include "utilities/decoder.hpp" +#include "utilities/elfFile.hpp" + +class ElfDecoder: public NullDecoder { + +public: + ElfDecoder() { + _opened_elf_files = NULL; + _decoder_status = no_error; + } + ~ElfDecoder(); + + bool can_decode_C_frame_in_vm() const { return true; } + + bool demangle(const char* symbol, char *buf, int buflen); + bool decode(address addr, char *buf, int buflen, int* offset, const char* filepath = NULL); + +private: + ElfFile* get_elf_file(const char* filepath); + +private: + ElfFile* _opened_elf_files; +}; + +#endif +#endif // SHARE_VM_UTILITIES_DECODER_ELF_HPP diff --git a/hotspot/src/share/vm/utilities/elfFile.cpp b/hotspot/src/share/vm/utilities/elfFile.cpp index 2db1f71e08d..2e4b68302e9 100644 --- a/hotspot/src/share/vm/utilities/elfFile.cpp +++ b/hotspot/src/share/vm/utilities/elfFile.cpp @@ -44,7 +44,7 @@ ElfFile::ElfFile(const char* filepath) { m_string_tables = NULL; m_symbol_tables = NULL; m_next = NULL; - m_status = Decoder::no_error; + m_status = NullDecoder::no_error; int len = strlen(filepath) + 1; m_filepath = (const char*)os::malloc(len * sizeof(char)); @@ -54,10 +54,10 @@ ElfFile::ElfFile(const char* filepath) { if (m_file != NULL) { load_tables(); } else { - m_status = Decoder::file_not_found; + m_status = NullDecoder::file_not_found; } } else { - m_status = Decoder::out_of_memory; + m_status = NullDecoder::out_of_memory; } } @@ -96,41 +96,41 @@ bool ElfFile::is_elf_file(Elf_Ehdr& hdr) { bool ElfFile::load_tables() { assert(m_file, "file not open"); - assert(m_status == Decoder::no_error, "already in error"); + assert(!NullDecoder::is_error(m_status), "already in error"); // read elf file header if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; return false; } if (!is_elf_file(m_elfHdr)) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; return false; } // walk elf file's section headers, and load string tables Elf_Shdr shdr; if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) { - if (m_status != Decoder::no_error) return false; + if (NullDecoder::is_error(m_status)) return false; for (int index = 0; index < m_elfHdr.e_shnum; index ++) { if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; return false; } // string table if (shdr.sh_type == SHT_STRTAB) { ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index); if (table == NULL) { - m_status = Decoder::out_of_memory; + m_status = NullDecoder::out_of_memory; return false; } add_string_table(table); } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr); if (table == NULL) { - m_status = Decoder::out_of_memory; + m_status = NullDecoder::out_of_memory; return false; } add_symbol_table(table); @@ -140,32 +140,33 @@ bool ElfFile::load_tables() { return true; } -const char* ElfFile::decode(address addr, int* offset) { +bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) { // something already went wrong, just give up - if (m_status != Decoder::no_error) { - return NULL; + if (NullDecoder::is_error(m_status)) { + return false; } - ElfSymbolTable* symbol_table = m_symbol_tables; int string_table_index; int pos_in_string_table; int off = INT_MAX; bool found_symbol = false; while (symbol_table != NULL) { - if (Decoder::no_error == symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) { + if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) { found_symbol = true; } symbol_table = symbol_table->m_next; } - if (!found_symbol) return NULL; + if (!found_symbol) return false; ElfStringTable* string_table = get_string_table(string_table_index); + if (string_table == NULL) { - m_status = Decoder::file_invalid; - return NULL; + m_status = NullDecoder::file_invalid; + return false; } if (offset) *offset = off; - return string_table->string_at(pos_in_string_table); + + return string_table->string_at(pos_in_string_table, buf, buflen); } diff --git a/hotspot/src/share/vm/utilities/elfFile.hpp b/hotspot/src/share/vm/utilities/elfFile.hpp index b40b90ae66b..e6f4ce263d6 100644 --- a/hotspot/src/share/vm/utilities/elfFile.hpp +++ b/hotspot/src/share/vm/utilities/elfFile.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,8 @@ * */ -#ifndef __ELF_FILE_HPP -#define __ELF_FILE_HPP +#ifndef SHARE_VM_UTILITIES_ELF_FILE_HPP +#define SHARE_VM_UTILITIES_ELF_FILE_HPP #if !defined(_WINDOWS) && !defined(__APPLE__) @@ -83,12 +83,12 @@ class ElfSymbolTable; // part of code to be very defensive, and bait out if anything went wrong. class ElfFile: public CHeapObj { - friend class Decoder; + friend class ElfDecoder; public: ElfFile(const char* filepath); ~ElfFile(); - const char* decode(address addr, int* offset); + bool decode(address addr, char* buf, int buflen, int* offset); const char* filepath() { return m_filepath; } @@ -99,7 +99,7 @@ class ElfFile: public CHeapObj { return (m_filepath && !strcmp(filepath, m_filepath)); } - Decoder::decoder_status get_status() { + NullDecoder::decoder_status get_status() { return m_status; } @@ -119,8 +119,9 @@ class ElfFile: public CHeapObj { // return a string table at specified section index ElfStringTable* get_string_table(int index); - // look up an address and return the nearest symbol - const char* look_up(Elf_Shdr shdr, address addr, int* offset); +protected: + ElfFile* next() const { return m_next; } + void set_next(ElfFile* file) { m_next = file; } protected: ElfFile* m_next; @@ -131,17 +132,17 @@ class ElfFile: public CHeapObj { FILE* m_file; // Elf header - Elf_Ehdr m_elfHdr; + Elf_Ehdr m_elfHdr; // symbol tables - ElfSymbolTable* m_symbol_tables; + ElfSymbolTable* m_symbol_tables; // string tables - ElfStringTable* m_string_tables; + ElfStringTable* m_string_tables; - Decoder::decoder_status m_status; + NullDecoder::decoder_status m_status; }; #endif // _WINDOWS -#endif // __ELF_FILE_HPP +#endif // SHARE_VM_UTILITIES_ELF_FILE_HPP diff --git a/hotspot/src/share/vm/utilities/elfStringTable.cpp b/hotspot/src/share/vm/utilities/elfStringTable.cpp index 905f82bfeb5..89286cb1883 100644 --- a/hotspot/src/share/vm/utilities/elfStringTable.cpp +++ b/hotspot/src/share/vm/utilities/elfStringTable.cpp @@ -38,7 +38,7 @@ ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) { m_index = index; m_next = NULL; m_file = file; - m_status = Decoder::no_error; + m_status = NullDecoder::no_error; // try to load the string table long cur_offset = ftell(file); @@ -48,7 +48,7 @@ ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) { if (fseek(file, shdr.sh_offset, SEEK_SET) || fread((void*)m_table, shdr.sh_size, 1, file) != 1 || fseek(file, cur_offset, SEEK_SET)) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; os::free((void*)m_table); m_table = NULL; } @@ -67,22 +67,23 @@ ElfStringTable::~ElfStringTable() { } } -const char* ElfStringTable::string_at(int pos) { - if (m_status != Decoder::no_error) { - return NULL; +bool ElfStringTable::string_at(int pos, char* buf, int buflen) { + if (NullDecoder::is_error(m_status)) { + return false; } if (m_table != NULL) { - return (const char*)(m_table + pos); + jio_snprintf(buf, buflen, "%s", (const char*)(m_table + pos)); + return true; } else { long cur_pos = ftell(m_file); if (cur_pos == -1 || fseek(m_file, m_shdr.sh_offset + pos, SEEK_SET) || - fread(m_symbol, 1, MAX_SYMBOL_LEN, m_file) <= 0 || + fread(buf, 1, buflen, m_file) <= 0 || fseek(m_file, cur_pos, SEEK_SET)) { - m_status = Decoder::file_invalid; - return NULL; + m_status = NullDecoder::file_invalid; + return false; } - return (const char*)m_symbol; + return true; } } diff --git a/hotspot/src/share/vm/utilities/elfStringTable.hpp b/hotspot/src/share/vm/utilities/elfStringTable.hpp index a984e3a3323..96f30b159ea 100644 --- a/hotspot/src/share/vm/utilities/elfStringTable.hpp +++ b/hotspot/src/share/vm/utilities/elfStringTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,8 @@ * */ -#ifndef __ELF_STRING_TABLE_HPP -#define __ELF_STRING_TABLE_HPP +#ifndef SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP +#define SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP #if !defined(_WINDOWS) && !defined(__APPLE__) @@ -35,9 +35,6 @@ // The string table represents a string table section in an elf file. // Whenever there is enough memory, it will load whole string table as // one blob. Otherwise, it will load string from file when requested. - -#define MAX_SYMBOL_LEN 256 - class ElfStringTable: CHeapObj { friend class ElfFile; public: @@ -48,10 +45,10 @@ class ElfStringTable: CHeapObj { int index() { return m_index; }; // get string at specified offset - const char* string_at(int offset); + bool string_at(int offset, char* buf, int buflen); // get status code - Decoder::decoder_status get_status() { return m_status; }; + NullDecoder::decoder_status get_status() { return m_status; }; protected: ElfStringTable* m_next; @@ -69,13 +66,10 @@ class ElfStringTable: CHeapObj { // section header Elf_Shdr m_shdr; - // buffer for reading individual string - char m_symbol[MAX_SYMBOL_LEN]; - // error code - Decoder::decoder_status m_status; + NullDecoder::decoder_status m_status; }; -#endif // _WINDOWS +#endif // _WINDOWS and _APPLE -#endif // __ELF_STRING_TABLE_HPP +#endif // SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP diff --git a/hotspot/src/share/vm/utilities/elfSymbolTable.cpp b/hotspot/src/share/vm/utilities/elfSymbolTable.cpp index d1606010d35..3ac9b9215f6 100644 --- a/hotspot/src/share/vm/utilities/elfSymbolTable.cpp +++ b/hotspot/src/share/vm/utilities/elfSymbolTable.cpp @@ -34,7 +34,7 @@ ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) { m_symbols = NULL; m_next = NULL; m_file = file; - m_status = Decoder::no_error; + m_status = NullDecoder::no_error; // try to load the string table long cur_offset = ftell(file); @@ -45,16 +45,16 @@ ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) { if (fseek(file, shdr.sh_offset, SEEK_SET) || fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 || fseek(file, cur_offset, SEEK_SET)) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; os::free(m_symbols); m_symbols = NULL; } } - if (m_status == Decoder::no_error) { + if (!NullDecoder::is_error(m_status)) { memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr)); } } else { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; } } @@ -68,13 +68,13 @@ ElfSymbolTable::~ElfSymbolTable() { } } -Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) { +bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) { assert(stringtableIndex, "null string table index pointer"); assert(posIndex, "null string table offset pointer"); assert(offset, "null offset pointer"); - if (m_status != Decoder::no_error) { - return m_status; + if (NullDecoder::is_error(m_status)) { + return false; } address pc = 0; @@ -97,8 +97,8 @@ Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableInd long cur_pos; if ((cur_pos = ftell(m_file)) == -1 || fseek(m_file, m_shdr.sh_offset, SEEK_SET)) { - m_status = Decoder::file_invalid; - return m_status; + m_status = NullDecoder::file_invalid; + return false; } Elf_Sym sym; @@ -114,13 +114,13 @@ Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableInd } } } else { - m_status = Decoder::file_invalid; - return m_status; + m_status = NullDecoder::file_invalid; + return false; } } fseek(m_file, cur_pos, SEEK_SET); } - return m_status; + return true; } #endif // _WINDOWS diff --git a/hotspot/src/share/vm/utilities/elfSymbolTable.hpp b/hotspot/src/share/vm/utilities/elfSymbolTable.hpp index c8a11fca2ac..a149b99dfd8 100644 --- a/hotspot/src/share/vm/utilities/elfSymbolTable.hpp +++ b/hotspot/src/share/vm/utilities/elfSymbolTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,8 @@ * */ -#ifndef __ELF_SYMBOL_TABLE_HPP -#define __ELF_SYMBOL_TABLE_HPP +#ifndef SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP +#define SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP #if !defined(_WINDOWS) && !defined(__APPLE__) @@ -45,9 +45,9 @@ class ElfSymbolTable: public CHeapObj { ~ElfSymbolTable(); // search the symbol that is nearest to the specified address. - Decoder::decoder_status lookup(address addr, int* stringtableIndex, int* posIndex, int* offset); + bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset); - Decoder::decoder_status get_status() { return m_status; }; + NullDecoder::decoder_status get_status() { return m_status; }; protected: ElfSymbolTable* m_next; @@ -62,9 +62,9 @@ class ElfSymbolTable: public CHeapObj { // section header Elf_Shdr m_shdr; - Decoder::decoder_status m_status; + NullDecoder::decoder_status m_status; }; -#endif // _WINDOWS +#endif // _WINDOWS and _APPLE -#endif // __ELF_SYMBOL_TABLE_HPP +#endif // SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index 94ed68ea848..a212f7646b4 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -571,8 +571,6 @@ void VMError::report(outputStream* st) { if (fr.pc()) { st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); - // initialize decoder to decode C frames - Decoder decoder; int count = 0; while (count++ < StackPrintLimit) { From 75e511ab32300a5b78acd7ea9268ecdbe98d6a5c Mon Sep 17 00:00:00 2001 From: Kurchi Subhra Hazra Date: Tue, 17 Jan 2012 15:55:40 -0800 Subject: [PATCH 45/96] 7117570: Warnings in sun.mangement.* and its subpackages Reviewed-by: mchung, dsamersoff --- .../share/classes/sun/management/Agent.java | 16 ++--- .../sun/management/ConnectorAddressLink.java | 16 ++--- .../share/classes/sun/management/Flag.java | 2 +- ...rbageCollectionNotifInfoCompositeData.java | 12 ++-- .../sun/management/GarbageCollectorImpl.java | 9 +-- .../classes/sun/management/GcInfoBuilder.java | 2 +- .../sun/management/GcInfoCompositeData.java | 29 ++------ .../sun/management/HotSpotDiagnostic.java | 2 +- .../sun/management/HotspotCompilation.java | 14 ++-- .../classes/sun/management/HotspotThread.java | 2 +- .../sun/management/LazyCompositeData.java | 15 ++--- .../management/ManagementFactoryHelper.java | 6 +- .../sun/management/MappedMXBeanType.java | 66 +++++++++---------- .../management/MonitorInfoCompositeData.java | 2 +- .../NotificationEmitterSupport.java | 12 ++-- .../classes/sun/management/RuntimeImpl.java | 2 +- .../management/ThreadInfoCompositeData.java | 2 +- .../counter/perf/PerfInstrumentation.java | 7 +- .../jmxremote/ConnectorBootstrap.java | 38 +++++------ .../sun/management/snmp/AdaptorBootstrap.java | 7 +- .../jvminstr/JVM_MANAGEMENT_MIB_IMPL.java | 10 +-- .../snmp/jvminstr/JvmMemGCTableMetaImpl.java | 2 + .../jvminstr/JvmMemManagerTableMetaImpl.java | 11 +++- .../JvmMemMgrPoolRelTableMetaImpl.java | 22 ++++--- .../jvminstr/JvmMemPoolTableMetaImpl.java | 11 +++- .../snmp/jvminstr/JvmMemoryImpl.java | 2 +- .../snmp/jvminstr/JvmMemoryMetaImpl.java | 2 + .../management/snmp/jvminstr/JvmOSImpl.java | 2 + .../jvminstr/JvmRTBootClassPathEntryImpl.java | 2 + .../JvmRTBootClassPathTableMetaImpl.java | 5 +- .../jvminstr/JvmRTClassPathEntryImpl.java | 1 + .../jvminstr/JvmRTClassPathTableMetaImpl.java | 5 +- .../jvminstr/JvmRTInputArgsEntryImpl.java | 1 + .../jvminstr/JvmRTInputArgsTableMetaImpl.java | 5 +- .../jvminstr/JvmRTLibraryPathEntryImpl.java | 1 + .../JvmRTLibraryPathTableMetaImpl.java | 4 +- .../snmp/jvminstr/JvmRuntimeMetaImpl.java | 1 + .../jvminstr/JvmThreadInstanceEntryImpl.java | 2 + .../JvmThreadInstanceTableMetaImpl.java | 9 ++- .../snmp/jvminstr/JvmThreadingMetaImpl.java | 2 + .../jvmmib/EnumJvmClassesVerboseLevel.java | 9 +-- .../EnumJvmJITCompilerTimeMonitoring.java | 9 +-- .../snmp/jvmmib/EnumJvmMemManagerState.java | 10 +-- .../EnumJvmMemPoolCollectThreshdSupport.java | 9 +-- .../snmp/jvmmib/EnumJvmMemPoolState.java | 9 +-- .../jvmmib/EnumJvmMemPoolThreshdSupport.java | 9 +-- .../snmp/jvmmib/EnumJvmMemPoolType.java | 9 +-- .../snmp/jvmmib/EnumJvmMemoryGCCall.java | 9 +-- .../jvmmib/EnumJvmMemoryGCVerboseLevel.java | 9 +-- .../jvmmib/EnumJvmRTBootClassPathSupport.java | 9 +-- .../EnumJvmThreadContentionMonitoring.java | 9 +-- .../EnumJvmThreadCpuTimeMonitoring.java | 9 +-- .../snmp/jvmmib/JVM_MANAGEMENT_MIB.java | 1 + .../jvmmib/JVM_MANAGEMENT_MIBOidTable.java | 1 + .../snmp/jvmmib/JvmClassLoadingMeta.java | 1 + .../snmp/jvmmib/JvmCompilationMeta.java | 1 + .../snmp/jvmmib/JvmMemGCEntryMeta.java | 1 + .../snmp/jvmmib/JvmMemGCTableMeta.java | 1 + .../snmp/jvmmib/JvmMemManagerEntryMeta.java | 1 + .../snmp/jvmmib/JvmMemManagerTableMeta.java | 1 + .../jvmmib/JvmMemMgrPoolRelEntryMeta.java | 1 + .../jvmmib/JvmMemMgrPoolRelTableMeta.java | 1 + .../snmp/jvmmib/JvmMemPoolEntryMeta.java | 1 + .../snmp/jvmmib/JvmMemPoolTableMeta.java | 2 + .../sun/management/snmp/jvmmib/JvmOSMeta.java | 2 + .../jvmmib/JvmRTBootClassPathEntryMeta.java | 1 + .../jvmmib/JvmRTBootClassPathTableMeta.java | 1 + .../snmp/jvmmib/JvmRTClassPathEntryMeta.java | 1 + .../snmp/jvmmib/JvmRTClassPathTableMeta.java | 1 + .../snmp/jvmmib/JvmRTInputArgsEntryMeta.java | 1 + .../snmp/jvmmib/JvmRTInputArgsTableMeta.java | 1 + .../jvmmib/JvmRTLibraryPathEntryMeta.java | 1 + .../jvmmib/JvmRTLibraryPathTableMeta.java | 1 + .../snmp/jvmmib/JvmRuntimeMeta.java | 1 + .../jvmmib/JvmThreadInstanceEntryMeta.java | 1 + .../jvmmib/JvmThreadInstanceTableMeta.java | 1 + .../snmp/jvmmib/JvmThreadingMeta.java | 1 + .../sun/management/snmp/util/MibLogger.java | 8 +-- .../snmp/util/SnmpListTableCache.java | 10 +-- .../snmp/util/SnmpNamedListTableCache.java | 26 ++++---- .../management/snmp/util/SnmpTableCache.java | 2 +- 81 files changed, 294 insertions(+), 249 deletions(-) diff --git a/jdk/src/share/classes/sun/management/Agent.java b/jdk/src/share/classes/sun/management/Agent.java index 0111f71a597..d5900930bbd 100644 --- a/jdk/src/share/classes/sun/management/Agent.java +++ b/jdk/src/share/classes/sun/management/Agent.java @@ -216,11 +216,8 @@ public class Agent { adaptorClass.getMethod("initialize", String.class, Properties.class); initializeMethod.invoke(null,snmpPort,props); - } catch (ClassNotFoundException x) { - // The SNMP packages are not present: throws an exception. - throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,x); - } catch (NoSuchMethodException x) { - // should not happen... + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) { + // snmp runtime doesn't exist - initialization fails throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,x); } catch (InvocationTargetException x) { final Throwable cause = x.getCause(); @@ -230,9 +227,6 @@ public class Agent { throw (Error) cause; // should not happen... throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,cause); - } catch (IllegalAccessException x) { - // should not happen... - throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,x); } } @@ -273,8 +267,8 @@ public class Agent { } catch (IOException e) { error(CONFIG_FILE_CLOSE_FAILED, fname); } - } - } + } + } } public static void startAgent() throws Exception { @@ -309,7 +303,7 @@ public class Agent { // invoke the premain(String args) method Class clz = ClassLoader.getSystemClassLoader().loadClass(cname); Method premain = clz.getMethod("premain", - new Class[] { String.class }); + new Class[] { String.class }); premain.invoke(null, /* static */ new Object[] { args }); } catch (ClassNotFoundException ex) { diff --git a/jdk/src/share/classes/sun/management/ConnectorAddressLink.java b/jdk/src/share/classes/sun/management/ConnectorAddressLink.java index 82241e76d2b..343ec45abba 100644 --- a/jdk/src/share/classes/sun/management/ConnectorAddressLink.java +++ b/jdk/src/share/classes/sun/management/ConnectorAddressLink.java @@ -117,11 +117,11 @@ public class ConnectorAddressLink { } catch (IllegalArgumentException iae) { throw new IOException(iae.getMessage()); } - List counters = + List counters = new PerfInstrumentation(bb).findByPattern(CONNECTOR_ADDRESS_COUNTER); - Iterator i = counters.iterator(); + Iterator i = counters.iterator(); if (i.hasNext()) { - Counter c = (Counter) i.next(); + Counter c = i.next(); return (String) c.getValue(); } else { return null; @@ -167,13 +167,13 @@ public class ConnectorAddressLink { } catch (IllegalArgumentException iae) { throw new IOException(iae.getMessage()); } - List counters = new PerfInstrumentation(bb).getAllCounters(); - Map properties = new HashMap(); - for (Object c : counters) { - String name = ((Counter) c).getName(); + List counters = new PerfInstrumentation(bb).getAllCounters(); + Map properties = new HashMap<>(); + for (Counter c : counters) { + String name = c.getName(); if (name.startsWith(REMOTE_CONNECTOR_COUNTER_PREFIX) && !name.equals(CONNECTOR_ADDRESS_COUNTER)) { - properties.put(name, ((Counter) c).getValue().toString()); + properties.put(name, c.getValue().toString()); } } return properties; diff --git a/jdk/src/share/classes/sun/management/Flag.java b/jdk/src/share/classes/sun/management/Flag.java index f9109b8ce8f..05f5c556ec3 100644 --- a/jdk/src/share/classes/sun/management/Flag.java +++ b/jdk/src/share/classes/sun/management/Flag.java @@ -91,7 +91,7 @@ class Flag { Flag[] flags = new Flag[numFlags]; int count = getFlags(names, flags, numFlags); - List result = new ArrayList(); + List result = new ArrayList<>(); for (Flag f : flags) { if (f != null) { result.add(f); diff --git a/jdk/src/share/classes/sun/management/GarbageCollectionNotifInfoCompositeData.java b/jdk/src/share/classes/sun/management/GarbageCollectionNotifInfoCompositeData.java index 3284b09286e..f245c5a6d4b 100644 --- a/jdk/src/share/classes/sun/management/GarbageCollectionNotifInfoCompositeData.java +++ b/jdk/src/share/classes/sun/management/GarbageCollectionNotifInfoCompositeData.java @@ -69,11 +69,7 @@ public class GarbageCollectionNotifInfoCompositeData extends LazyCompositeData { Field f = cl.getDeclaredField("builder"); f.setAccessible(true); return (GcInfoBuilder)f.get(gcNotifInfo.getGcInfo()); - } catch(ClassNotFoundException e) { - return null; - } catch(NoSuchFieldException e) { - return null; - } catch(IllegalAccessException e) { + } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { return null; } } @@ -82,7 +78,7 @@ public class GarbageCollectionNotifInfoCompositeData extends LazyCompositeData { synchronized(compositeTypeByBuilder) { gict = compositeTypeByBuilder.get(builder); if(gict == null) { - OpenType[] gcNotifInfoItemTypes = new OpenType[] { + OpenType[] gcNotifInfoItemTypes = new OpenType[] { SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, @@ -141,7 +137,7 @@ public class GarbageCollectionNotifInfoCompositeData extends LazyCompositeData { GC_INFO }; private static HashMap compositeTypeByBuilder = - new HashMap(); + new HashMap<>(); public static String getGcName(CompositeData cd) { String gcname = getString(cd, GC_NAME); @@ -195,7 +191,7 @@ public class GarbageCollectionNotifInfoCompositeData extends LazyCompositeData { private static synchronized CompositeType getBaseGcNotifInfoCompositeType() { if (baseGcNotifInfoCompositeType == null) { try { - OpenType[] baseGcNotifInfoItemTypes = new OpenType[] { + OpenType[] baseGcNotifInfoItemTypes = new OpenType[] { SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, diff --git a/jdk/src/share/classes/sun/management/GarbageCollectorImpl.java b/jdk/src/share/classes/sun/management/GarbageCollectorImpl.java index 09c1ffbec4d..fa0d6170462 100644 --- a/jdk/src/share/classes/sun/management/GarbageCollectorImpl.java +++ b/jdk/src/share/classes/sun/management/GarbageCollectorImpl.java @@ -70,14 +70,11 @@ class GarbageCollectorImpl extends MemoryManagerImpl private String[] poolNames = null; synchronized String[] getAllPoolNames() { if (poolNames == null) { - List pools = ManagementFactory.getMemoryPoolMXBeans(); + List pools = ManagementFactory.getMemoryPoolMXBeans(); poolNames = new String[pools.size()]; int i = 0; - for (ListIterator iter = pools.listIterator(); - iter.hasNext(); - i++) { - MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next(); - poolNames[i] = p.getName(); + for (MemoryPoolMXBean m : pools) { + poolNames[i++] = m.getName(); } } return poolNames; diff --git a/jdk/src/share/classes/sun/management/GcInfoBuilder.java b/jdk/src/share/classes/sun/management/GcInfoBuilder.java index 04ac6df3a1e..1c3f53df0b5 100644 --- a/jdk/src/share/classes/sun/management/GcInfoBuilder.java +++ b/jdk/src/share/classes/sun/management/GcInfoBuilder.java @@ -104,7 +104,7 @@ public class GcInfoBuilder { int itemCount = numGcInfoItems + gcExtItemCount; allItemNames = new String[itemCount]; String[] allItemDescs = new String[itemCount]; - OpenType[] allItemTypes = new OpenType[itemCount]; + OpenType[] allItemTypes = new OpenType[itemCount]; System.arraycopy(gcInfoItemNames, 0, allItemNames, 0, numGcInfoItems); System.arraycopy(gcInfoItemNames, 0, allItemDescs, 0, numGcInfoItems); diff --git a/jdk/src/share/classes/sun/management/GcInfoCompositeData.java b/jdk/src/share/classes/sun/management/GcInfoCompositeData.java index fb423e1608b..b3050a1c702 100644 --- a/jdk/src/share/classes/sun/management/GcInfoCompositeData.java +++ b/jdk/src/share/classes/sun/management/GcInfoCompositeData.java @@ -76,11 +76,7 @@ public class GcInfoCompositeData extends LazyCompositeData { Field f = cl.getDeclaredField("builder"); f.setAccessible(true); return (GcInfoBuilder)f.get(info); - } catch(ClassNotFoundException e) { - return null; - } catch(NoSuchFieldException e) { - return null; - } catch(IllegalAccessException e) { + } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { return null; } } @@ -92,11 +88,7 @@ public class GcInfoCompositeData extends LazyCompositeData { Field f = cl.getDeclaredField("extAttributes"); f.setAccessible(true); return (Object[])f.get(info); - } catch(ClassNotFoundException e) { - return null; - } catch(NoSuchFieldException e) { - return null; - } catch(IllegalAccessException e) { + } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { return null; } } @@ -180,10 +172,7 @@ public class GcInfoCompositeData extends LazyCompositeData { Method m = GcInfo.class.getMethod("getMemoryUsageBeforeGc"); memoryUsageMapType = MappedMXBeanType.getMappedType(m.getGenericReturnType()); - } catch (NoSuchMethodException e) { - // Should never reach here - throw new AssertionError(e); - } catch (OpenDataException e) { + } catch (NoSuchMethodException | OpenDataException e) { // Should never reach here throw new AssertionError(e); } @@ -197,7 +186,7 @@ public class GcInfoCompositeData extends LazyCompositeData { static synchronized OpenType[] getBaseGcInfoItemTypes() { if (baseGcInfoItemTypes == null) { OpenType memoryUsageOpenType = memoryUsageMapType.getOpenType(); - baseGcInfoItemTypes = new OpenType[] { + baseGcInfoItemTypes = new OpenType[] { SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, @@ -225,10 +214,7 @@ public class GcInfoCompositeData extends LazyCompositeData { try { TabularData td = (TabularData) cd.get(MEMORY_USAGE_BEFORE_GC); return cast(memoryUsageMapType.toJavaTypeData(td)); - } catch (InvalidObjectException e) { - // Should never reach here - throw new AssertionError(e); - } catch (OpenDataException e) { + } catch (InvalidObjectException | OpenDataException e) { // Should never reach here throw new AssertionError(e); } @@ -244,10 +230,7 @@ public class GcInfoCompositeData extends LazyCompositeData { TabularData td = (TabularData) cd.get(MEMORY_USAGE_AFTER_GC); //return (Map) return cast(memoryUsageMapType.toJavaTypeData(td)); - } catch (InvalidObjectException e) { - // Should never reach here - throw new AssertionError(e); - } catch (OpenDataException e) { + } catch (InvalidObjectException | OpenDataException e) { // Should never reach here throw new AssertionError(e); } diff --git a/jdk/src/share/classes/sun/management/HotSpotDiagnostic.java b/jdk/src/share/classes/sun/management/HotSpotDiagnostic.java index dc7a0015b4f..f48d0988ccf 100644 --- a/jdk/src/share/classes/sun/management/HotSpotDiagnostic.java +++ b/jdk/src/share/classes/sun/management/HotSpotDiagnostic.java @@ -48,7 +48,7 @@ public class HotSpotDiagnostic implements HotSpotDiagnosticMXBean { public List getDiagnosticOptions() { List allFlags = Flag.getAllFlags(); - List result = new ArrayList(); + List result = new ArrayList<>(); for (Flag flag : allFlags) { if (flag.isWriteable() && flag.isExternal()) { result.add(flag.getVMOption()); diff --git a/jdk/src/share/classes/sun/management/HotspotCompilation.java b/jdk/src/share/classes/sun/management/HotspotCompilation.java index 7e9ee0cf268..0c97c897bc9 100644 --- a/jdk/src/share/classes/sun/management/HotspotCompilation.java +++ b/jdk/src/share/classes/sun/management/HotspotCompilation.java @@ -120,13 +120,13 @@ class HotspotCompilation // current implementation. We first look up in the SUN_CI namespace // since most counters are in SUN_CI namespace. - if ((c = (Counter) counters.get(SUN_CI + name)) != null) { + if ((c = counters.get(SUN_CI + name)) != null) { return c; } - if ((c = (Counter) counters.get(COM_SUN_CI + name)) != null) { + if ((c = counters.get(COM_SUN_CI + name)) != null) { return c; } - if ((c = (Counter) counters.get(JAVA_CI + name)) != null) { + if ((c = counters.get(JAVA_CI + name)) != null) { return c; } @@ -136,10 +136,8 @@ class HotspotCompilation private void initCompilerCounters() { // Build a tree map of the current list of performance counters - ListIterator iter = getInternalCompilerCounters().listIterator(); - counters = new TreeMap(); - while (iter.hasNext()) { - Counter c = (Counter) iter.next(); + counters = new TreeMap<>(); + for (Counter c: getInternalCompilerCounters()) { counters.put(c.getName(), c); } @@ -200,7 +198,7 @@ class HotspotCompilation } public java.util.List getCompilerThreadStats() { - List list = new ArrayList(threads.length); + List list = new ArrayList<>(threads.length); int i = 0; if (threads[0] == null) { // no adaptor thread diff --git a/jdk/src/share/classes/sun/management/HotspotThread.java b/jdk/src/share/classes/sun/management/HotspotThread.java index 62329d2e94e..b9003c2093a 100644 --- a/jdk/src/share/classes/sun/management/HotspotThread.java +++ b/jdk/src/share/classes/sun/management/HotspotThread.java @@ -58,7 +58,7 @@ class HotspotThread String[] names = new String[count]; long[] times = new long[count]; int numThreads = getInternalThreadTimes0(names, times); - Map result = new HashMap(numThreads); + Map result = new HashMap<>(numThreads); for (int i = 0; i < numThreads; i++) { result.put(names[i], new Long(times[i])); } diff --git a/jdk/src/share/classes/sun/management/LazyCompositeData.java b/jdk/src/share/classes/sun/management/LazyCompositeData.java index 6bae9b94d9d..c11c9faefab 100644 --- a/jdk/src/share/classes/sun/management/LazyCompositeData.java +++ b/jdk/src/share/classes/sun/management/LazyCompositeData.java @@ -81,7 +81,7 @@ public abstract class LazyCompositeData return compositeData().toString(); } - public Collection values() { + public Collection values() { return compositeData().values(); } @@ -153,16 +153,15 @@ public abstract class LazyCompositeData // We can't use CompositeType.isValue() since it returns false // if the type name doesn't match. - Set allItems = type1.keySet(); + Set allItems = type1.keySet(); // Check all items in the type1 exist in type2 if (!type2.keySet().containsAll(allItems)) return false; - for (Iterator iter = allItems.iterator(); iter.hasNext(); ) { - String item = (String) iter.next(); - OpenType ot1 = type1.getType(item); - OpenType ot2 = type2.getType(item); + for (String item: allItems) { + OpenType ot1 = type1.getType(item); + OpenType ot2 = type2.getType(item); if (ot1 instanceof CompositeType) { if (! (ot2 instanceof CompositeType)) return false; @@ -183,8 +182,8 @@ public abstract class LazyCompositeData protected static boolean isTypeMatched(TabularType type1, TabularType type2) { if (type1 == type2) return true; - List list1 = type1.getIndexNames(); - List list2 = type2.getIndexNames(); + List list1 = type1.getIndexNames(); + List list2 = type2.getIndexNames(); // check if the list of index names are the same if (!list1.equals(list2)) diff --git a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java index d2901068344..025b7a26d64 100644 --- a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java +++ b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java @@ -110,7 +110,7 @@ public class ManagementFactoryHelper { public static List getMemoryPoolMXBeans() { MemoryPoolMXBean[] pools = MemoryImpl.getMemoryPools(); - List list = new ArrayList(pools.length); + List list = new ArrayList<>(pools.length); for (MemoryPoolMXBean p : pools) { list.add(p); } @@ -119,7 +119,7 @@ public class ManagementFactoryHelper { public static List getMemoryManagerMXBeans() { MemoryManagerMXBean[] mgrs = MemoryImpl.getMemoryManagers(); - List result = new ArrayList(mgrs.length); + List result = new ArrayList<>(mgrs.length); for (MemoryManagerMXBean m : mgrs) { result.add(m); } @@ -128,7 +128,7 @@ public class ManagementFactoryHelper { public static List getGarbageCollectorMXBeans() { MemoryManagerMXBean[] mgrs = MemoryImpl.getMemoryManagers(); - List result = new ArrayList(mgrs.length); + List result = new ArrayList<>(mgrs.length); for (MemoryManagerMXBean m : mgrs) { if (GarbageCollectorMXBean.class.isInstance(m)) { result.add(GarbageCollectorMXBean.class.cast(m)); diff --git a/jdk/src/share/classes/sun/management/MappedMXBeanType.java b/jdk/src/share/classes/sun/management/MappedMXBeanType.java index 0efe335603b..db90899b06b 100644 --- a/jdk/src/share/classes/sun/management/MappedMXBeanType.java +++ b/jdk/src/share/classes/sun/management/MappedMXBeanType.java @@ -62,18 +62,18 @@ import com.sun.management.VMOption; @SuppressWarnings("unchecked") public abstract class MappedMXBeanType { private static final WeakHashMap convertedTypes = - new WeakHashMap(); + new WeakHashMap<>(); boolean isBasicType = false; - OpenType openType = inProgress; - Class mappedTypeClass; + OpenType openType = inProgress; + Class mappedTypeClass; static synchronized MappedMXBeanType newMappedType(Type javaType) throws OpenDataException { MappedMXBeanType mt = null; if (javaType instanceof Class) { - final Class c = (Class) javaType; + final Class c = (Class) javaType; if (c.isEnum()) { mt = new EnumMXBeanType(c); } else if (c.isArray()) { @@ -85,7 +85,7 @@ public abstract class MappedMXBeanType { final ParameterizedType pt = (ParameterizedType) javaType; final Type rawType = pt.getRawType(); if (rawType instanceof Class) { - final Class rc = (Class) rawType; + final Class rc = (Class) rawType; if (rc == List.class) { mt = new ListMXBeanType(pt); } else if (rc == Map.class) { @@ -106,7 +106,7 @@ public abstract class MappedMXBeanType { } // basic types do not require data mapping - static synchronized MappedMXBeanType newBasicType(Class c, OpenType ot) + static synchronized MappedMXBeanType newBasicType(Class c, OpenType ot) throws OpenDataException { MappedMXBeanType mt = new BasicMXBeanType(c, ot); convertedTypes.put(c, mt); @@ -127,7 +127,7 @@ public abstract class MappedMXBeanType { } // Convert a class to an OpenType - public static synchronized OpenType toOpenType(Type t) + public static synchronized OpenType toOpenType(Type t) throws OpenDataException { MappedMXBeanType mt = getMappedType(t); return mt.getOpenType(); @@ -152,7 +152,7 @@ public abstract class MappedMXBeanType { } // Return the mapped open type - OpenType getOpenType() { + OpenType getOpenType() { return openType; } @@ -168,7 +168,7 @@ public abstract class MappedMXBeanType { } // Return the mapped open type - Class getMappedTypeClass() { + Class getMappedTypeClass() { return mappedTypeClass; } @@ -192,8 +192,8 @@ public abstract class MappedMXBeanType { // T <-> T (no conversion) // static class BasicMXBeanType extends MappedMXBeanType { - final Class basicType; - BasicMXBeanType(Class c, OpenType openType) { + final Class basicType; + BasicMXBeanType(Class c, OpenType openType) { this.basicType = c; this.openType = openType; this.mappedTypeClass = c; @@ -228,7 +228,7 @@ public abstract class MappedMXBeanType { // static class EnumMXBeanType extends MappedMXBeanType { final Class enumClass; - EnumMXBeanType(Class c) { + EnumMXBeanType(Class c) { this.enumClass = c; this.openType = STRING; this.mappedTypeClass = String.class; @@ -269,16 +269,16 @@ public abstract class MappedMXBeanType { // E[] <-> openTypeData(E)[] // static class ArrayMXBeanType extends MappedMXBeanType { - final Class arrayClass; + final Class arrayClass; protected MappedMXBeanType componentType; protected MappedMXBeanType baseElementType; - ArrayMXBeanType(Class c) throws OpenDataException { + ArrayMXBeanType(Class c) throws OpenDataException { this.arrayClass = c; this.componentType = getMappedType(c.getComponentType()); StringBuilder className = new StringBuilder(); - Class et = c; + Class et = c; int dim; for (dim = 0; et.isArray(); dim++) { className.append('['); @@ -299,7 +299,7 @@ public abstract class MappedMXBeanType { throw ode; } - openType = new ArrayType(dim, baseElementType.getOpenType()); + openType = new ArrayType<>(dim, baseElementType.getOpenType()); } protected ArrayMXBeanType() { @@ -395,7 +395,7 @@ public abstract class MappedMXBeanType { throw ode; } - openType = new ArrayType(dim, baseElementType.getOpenType()); + openType = new ArrayType<>(dim, baseElementType.getOpenType()); } Type getJavaType() { @@ -428,7 +428,7 @@ public abstract class MappedMXBeanType { throw new OpenDataException("Element Type for " + pt + " not supported"); } - final Class et = (Class) argTypes[0]; + final Class et = (Class) argTypes[0]; if (et.isArray()) { throw new OpenDataException("Element Type for " + pt + " not supported"); @@ -445,7 +445,7 @@ public abstract class MappedMXBeanType { ode.initCause(e); throw ode; } - openType = new ArrayType(1, paramType.getOpenType()); + openType = new ArrayType<>(1, paramType.getOpenType()); } Type getJavaType() { @@ -473,7 +473,7 @@ public abstract class MappedMXBeanType { throws OpenDataException, InvalidObjectException { final Object[] openArray = (Object[]) data; - List result = new ArrayList(openArray.length); + List result = new ArrayList<>(openArray.length); for (Object o : openArray) { result.add(paramType.toJavaTypeData(o)); } @@ -514,7 +514,7 @@ public abstract class MappedMXBeanType { // FIXME: generate typeName for generic typeName = "Map<" + keyType.getName() + "," + valueType.getName() + ">"; - final OpenType[] mapItemTypes = new OpenType[] { + final OpenType[] mapItemTypes = new OpenType[] { keyType.getOpenType(), valueType.getOpenType(), }; @@ -543,7 +543,7 @@ public abstract class MappedMXBeanType { final TabularData table = new TabularDataSupport(tabularType); final CompositeType rowType = tabularType.getRowType(); - for (Map.Entry entry : map.entrySet()) { + for (Map.Entry entry : map.entrySet()) { final Object key = keyType.toOpenTypeData(entry.getKey()); final Object value = valueType.toOpenTypeData(entry.getValue()); final CompositeData row = @@ -560,7 +560,7 @@ public abstract class MappedMXBeanType { final TabularData td = (TabularData) data; - Map result = new HashMap(); + Map result = new HashMap<>(); for (CompositeData row : (Collection) td.values()) { Object key = keyType.toJavaTypeData(row.get(KEY)); Object value = valueType.toJavaTypeData(row.get(VALUE)); @@ -607,7 +607,7 @@ public abstract class MappedMXBeanType { final boolean isCompositeData; Method fromMethod = null; - CompositeDataMXBeanType(Class c) throws OpenDataException { + CompositeDataMXBeanType(Class c) throws OpenDataException { this.javaClass = c; this.mappedTypeClass = COMPOSITE_DATA_CLASS; @@ -639,8 +639,8 @@ public abstract class MappedMXBeanType { return javaClass.getMethods(); } }); - final List names = new ArrayList(); - final List types = new ArrayList(); + final List names = new ArrayList<>(); + final List> types = new ArrayList<>(); /* Select public methods that look like "T getX()" or "boolean isX()", where T is not void and X is not the empty @@ -678,7 +678,7 @@ public abstract class MappedMXBeanType { c.getName(), nameArray, // field names nameArray, // field descriptions - types.toArray(new OpenType[0])); + types.toArray(new OpenType[0])); } } @@ -722,7 +722,7 @@ public abstract class MappedMXBeanType { // so that no other classes are sent over the wire CompositeData cd = (CompositeData) data; CompositeType ct = cd.getCompositeType(); - String[] itemNames = (String[]) ct.keySet().toArray(new String[0]); + String[] itemNames = ct.keySet().toArray(new String[0]); Object[] itemValues = cd.getAll(itemNames); return new CompositeDataSupport(ct, itemNames, itemValues); } @@ -779,9 +779,9 @@ public abstract class MappedMXBeanType { } private static final long serialVersionUID = -3413063475064374490L; } - private static final OpenType inProgress; + private static final OpenType inProgress; static { - OpenType t; + OpenType t; try { t = new InProgress(); } catch (OpenDataException e) { @@ -799,8 +799,8 @@ public abstract class MappedMXBeanType { static { try { for (int i = 0; i < simpleTypes.length; i++) { - final OpenType t = simpleTypes[i]; - Class c; + final OpenType t = simpleTypes[i]; + Class c; try { c = Class.forName(t.getClassName(), false, String.class.getClassLoader()); @@ -816,7 +816,7 @@ public abstract class MappedMXBeanType { if (c.getName().startsWith("java.lang.")) { try { final Field typeField = c.getField("TYPE"); - final Class primitiveType = (Class) typeField.get(null); + final Class primitiveType = (Class) typeField.get(null); MappedMXBeanType.newBasicType(primitiveType, t); } catch (NoSuchFieldException e) { // OK: must not be a primitive wrapper diff --git a/jdk/src/share/classes/sun/management/MonitorInfoCompositeData.java b/jdk/src/share/classes/sun/management/MonitorInfoCompositeData.java index 58bea9d550b..92b1cccc0a4 100644 --- a/jdk/src/share/classes/sun/management/MonitorInfoCompositeData.java +++ b/jdk/src/share/classes/sun/management/MonitorInfoCompositeData.java @@ -92,7 +92,7 @@ public class MonitorInfoCompositeData extends LazyCompositeData { monitorInfoCompositeType = (CompositeType) MappedMXBeanType.toOpenType(MonitorInfo.class); Set s = monitorInfoCompositeType.keySet(); - monitorInfoItemNames = (String[]) s.toArray(new String[0]); + monitorInfoItemNames = s.toArray(new String[0]); } catch (OpenDataException e) { // Should never reach here throw new AssertionError(e); diff --git a/jdk/src/share/classes/sun/management/NotificationEmitterSupport.java b/jdk/src/share/classes/sun/management/NotificationEmitterSupport.java index 436211d4a40..580643b038a 100644 --- a/jdk/src/share/classes/sun/management/NotificationEmitterSupport.java +++ b/jdk/src/share/classes/sun/management/NotificationEmitterSupport.java @@ -71,7 +71,7 @@ abstract class NotificationEmitterSupport implements NotificationEmitter { efficient solution would be to clone the listener list every time a notification is sent. */ synchronized (listenerLock) { - List newList = new ArrayList(listenerList.size() + 1); + List newList = new ArrayList<>(listenerList.size() + 1); newList.addAll(listenerList); newList.add(new ListenerInfo(listener, filter, handback)); listenerList = newList; @@ -82,12 +82,12 @@ abstract class NotificationEmitterSupport implements NotificationEmitter { throws ListenerNotFoundException { synchronized (listenerLock) { - List newList = new ArrayList(listenerList); + List newList = new ArrayList<>(listenerList); /* We scan the list of listeners in reverse order because in forward order we would have to repeat the loop with the same index after a remove. */ for (int i=newList.size()-1; i>=0; i--) { - ListenerInfo li = (ListenerInfo)newList.get(i); + ListenerInfo li = newList.get(i); if (li.listener == listener) newList.remove(i); @@ -106,10 +106,10 @@ abstract class NotificationEmitterSupport implements NotificationEmitter { boolean found = false; synchronized (listenerLock) { - List newList = new ArrayList(listenerList); + List newList = new ArrayList<>(listenerList); final int size = newList.size(); for (int i = 0; i < size; i++) { - ListenerInfo li = (ListenerInfo) newList.get(i); + ListenerInfo li = newList.get(i); if (li.listener == listener) { found = true; @@ -148,7 +148,7 @@ abstract class NotificationEmitterSupport implements NotificationEmitter { final int size = currentList.size(); for (int i = 0; i < size; i++) { - ListenerInfo li = (ListenerInfo) currentList.get(i); + ListenerInfo li = currentList.get(i); if (li.filter == null || li.filter.isNotificationEnabled(notification)) { diff --git a/jdk/src/share/classes/sun/management/RuntimeImpl.java b/jdk/src/share/classes/sun/management/RuntimeImpl.java index 53f33ee73f4..9f52969e7c1 100644 --- a/jdk/src/share/classes/sun/management/RuntimeImpl.java +++ b/jdk/src/share/classes/sun/management/RuntimeImpl.java @@ -128,7 +128,7 @@ class RuntimeImpl implements RuntimeMXBean { public Map getSystemProperties() { Properties sysProps = System.getProperties(); - Map map = new HashMap(); + Map map = new HashMap<>(); // Properties.entrySet() does not include the entries in // the default properties. So use Properties.stringPropertyNames() diff --git a/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java b/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java index 4c483d305b5..7a911e4fd32 100644 --- a/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java +++ b/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java @@ -190,7 +190,7 @@ public class ThreadInfoCompositeData extends LazyCompositeData { threadInfoV6Attributes.length; String[] v5ItemNames = new String[numV5Attributes]; String[] v5ItemDescs = new String[numV5Attributes]; - OpenType[] v5ItemTypes = new OpenType[numV5Attributes]; + OpenType[] v5ItemTypes = new OpenType[numV5Attributes]; int i = 0; for (String n : itemNames) { if (isV5Attribute(n)) { diff --git a/jdk/src/share/classes/sun/management/counter/perf/PerfInstrumentation.java b/jdk/src/share/classes/sun/management/counter/perf/PerfInstrumentation.java index eb7ae7ac332..2d0cb5bee6e 100644 --- a/jdk/src/share/classes/sun/management/counter/perf/PerfInstrumentation.java +++ b/jdk/src/share/classes/sun/management/counter/perf/PerfInstrumentation.java @@ -73,7 +73,7 @@ public class PerfInstrumentation { buffer.position(prologue.getEntryOffset()); nextEntry = buffer.position(); // rebuild all the counters - map = new TreeMap(); + map = new TreeMap<>(); } boolean hasNext() { @@ -154,7 +154,7 @@ public class PerfInstrumentation { map.put(c.getName(), c); } } - return new ArrayList(map.values()); + return new ArrayList<>(map.values()); } public synchronized List findByPattern(String patternString) { @@ -167,7 +167,8 @@ public class PerfInstrumentation { Pattern pattern = Pattern.compile(patternString); Matcher matcher = pattern.matcher(""); - List matches = new ArrayList(); + List matches = new ArrayList<>(); + for (Map.Entry me: map.entrySet()) { String name = me.getKey(); diff --git a/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java b/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java index a3b318a8cec..710180516dc 100644 --- a/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java +++ b/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java @@ -234,14 +234,15 @@ public final class ConnectorBootstrap { "authenticated Subject is null"); } final Set principals = subject.getPrincipals(); - for (Principal p: principals) { - if (properties.containsKey(p.getName())) { + for (Principal p1: principals) { + if (properties.containsKey(p1.getName())) { return; } } - final Set principalsStr = new HashSet(); - for (Principal p: principals) { - principalsStr.add(p.getName()); + + final Set principalsStr = new HashSet<>(); + for (Principal p2: principals) { + principalsStr.add(p2.getName()); } throw new SecurityException( "Access denied! No entries found in the access file [" + @@ -255,9 +256,9 @@ public final class ConnectorBootstrap { if (fname == null) { return p; } - FileInputStream fin = new FileInputStream(fname); - p.load(fin); - fin.close(); + try (FileInputStream fin = new FileInputStream(fname)) { + p.load(fin); + } return p; } private final Map environment; @@ -430,7 +431,7 @@ public final class ConnectorBootstrap { try { // Export remote connector address and associated configuration // properties to the instrumentation buffer. - Map properties = new HashMap(); + Map properties = new HashMap<>(); properties.put("remoteAddress", url.toString()); properties.put("authenticate", useAuthenticationStr); properties.put("ssl", useSslStr); @@ -456,7 +457,7 @@ public final class ConnectorBootstrap { System.setProperty("java.rmi.server.randomIDs", "true"); // This RMI server should not keep the VM alive - Map env = new HashMap(); + Map env = new HashMap<>(); env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter()); // The local connector server need only be available via the @@ -599,12 +600,9 @@ public final class ConnectorBootstrap { try { // Load the SSL keystore properties from the config file Properties p = new Properties(); - InputStream in = new FileInputStream(sslConfigFileName); - try { + try (InputStream in = new FileInputStream(sslConfigFileName)) { BufferedInputStream bin = new BufferedInputStream(in); p.load(bin); - } finally { - in.close(); } String keyStore = p.getProperty("javax.net.ssl.keyStore"); @@ -628,11 +626,8 @@ public final class ConnectorBootstrap { KeyStore ks = null; if (keyStore != null) { ks = KeyStore.getInstance(KeyStore.getDefaultType()); - FileInputStream ksfis = new FileInputStream(keyStore); - try { + try (FileInputStream ksfis = new FileInputStream(keyStore)) { ks.load(ksfis, keyStorePasswd); - } finally { - ksfis.close(); } } KeyManagerFactory kmf = KeyManagerFactory.getInstance( @@ -642,11 +637,8 @@ public final class ConnectorBootstrap { KeyStore ts = null; if (trustStore != null) { ts = KeyStore.getInstance(KeyStore.getDefaultType()); - FileInputStream tsfis = new FileInputStream(trustStore); - try { + try (FileInputStream tsfis = new FileInputStream(trustStore)) { ts.load(tsfis, trustStorePasswd); - } finally { - tsfis.close(); } } TrustManagerFactory tmf = TrustManagerFactory.getInstance( @@ -689,7 +681,7 @@ public final class ConnectorBootstrap { JMXServiceURL url = new JMXServiceURL("rmi", null, 0); - Map env = new HashMap(); + Map env = new HashMap<>(); PermanentExporter exporter = new PermanentExporter(); diff --git a/jdk/src/share/classes/sun/management/snmp/AdaptorBootstrap.java b/jdk/src/share/classes/sun/management/snmp/AdaptorBootstrap.java index 27d28fc5f5f..fdc66ce8d1c 100644 --- a/jdk/src/share/classes/sun/management/snmp/AdaptorBootstrap.java +++ b/jdk/src/share/classes/sun/management/snmp/AdaptorBootstrap.java @@ -118,21 +118,22 @@ public final class AdaptorBootstrap { /** * Retrieve the Trap Target List from the ACL file. **/ + @SuppressWarnings("unchecked") private static List getTargetList(InetAddressAcl acl, int defaultTrapPort) { final ArrayList result = - new ArrayList(); + new ArrayList<>(); if (acl != null) { if (log.isDebugOn()) log.debug("getTargetList",Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.processing")); - final Enumeration td=acl.getTrapDestinations(); + final Enumeration td = acl.getTrapDestinations(); for (; td.hasMoreElements() ;) { final InetAddress targetAddr = (InetAddress)td.nextElement(); final Enumeration tc = acl.getTrapCommunities(targetAddr); for (;tc.hasMoreElements() ;) { - final String community = (String) tc.nextElement(); + final String community = (String)tc.nextElement(); final NotificationTarget target = new NotificationTargetImpl(targetAddr, defaultTrapPort, diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JVM_MANAGEMENT_MIB_IMPL.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JVM_MANAGEMENT_MIB_IMPL.java index 65b7b1b8852..a692889b557 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JVM_MANAGEMENT_MIB_IMPL.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JVM_MANAGEMENT_MIB_IMPL.java @@ -90,14 +90,14 @@ public class JVM_MANAGEMENT_MIB_IMPL extends JVM_MANAGEMENT_MIB { SnmpOidTable table = null; if(tableRef == null) { table = new JVM_MANAGEMENT_MIBOidTable(); - tableRef = new WeakReference(table); + tableRef = new WeakReference<>(table); return table; } table = tableRef.get(); if(table == null) { table = new JVM_MANAGEMENT_MIBOidTable(); - tableRef = new WeakReference(table); + tableRef = new WeakReference<>(table); } return table; @@ -198,7 +198,7 @@ public class JVM_MANAGEMENT_MIB_IMPL extends JVM_MANAGEMENT_MIB { * List of notification targets. */ private ArrayList notificationTargets = - new ArrayList(); + new ArrayList<>(); private final NotificationEmitter emitter; private final NotificationHandler handler; @@ -215,7 +215,7 @@ public class JVM_MANAGEMENT_MIB_IMPL extends JVM_MANAGEMENT_MIB { } private synchronized void sendTrap(SnmpOid trap, SnmpVarBindList list) { - final Iterator iterator = notificationTargets.iterator(); + final Iterator iterator = notificationTargets.iterator(); final SnmpAdaptorServer adaptor = (SnmpAdaptorServer) getSnmpAdaptor(); @@ -232,7 +232,7 @@ public class JVM_MANAGEMENT_MIB_IMPL extends JVM_MANAGEMENT_MIB { while(iterator.hasNext()) { NotificationTarget target = null; try { - target = (NotificationTarget) iterator.next(); + target = iterator.next(); SnmpPeer peer = new SnmpPeer(target.getAddress(), target.getPort()); SnmpParameters p = new SnmpParameters(); diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemGCTableMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemGCTableMetaImpl.java index 91facb1b83a..c2d1a5387dd 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemGCTableMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemGCTableMetaImpl.java @@ -58,6 +58,8 @@ import sun.management.snmp.util.JvmContextFactory; */ public class JvmMemGCTableMetaImpl extends JvmMemGCTableMeta { + static final long serialVersionUID = 8250461197108867607L; + /** * This class acts as a filter over the SnmpTableHandler * used for the JvmMemoryManagerTable. It filters out diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemManagerTableMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemManagerTableMetaImpl.java index 51bd51c8671..73cccfaa832 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemManagerTableMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemManagerTableMetaImpl.java @@ -61,12 +61,17 @@ import sun.management.snmp.util.JvmContextFactory; */ public class JvmMemManagerTableMetaImpl extends JvmMemManagerTableMeta { + static final long serialVersionUID = 36176771566817592L; + /** * A concrete implementation of {@link SnmpNamedListTableCache}, for the * jvmMemManagerTable. **/ private static class JvmMemManagerTableCache extends SnmpNamedListTableCache { + + static final long serialVersionUID = 6564294074653009240L; + /** * Create a weak cache for the jvmMemManagerTable. * @param validity validity of the cached data, in ms. @@ -87,7 +92,7 @@ public class JvmMemManagerTableMetaImpl extends JvmMemManagerTableMeta { * MemoryManagerMXBean in the list. * @return ((MemoryManagerMXBean)item).getName() **/ - protected String getKey(Object context, List rawDatas, + protected String getKey(Object context, List rawDatas, int rank, Object item) { if (item == null) return null; final String name = ((MemoryManagerMXBean)item).getName(); @@ -99,7 +104,7 @@ public class JvmMemManagerTableMetaImpl extends JvmMemManagerTableMeta { * Call getTableHandler(JvmContextFactory.getUserData()). **/ public SnmpTableHandler getTableHandler() { - final Map userData = JvmContextFactory.getUserData(); + final Map userData = JvmContextFactory.getUserData(); return getTableDatas(userData); } @@ -114,7 +119,7 @@ public class JvmMemManagerTableMetaImpl extends JvmMemManagerTableMeta { * Call ManagementFactory.getMemoryManagerMXBeans() to * load the raw data of this table. **/ - protected List loadRawDatas(Map userData) { + protected List loadRawDatas(Map userData) { return ManagementFactory.getMemoryManagerMXBeans(); } diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemMgrPoolRelTableMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemMgrPoolRelTableMetaImpl.java index 36d90666778..703c46946a7 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemMgrPoolRelTableMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemMgrPoolRelTableMetaImpl.java @@ -64,13 +64,17 @@ import sun.management.snmp.util.JvmContextFactory; public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta implements Serializable { + static final long serialVersionUID = 1896509775012355443L; + /** * A concrete implementation of {@link SnmpTableCache}, for the * jvmMemMgrPoolRelTable. **/ + private static class JvmMemMgrPoolRelTableCache extends SnmpTableCache { + static final long serialVersionUID = 6059937161990659184L; final private JvmMemMgrPoolRelTableMetaImpl meta; /** @@ -87,7 +91,7 @@ public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta * Call getTableDatas(JvmContextFactory.getUserData()). **/ public SnmpTableHandler getTableHandler() { - final Map userData = JvmContextFactory.getUserData(); + final Map userData = JvmContextFactory.getUserData(); return getTableDatas(userData); } @@ -101,7 +105,7 @@ public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta return buildPoolIndexMap((SnmpCachedData)handler); // not optimizable... too bad. - final Map m = new HashMap(); + final Map m = new HashMap<>(); SnmpOid index=null; while ((index = handler.getNext(index))!=null) { final MemoryPoolMXBean mpm = @@ -124,7 +128,7 @@ public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta final SnmpOid[] indexes = cached.indexes; final Object[] datas = cached.datas; final int len = indexes.length; - final Map m = new HashMap(len); + final Map m = new HashMap<>(len); for (int i=0; i index - final Map poolIndexMap = buildPoolIndexMap(mpHandler); + final Map poolIndexMap = buildPoolIndexMap(mpHandler); // For each memory manager, get the list of memory pools // For each memory pool, find its index in the memory pool table // Create a row in the relation table. final TreeMap table = - new TreeMap(SnmpCachedData.oidComparator); + new TreeMap<>(SnmpCachedData.oidComparator); updateTreeMap(table,userData,mmHandler,mpHandler,poolIndexMap); return new SnmpCachedData(time,table); @@ -207,7 +211,7 @@ public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta protected void updateTreeMap(TreeMap table, Object userData, MemoryManagerMXBean mmm, SnmpOid mmIndex, - Map poolIndexMap) { + Map poolIndexMap) { // The MemoryManager index is an int, so it's the first // and only subidentifier. @@ -230,7 +234,7 @@ public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta for (int i = 0; i < mpList.length; i++) { final String mpmName = mpList[i]; if (mpmName == null) continue; - final SnmpOid mpIndex = (SnmpOid)poolIndexMap.get(mpmName); + final SnmpOid mpIndex = poolIndexMap.get(mpmName); if (mpIndex == null) continue; // The MemoryPool index is an int, so it's the first @@ -261,7 +265,7 @@ public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta protected void updateTreeMap(TreeMap table, Object userData, SnmpTableHandler mmHandler, SnmpTableHandler mpHandler, - Map poolIndexMap) { + Map poolIndexMap) { if (mmHandler instanceof SnmpCachedData) { updateTreeMap(table,userData,(SnmpCachedData)mmHandler, mpHandler,poolIndexMap); @@ -280,7 +284,7 @@ public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta protected void updateTreeMap(TreeMap table, Object userData, SnmpCachedData mmHandler, SnmpTableHandler mpHandler, - Map poolIndexMap) { + Map poolIndexMap) { final SnmpOid[] indexes = mmHandler.indexes; final Object[] datas = mmHandler.datas; diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemPoolTableMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemPoolTableMetaImpl.java index 1a3bf604df7..cb2d68675ea 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemPoolTableMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemPoolTableMetaImpl.java @@ -61,11 +61,16 @@ import sun.management.snmp.util.JvmContextFactory; */ public class JvmMemPoolTableMetaImpl extends JvmMemPoolTableMeta { + static final long serialVersionUID = -2525820976094284957L; + /** * A concrete implementation of {@link SnmpNamedListTableCache}, for the * jvmMemPoolTable. **/ private static class JvmMemPoolTableCache extends SnmpNamedListTableCache { + + static final long serialVersionUID = -1755520683086760574L; + /** * Create a weak cache for the jvmMemPoolTable. * @param validity validity of the cached data, in ms. @@ -86,7 +91,7 @@ public class JvmMemPoolTableMetaImpl extends JvmMemPoolTableMeta { * MemoryPoolMXBean in the list. * @return ((MemoryPoolMXBean)item).getName() **/ - protected String getKey(Object context, List rawDatas, + protected String getKey(Object context, List rawDatas, int rank, Object item) { if (item == null) return null; final String name = ((MemoryPoolMXBean)item).getName(); @@ -98,7 +103,7 @@ public class JvmMemPoolTableMetaImpl extends JvmMemPoolTableMeta { * Call getTableDatas(JvmContextFactory.getUserData()). **/ public SnmpTableHandler getTableHandler() { - final Map userData = JvmContextFactory.getUserData(); + final Map userData = JvmContextFactory.getUserData(); return getTableDatas(userData); } @@ -113,7 +118,7 @@ public class JvmMemPoolTableMetaImpl extends JvmMemPoolTableMeta { * Call ManagementFactory.getMemoryPoolMXBeans() to * load the raw data of this table. **/ - protected List loadRawDatas(Map userData) { + protected List loadRawDatas(Map userData) { return ManagementFactory.getMemoryPoolMXBeans(); } } diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemoryImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemoryImpl.java index 63a4e76394e..f95ec58537b 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemoryImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemoryImpl.java @@ -275,7 +275,7 @@ public class JvmMemoryImpl implements JvmMemoryMBean { */ public EnumJvmMemoryGCCall getJvmMemoryGCCall() throws SnmpStatusException { - final Map m = JvmContextFactory.getUserData(); + final Map m = JvmContextFactory.getUserData(); if (m != null) { final EnumJvmMemoryGCCall cached diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemoryMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemoryMetaImpl.java index be496066a68..207415eddbc 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemoryMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmMemoryMetaImpl.java @@ -50,6 +50,8 @@ import sun.management.snmp.util.MibLogger; * The class is used for representing SNMP metadata for the "JvmMemory" group. */ public class JvmMemoryMetaImpl extends JvmMemoryMeta { + + static final long serialVersionUID = -6500448253825893071L; /** * Constructor for the metadata associated to "JvmMemory". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmOSImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmOSImpl.java index 28c2929ecee..e001697727f 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmOSImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmOSImpl.java @@ -47,6 +47,8 @@ import sun.management.snmp.jvmmib.JvmOSMBean; */ public class JvmOSImpl implements JvmOSMBean, Serializable { + static final long serialVersionUID = 1839834731763310809L; + /** * Constructor for the "JvmOS" group. * If the group contains a table, the entries created through an diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTBootClassPathEntryImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTBootClassPathEntryImpl.java index 6624af601b6..6e423299947 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTBootClassPathEntryImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTBootClassPathEntryImpl.java @@ -44,6 +44,8 @@ import sun.management.snmp.jvmmib.JvmRTBootClassPathEntryMBean; public class JvmRTBootClassPathEntryImpl implements JvmRTBootClassPathEntryMBean, Serializable { + static final long serialVersionUID = -2282652055235913013L; + private final String item; private final int index; diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTBootClassPathTableMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTBootClassPathTableMetaImpl.java index abc548e43db..df794869bf1 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTBootClassPathTableMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTBootClassPathTableMetaImpl.java @@ -71,6 +71,8 @@ import sun.management.snmp.util.JvmContextFactory; public class JvmRTBootClassPathTableMetaImpl extends JvmRTBootClassPathTableMeta { + static final long serialVersionUID = -8659886610487538299L; + private SnmpTableCache cache; /** @@ -78,6 +80,7 @@ public class JvmRTBootClassPathTableMetaImpl * JvmRTBootClassPathTable. **/ private static class JvmRTBootClassPathTableCache extends SnmpTableCache { + static final long serialVersionUID = -2637458695413646098L; private JvmRTBootClassPathTableMetaImpl meta; JvmRTBootClassPathTableCache(JvmRTBootClassPathTableMetaImpl meta, @@ -90,7 +93,7 @@ public class JvmRTBootClassPathTableMetaImpl * Call getTableDatas(JvmContextFactory.getUserData()). **/ public SnmpTableHandler getTableHandler() { - final Map userData = JvmContextFactory.getUserData(); + final Map userData = JvmContextFactory.getUserData(); return getTableDatas(userData); } diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTClassPathEntryImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTClassPathEntryImpl.java index d52d1223ad3..188051afcb2 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTClassPathEntryImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTClassPathEntryImpl.java @@ -44,6 +44,7 @@ import sun.management.snmp.jvmmib.JvmRTClassPathEntryMBean; public class JvmRTClassPathEntryImpl implements JvmRTClassPathEntryMBean, Serializable { + static final long serialVersionUID = 8524792845083365742L; private final String item; private final int index; diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTClassPathTableMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTClassPathTableMetaImpl.java index 0e952cb1d7c..df6168d0221 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTClassPathTableMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTClassPathTableMetaImpl.java @@ -70,6 +70,8 @@ import sun.management.snmp.util.JvmContextFactory; */ public class JvmRTClassPathTableMetaImpl extends JvmRTClassPathTableMeta { + static final long serialVersionUID = -6914494148818455166L; + private SnmpTableCache cache; /** @@ -77,6 +79,7 @@ public class JvmRTClassPathTableMetaImpl extends JvmRTClassPathTableMeta { * JvmRTClassPathTable. **/ private static class JvmRTClassPathTableCache extends SnmpTableCache { + static final long serialVersionUID = 3805032372592117315L; private JvmRTClassPathTableMetaImpl meta; JvmRTClassPathTableCache(JvmRTClassPathTableMetaImpl meta, @@ -89,7 +92,7 @@ public class JvmRTClassPathTableMetaImpl extends JvmRTClassPathTableMeta { * Call getTableDatas(JvmContextFactory.getUserData()). **/ public SnmpTableHandler getTableHandler() { - final Map userData = JvmContextFactory.getUserData(); + final Map userData = JvmContextFactory.getUserData(); return getTableDatas(userData); } diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTInputArgsEntryImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTInputArgsEntryImpl.java index b480c48c5ff..80811ed39db 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTInputArgsEntryImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTInputArgsEntryImpl.java @@ -44,6 +44,7 @@ import sun.management.snmp.jvmmib.JvmRTInputArgsEntryMBean; public class JvmRTInputArgsEntryImpl implements JvmRTInputArgsEntryMBean, Serializable { + static final long serialVersionUID = 1000306518436503395L; private final String item; private final int index; diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTInputArgsTableMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTInputArgsTableMetaImpl.java index 259a2844c4b..13e5d4adff3 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTInputArgsTableMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTInputArgsTableMetaImpl.java @@ -70,6 +70,7 @@ import sun.management.snmp.util.JvmContextFactory; */ public class JvmRTInputArgsTableMetaImpl extends JvmRTInputArgsTableMeta { + static final long serialVersionUID = -2083438094888099238L; private SnmpTableCache cache; /** @@ -77,6 +78,8 @@ public class JvmRTInputArgsTableMetaImpl extends JvmRTInputArgsTableMeta { * JvmRTInputArgsTable. **/ private static class JvmRTInputArgsTableCache extends SnmpTableCache { + + static final long serialVersionUID = 1693751105464785192L; private JvmRTInputArgsTableMetaImpl meta; JvmRTInputArgsTableCache(JvmRTInputArgsTableMetaImpl meta, @@ -89,7 +92,7 @@ public class JvmRTInputArgsTableMetaImpl extends JvmRTInputArgsTableMeta { * Call getTableDatas(JvmContextFactory.getUserData()). **/ public SnmpTableHandler getTableHandler() { - final Map userData = JvmContextFactory.getUserData(); + final Map userData = JvmContextFactory.getUserData(); return getTableDatas(userData); } diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTLibraryPathEntryImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTLibraryPathEntryImpl.java index 5447768d88f..554b342b8f4 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTLibraryPathEntryImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTLibraryPathEntryImpl.java @@ -44,6 +44,7 @@ import sun.management.snmp.jvmmib.JvmRTLibraryPathEntryMBean; public class JvmRTLibraryPathEntryImpl implements JvmRTLibraryPathEntryMBean, Serializable { + static final long serialVersionUID = -3322438153507369765L; private final String item; private final int index; diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTLibraryPathTableMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTLibraryPathTableMetaImpl.java index 62b5ae82ffe..971677b8532 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTLibraryPathTableMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRTLibraryPathTableMetaImpl.java @@ -70,6 +70,7 @@ import sun.management.snmp.util.JvmContextFactory; */ public class JvmRTLibraryPathTableMetaImpl extends JvmRTLibraryPathTableMeta { + static final long serialVersionUID = 6713252710712502068L; private SnmpTableCache cache; /** @@ -77,6 +78,7 @@ public class JvmRTLibraryPathTableMetaImpl extends JvmRTLibraryPathTableMeta { * JvmRTLibraryPathTable. **/ private static class JvmRTLibraryPathTableCache extends SnmpTableCache { + static final long serialVersionUID = 2035304445719393195L; private JvmRTLibraryPathTableMetaImpl meta; JvmRTLibraryPathTableCache(JvmRTLibraryPathTableMetaImpl meta, @@ -89,7 +91,7 @@ public class JvmRTLibraryPathTableMetaImpl extends JvmRTLibraryPathTableMeta { * Call getTableDatas(JvmContextFactory.getUserData()). **/ public SnmpTableHandler getTableHandler() { - final Map userData = JvmContextFactory.getUserData(); + final Map userData = JvmContextFactory.getUserData(); return getTableDatas(userData); } diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRuntimeMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRuntimeMetaImpl.java index 895e8d227b1..1f15b4f80f7 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRuntimeMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmRuntimeMetaImpl.java @@ -68,6 +68,7 @@ import sun.management.snmp.jvmmib.JvmRTLibraryPathTableMeta; */ public class JvmRuntimeMetaImpl extends JvmRuntimeMeta { + static final long serialVersionUID = -6570428414857608618L; /** * Constructor for the metadata associated to "JvmRuntime". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadInstanceEntryImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadInstanceEntryImpl.java index 4410a7c1be8..77acb455b2c 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadInstanceEntryImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadInstanceEntryImpl.java @@ -53,6 +53,8 @@ import sun.management.snmp.util.MibLogger; public class JvmThreadInstanceEntryImpl implements JvmThreadInstanceEntryMBean, Serializable { + static final long serialVersionUID = 910173589985461347L; + public final static class ThreadStateMap { public final static class Byte0 { public final static byte inNative = (byte)0x80; // bit 1 diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadInstanceTableMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadInstanceTableMetaImpl.java index 0c9c2357dcd..b2ce4774c06 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadInstanceTableMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadInstanceTableMetaImpl.java @@ -78,6 +78,8 @@ import sun.management.snmp.util.JvmContextFactory; public class JvmThreadInstanceTableMetaImpl extends JvmThreadInstanceTableMeta { + static final long serialVersionUID = -8432271929226397492L; + /** * Maximum depth of the stacktrace that might be returned through * SNMP. @@ -135,6 +137,7 @@ public class JvmThreadInstanceTableMetaImpl private static class JvmThreadInstanceTableCache extends SnmpTableCache { + static final long serialVersionUID = 4947330124563406878L; final private JvmThreadInstanceTableMetaImpl meta; /** @@ -151,7 +154,7 @@ public class JvmThreadInstanceTableMetaImpl * Call getTableDatas(JvmContextFactory.getUserData()). **/ public SnmpTableHandler getTableHandler() { - final Map userData = JvmContextFactory.getUserData(); + final Map userData = JvmContextFactory.getUserData(); return getTableDatas(userData); } @@ -172,7 +175,7 @@ public class JvmThreadInstanceTableMetaImpl SnmpOid indexes[] = new SnmpOid[id.length]; final TreeMap table = - new TreeMap(SnmpCachedData.oidComparator); + new TreeMap<>(SnmpCachedData.oidComparator); for(int i = 0; i < id.length; i++) { log.debug("", "Making index for thread id [" + id[i] +"]"); //indexes[i] = makeOid(id[i]); @@ -277,7 +280,7 @@ public class JvmThreadInstanceTableMetaImpl // Get the request contextual cache (userData). // - final Map m = JvmContextFactory.getUserData(); + final Map m = JvmContextFactory.getUserData(); // Get the handler. // diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadingMetaImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadingMetaImpl.java index 9239e7dc264..f2773c5b0de 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadingMetaImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JvmThreadingMetaImpl.java @@ -66,6 +66,8 @@ import sun.management.snmp.jvmmib.JvmThreadInstanceTableMeta; */ public class JvmThreadingMetaImpl extends JvmThreadingMeta { + static final long serialVersionUID = -2104788458393251457L; + /** * Constructor for the metadata associated to "JvmThreading". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmClassesVerboseLevel.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmClassesVerboseLevel.java index caa7bc94370..16113d4b160 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmClassesVerboseLevel.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmClassesVerboseLevel.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmClassesVerboseLevel extends Enumerated implements Serializable { + static final long serialVersionUID = -620710366914810374L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "verbose"); intTable.put(new Integer(1), "silent"); @@ -70,11 +71,11 @@ public class EnumJvmClassesVerboseLevel extends Enumerated implements Serializab super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmJITCompilerTimeMonitoring.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmJITCompilerTimeMonitoring.java index 038d3796da5..e69bc4ebd62 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmJITCompilerTimeMonitoring.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmJITCompilerTimeMonitoring.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmJITCompilerTimeMonitoring extends Enumerated implements Serializable { + static final long serialVersionUID = 3953565918146461236L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "supported"); intTable.put(new Integer(1), "unsupported"); @@ -70,11 +71,11 @@ public class EnumJvmJITCompilerTimeMonitoring extends Enumerated implements Seri super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemManagerState.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemManagerState.java index fd2a324d62f..6eea58eb6a7 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemManagerState.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemManagerState.java @@ -43,10 +43,12 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmMemManagerState extends Enumerated implements Serializable { + static final long serialVersionUID = 8249515157795166343L; + protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "valid"); intTable.put(new Integer(1), "invalid"); @@ -70,11 +72,11 @@ public class EnumJvmMemManagerState extends Enumerated implements Serializable { super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolCollectThreshdSupport.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolCollectThreshdSupport.java index 5246160c174..6982ae7df07 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolCollectThreshdSupport.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolCollectThreshdSupport.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmMemPoolCollectThreshdSupport extends Enumerated implements Serializable { + static final long serialVersionUID = 8610091819732806282L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "supported"); intTable.put(new Integer(1), "unsupported"); @@ -70,11 +71,11 @@ public class EnumJvmMemPoolCollectThreshdSupport extends Enumerated implements S super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolState.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolState.java index 59c8f4bb0df..5046997454d 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolState.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolState.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmMemPoolState extends Enumerated implements Serializable { + static final long serialVersionUID = 3038175407527743027L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "valid"); intTable.put(new Integer(1), "invalid"); @@ -70,11 +71,11 @@ public class EnumJvmMemPoolState extends Enumerated implements Serializable { super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolThreshdSupport.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolThreshdSupport.java index acd00df649a..1da71f93e3c 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolThreshdSupport.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolThreshdSupport.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmMemPoolThreshdSupport extends Enumerated implements Serializable { + static final long serialVersionUID = 7014693561120661029L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "supported"); intTable.put(new Integer(1), "unsupported"); @@ -70,11 +71,11 @@ public class EnumJvmMemPoolThreshdSupport extends Enumerated implements Serializ super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolType.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolType.java index 99f0cd49cf8..add9fd2a606 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolType.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemPoolType.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmMemPoolType extends Enumerated implements Serializable { + static final long serialVersionUID = -7214498472962396555L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "heap"); intTable.put(new Integer(1), "nonheap"); @@ -70,11 +71,11 @@ public class EnumJvmMemPoolType extends Enumerated implements Serializable { super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemoryGCCall.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemoryGCCall.java index ecf024b269d..ca19740a443 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemoryGCCall.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemoryGCCall.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmMemoryGCCall extends Enumerated implements Serializable { + static final long serialVersionUID = -2869147994287351375L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "supported"); intTable.put(new Integer(5), "failed"); @@ -76,11 +77,11 @@ public class EnumJvmMemoryGCCall extends Enumerated implements Serializable { super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemoryGCVerboseLevel.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemoryGCVerboseLevel.java index 51205085ba0..90a718f4d19 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemoryGCVerboseLevel.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmMemoryGCVerboseLevel.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmMemoryGCVerboseLevel extends Enumerated implements Serializable { + static final long serialVersionUID = 1362427628755978190L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "verbose"); intTable.put(new Integer(1), "silent"); @@ -70,11 +71,11 @@ public class EnumJvmMemoryGCVerboseLevel extends Enumerated implements Serializa super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmRTBootClassPathSupport.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmRTBootClassPathSupport.java index 4ec327e0bf1..9d2276c4e2f 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmRTBootClassPathSupport.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmRTBootClassPathSupport.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmRTBootClassPathSupport extends Enumerated implements Serializable { + static final long serialVersionUID = -5957542680437939894L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(2), "supported"); intTable.put(new Integer(1), "unsupported"); @@ -70,11 +71,11 @@ public class EnumJvmRTBootClassPathSupport extends Enumerated implements Seriali super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmThreadContentionMonitoring.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmThreadContentionMonitoring.java index 04e7b6be886..83400b9e2ca 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmThreadContentionMonitoring.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmThreadContentionMonitoring.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmThreadContentionMonitoring extends Enumerated implements Serializable { + static final long serialVersionUID = -6411827583604137210L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(3), "enabled"); intTable.put(new Integer(4), "disabled"); @@ -72,11 +73,11 @@ public class EnumJvmThreadContentionMonitoring extends Enumerated implements Ser super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmThreadCpuTimeMonitoring.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmThreadCpuTimeMonitoring.java index 90193644d9c..aad2715c45f 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmThreadCpuTimeMonitoring.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/EnumJvmThreadCpuTimeMonitoring.java @@ -43,10 +43,11 @@ import com.sun.jmx.snmp.Enumerated; */ public class EnumJvmThreadCpuTimeMonitoring extends Enumerated implements Serializable { + static final long serialVersionUID = -532837824105215699L; protected static Hashtable intTable = - new Hashtable(); + new Hashtable<>(); protected static Hashtable stringTable = - new Hashtable(); + new Hashtable<>(); static { intTable.put(new Integer(3), "enabled"); intTable.put(new Integer(4), "disabled"); @@ -72,11 +73,11 @@ public class EnumJvmThreadCpuTimeMonitoring extends Enumerated implements Serial super(x); } - protected Hashtable getIntTable() { + protected Hashtable getIntTable() { return intTable ; } - protected Hashtable getStringTable() { + protected Hashtable getStringTable() { return stringTable ; } diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JVM_MANAGEMENT_MIB.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JVM_MANAGEMENT_MIB.java index 4cdf366f222..9206a4361c4 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JVM_MANAGEMENT_MIB.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JVM_MANAGEMENT_MIB.java @@ -53,6 +53,7 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public abstract class JVM_MANAGEMENT_MIB extends SnmpMib implements Serializable { + static final long serialVersionUID = 6895037919735816732L; /** * Default constructor. Initialize the Mib tree. */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JVM_MANAGEMENT_MIBOidTable.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JVM_MANAGEMENT_MIBOidTable.java index 1f48df65c52..e9a896ebffb 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JVM_MANAGEMENT_MIBOidTable.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JVM_MANAGEMENT_MIBOidTable.java @@ -47,6 +47,7 @@ import com.sun.jmx.snmp.SnmpOidTableSupport; */ public class JVM_MANAGEMENT_MIBOidTable extends SnmpOidTableSupport implements Serializable { + static final long serialVersionUID = -5010870014488732061L; /** * Default constructor. Initialize the Mib tree. */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmClassLoadingMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmClassLoadingMeta.java index a3182136fc1..806e3e368e7 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmClassLoadingMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmClassLoadingMeta.java @@ -70,6 +70,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmClassLoadingMeta extends SnmpMibGroup implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = 5722857476941218568L; /** * Constructor for the metadata associated to "JvmClassLoading". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmCompilationMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmCompilationMeta.java index 0fda62cbf9d..ab805b34877 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmCompilationMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmCompilationMeta.java @@ -70,6 +70,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmCompilationMeta extends SnmpMibGroup implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = -95492874115033638L; /** * Constructor for the metadata associated to "JvmCompilation". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemGCEntryMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemGCEntryMeta.java index c421937682e..4ee165ab105 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemGCEntryMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemGCEntryMeta.java @@ -71,6 +71,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmMemGCEntryMeta extends SnmpMibEntry implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = 6082082529298387063L; /** * Constructor for the metadata associated to "JvmMemGCEntry". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemGCTableMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemGCTableMeta.java index 58ed92c8596..2eff503a2eb 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemGCTableMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemGCTableMeta.java @@ -68,6 +68,7 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public class JvmMemGCTableMeta extends SnmpMibTable implements Serializable { + static final long serialVersionUID = -8843296871149264612L; /** * Constructor for the table. Initialize metadata for "JvmMemGCTableMeta". * The reference on the MBean server is updated so the entries created through an SNMP SET will be AUTOMATICALLY REGISTERED in Java DMK. diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemManagerEntryMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemManagerEntryMeta.java index dba777920f7..812ce8c6cb7 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemManagerEntryMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemManagerEntryMeta.java @@ -71,6 +71,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmMemManagerEntryMeta extends SnmpMibEntry implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = 8166956416408970453L; /** * Constructor for the metadata associated to "JvmMemManagerEntry". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemManagerTableMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemManagerTableMeta.java index 3247b3f2fe3..cb0d502b41a 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemManagerTableMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemManagerTableMeta.java @@ -68,6 +68,7 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public class JvmMemManagerTableMeta extends SnmpMibTable implements Serializable { + static final long serialVersionUID = 5026520607518015233L; /** * Constructor for the table. Initialize metadata for "JvmMemManagerTableMeta". * The reference on the MBean server is updated so the entries created through an SNMP SET will be AUTOMATICALLY REGISTERED in Java DMK. diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemMgrPoolRelEntryMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemMgrPoolRelEntryMeta.java index 00a1c588f5d..143b93ce231 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemMgrPoolRelEntryMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemMgrPoolRelEntryMeta.java @@ -71,6 +71,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmMemMgrPoolRelEntryMeta extends SnmpMibEntry implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = 7414270971113459798L; /** * Constructor for the metadata associated to "JvmMemMgrPoolRelEntry". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemMgrPoolRelTableMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemMgrPoolRelTableMeta.java index 1cf86879d9a..62af9f740b4 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemMgrPoolRelTableMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemMgrPoolRelTableMeta.java @@ -68,6 +68,7 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public class JvmMemMgrPoolRelTableMeta extends SnmpMibTable implements Serializable { + static final long serialVersionUID = -310733366542788998L; /** * Constructor for the table. Initialize metadata for "JvmMemMgrPoolRelTableMeta". * The reference on the MBean server is updated so the entries created through an SNMP SET will be AUTOMATICALLY REGISTERED in Java DMK. diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemPoolEntryMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemPoolEntryMeta.java index 14860291a2e..85cf5281319 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemPoolEntryMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemPoolEntryMeta.java @@ -71,6 +71,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmMemPoolEntryMeta extends SnmpMibEntry implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = 7220682779249102830L; /** * Constructor for the metadata associated to "JvmMemPoolEntry". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemPoolTableMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemPoolTableMeta.java index 43c8ec7fad5..150e4eebe8a 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemPoolTableMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmMemPoolTableMeta.java @@ -68,6 +68,8 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public class JvmMemPoolTableMeta extends SnmpMibTable implements Serializable { + static final long serialVersionUID = -2799470815264898659L; + /** * Constructor for the table. Initialize metadata for "JvmMemPoolTableMeta". * The reference on the MBean server is updated so the entries created through an SNMP SET will be AUTOMATICALLY REGISTERED in Java DMK. diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmOSMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmOSMeta.java index f3ab763c9e1..971b606a934 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmOSMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmOSMeta.java @@ -70,6 +70,8 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmOSMeta extends SnmpMibGroup implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = -2024138733580127133L; + /** * Constructor for the metadata associated to "JvmOS". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTBootClassPathEntryMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTBootClassPathEntryMeta.java index 3516ba7d3db..d0346a340a3 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTBootClassPathEntryMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTBootClassPathEntryMeta.java @@ -71,6 +71,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmRTBootClassPathEntryMeta extends SnmpMibEntry implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = 7703840715080588941L; /** * Constructor for the metadata associated to "JvmRTBootClassPathEntry". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTBootClassPathTableMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTBootClassPathTableMeta.java index 91684f76543..1b732a61291 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTBootClassPathTableMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTBootClassPathTableMeta.java @@ -68,6 +68,7 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public class JvmRTBootClassPathTableMeta extends SnmpMibTable implements Serializable { + static final long serialVersionUID = 42471379600792135L; /** * Constructor for the table. Initialize metadata for "JvmRTBootClassPathTableMeta". * The reference on the MBean server is updated so the entries created through an SNMP SET will be AUTOMATICALLY REGISTERED in Java DMK. diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTClassPathEntryMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTClassPathEntryMeta.java index 2b0089c0327..2c8464d8cbd 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTClassPathEntryMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTClassPathEntryMeta.java @@ -71,6 +71,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmRTClassPathEntryMeta extends SnmpMibEntry implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = 3388703998226830801L; /** * Constructor for the metadata associated to "JvmRTClassPathEntry". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTClassPathTableMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTClassPathTableMeta.java index 12719afe27d..1cf89307768 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTClassPathTableMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTClassPathTableMeta.java @@ -68,6 +68,7 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public class JvmRTClassPathTableMeta extends SnmpMibTable implements Serializable { + static final long serialVersionUID = -1518727175345404443L; /** * Constructor for the table. Initialize metadata for "JvmRTClassPathTableMeta". * The reference on the MBean server is updated so the entries created through an SNMP SET will be AUTOMATICALLY REGISTERED in Java DMK. diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTInputArgsEntryMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTInputArgsEntryMeta.java index dcb8660179a..1a8dcf0e4a4 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTInputArgsEntryMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTInputArgsEntryMeta.java @@ -71,6 +71,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmRTInputArgsEntryMeta extends SnmpMibEntry implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = -7729576810347358025L; /** * Constructor for the metadata associated to "JvmRTInputArgsEntry". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTInputArgsTableMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTInputArgsTableMeta.java index cf7c83628c7..8ee7982efde 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTInputArgsTableMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTInputArgsTableMeta.java @@ -68,6 +68,7 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public class JvmRTInputArgsTableMeta extends SnmpMibTable implements Serializable { + static final long serialVersionUID = 5395531763015738645L; /** * Constructor for the table. Initialize metadata for "JvmRTInputArgsTableMeta". * The reference on the MBean server is updated so the entries created through an SNMP SET will be AUTOMATICALLY REGISTERED in Java DMK. diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTLibraryPathEntryMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTLibraryPathEntryMeta.java index 81a4e686146..f89ac7495b0 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTLibraryPathEntryMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTLibraryPathEntryMeta.java @@ -71,6 +71,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmRTLibraryPathEntryMeta extends SnmpMibEntry implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = -5851555586263475792L; /** * Constructor for the metadata associated to "JvmRTLibraryPathEntry". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTLibraryPathTableMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTLibraryPathTableMeta.java index b052f87b346..5f9e1163123 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTLibraryPathTableMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRTLibraryPathTableMeta.java @@ -68,6 +68,7 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public class JvmRTLibraryPathTableMeta extends SnmpMibTable implements Serializable { + static final long serialVersionUID = -632403620113109468L; /** * Constructor for the table. Initialize metadata for "JvmRTLibraryPathTableMeta". * The reference on the MBean server is updated so the entries created through an SNMP SET will be AUTOMATICALLY REGISTERED in Java DMK. diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRuntimeMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRuntimeMeta.java index 377b6e785ff..d0c48263d05 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRuntimeMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmRuntimeMeta.java @@ -70,6 +70,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmRuntimeMeta extends SnmpMibGroup implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = 1994595220765880109L; /** * Constructor for the metadata associated to "JvmRuntime". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadInstanceEntryMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadInstanceEntryMeta.java index f921e022c20..a6c30c14673 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadInstanceEntryMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadInstanceEntryMeta.java @@ -71,6 +71,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmThreadInstanceEntryMeta extends SnmpMibEntry implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = -2015330111801477399L; /** * Constructor for the metadata associated to "JvmThreadInstanceEntry". */ diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadInstanceTableMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadInstanceTableMeta.java index 3f2a436f830..68613ba5711 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadInstanceTableMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadInstanceTableMeta.java @@ -68,6 +68,7 @@ import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; */ public class JvmThreadInstanceTableMeta extends SnmpMibTable implements Serializable { + static final long serialVersionUID = 2519514732589115954L; /** * Constructor for the table. Initialize metadata for "JvmThreadInstanceTableMeta". * The reference on the MBean server is updated so the entries created through an SNMP SET will be AUTOMATICALLY REGISTERED in Java DMK. diff --git a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadingMeta.java b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadingMeta.java index 39d3267ebaa..6d81f943780 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadingMeta.java +++ b/jdk/src/share/classes/sun/management/snmp/jvmmib/JvmThreadingMeta.java @@ -70,6 +70,7 @@ import com.sun.jmx.snmp.SnmpDefinitions; public class JvmThreadingMeta extends SnmpMibGroup implements Serializable, SnmpStandardMetaServer { + static final long serialVersionUID = 5223833578005322854L; /** * Constructor for the metadata associated to "JvmThreading". */ diff --git a/jdk/src/share/classes/sun/management/snmp/util/MibLogger.java b/jdk/src/share/classes/sun/management/snmp/util/MibLogger.java index 51fa0a0c29d..4d1a5f07d7e 100644 --- a/jdk/src/share/classes/sun/management/snmp/util/MibLogger.java +++ b/jdk/src/share/classes/sun/management/snmp/util/MibLogger.java @@ -32,7 +32,7 @@ public class MibLogger { final Logger logger; final String className; - static String getClassName(Class clazz) { + static String getClassName(Class clazz) { if (clazz == null) return null; if (clazz.isArray()) return getClassName(clazz.getComponentType()) + "[]"; @@ -44,7 +44,7 @@ public class MibLogger { else return fullname.substring(lastpoint+1,len); } - static String getLoggerName(Class clazz) { + static String getLoggerName(Class clazz) { if (clazz == null) return "sun.management.snmp.jvminstr"; Package p = clazz.getPackage(); if (p == null) return "sun.management.snmp.jvminstr"; @@ -53,11 +53,11 @@ public class MibLogger { else return pname; } - public MibLogger(Class clazz) { + public MibLogger(Class clazz) { this(getLoggerName(clazz),getClassName(clazz)); } - public MibLogger(Class clazz, String postfix) { + public MibLogger(Class clazz, String postfix) { this(getLoggerName(clazz)+((postfix==null)?"":"."+postfix), getClassName(clazz)); } diff --git a/jdk/src/share/classes/sun/management/snmp/util/SnmpListTableCache.java b/jdk/src/share/classes/sun/management/snmp/util/SnmpListTableCache.java index f2aab9f1894..634f2bff06a 100644 --- a/jdk/src/share/classes/sun/management/snmp/util/SnmpListTableCache.java +++ b/jdk/src/share/classes/sun/management/snmp/util/SnmpListTableCache.java @@ -59,7 +59,7 @@ public abstract class SnmpListTableCache extends SnmpTableCache { * rawDatas list iterator. * @param item The raw data object for which an index must be determined. **/ - protected abstract SnmpOid getIndex(Object context, List rawDatas, + protected abstract SnmpOid getIndex(Object context, List rawDatas, int rank, Object item); /** @@ -75,7 +75,7 @@ public abstract class SnmpListTableCache extends SnmpTableCache { * extracted. * @return By default item is returned. **/ - protected Object getData(Object context, List rawDatas, + protected Object getData(Object context, List rawDatas, int rank, Object item) { return item; } @@ -95,14 +95,14 @@ public abstract class SnmpListTableCache extends SnmpTableCache { * computed. * @return the computed cached data. **/ - protected SnmpCachedData updateCachedDatas(Object context, List rawDatas) { + protected SnmpCachedData updateCachedDatas(Object context, List rawDatas) { final int size = ((rawDatas == null)?0:rawDatas.size()); if (size == 0) return null; final long time = System.currentTimeMillis(); - final Iterator it = rawDatas.iterator(); + final Iterator it = rawDatas.iterator(); final TreeMap map = - new TreeMap(SnmpCachedData.oidComparator); + new TreeMap<>(SnmpCachedData.oidComparator); for (int rank=0; it.hasNext() ; rank++) { final Object item = it.next(); final SnmpOid index = getIndex(context, rawDatas, rank, item); diff --git a/jdk/src/share/classes/sun/management/snmp/util/SnmpNamedListTableCache.java b/jdk/src/share/classes/sun/management/snmp/util/SnmpNamedListTableCache.java index b3955f3b4e6..494919d69f2 100644 --- a/jdk/src/share/classes/sun/management/snmp/util/SnmpNamedListTableCache.java +++ b/jdk/src/share/classes/sun/management/snmp/util/SnmpNamedListTableCache.java @@ -55,7 +55,7 @@ public abstract class SnmpNamedListTableCache extends SnmpListTableCache { * This map associate an entry name with the SnmpOid index that's * been allocated for it. **/ - protected TreeMap names = new TreeMap(); + protected TreeMap names = new TreeMap<>(); /** * The last allocate index. @@ -80,7 +80,7 @@ public abstract class SnmpNamedListTableCache extends SnmpListTableCache { * rawDatas list iterator. * @param item The raw data object for which a key name must be determined. **/ - protected abstract String getKey(Object context, List rawDatas, + protected abstract String getKey(Object context, List rawDatas, int rank, Object item); /** @@ -97,7 +97,7 @@ public abstract class SnmpNamedListTableCache extends SnmpListTableCache { * rawDatas list iterator. * @param item The raw data object for which an index must be determined. **/ - protected SnmpOid makeIndex(Object context, List rawDatas, + protected SnmpOid makeIndex(Object context, List rawDatas, int rank, Object item) { // check we are in the limits of an unsigned32. @@ -151,7 +151,7 @@ public abstract class SnmpNamedListTableCache extends SnmpListTableCache { * rawDatas list iterator. * @param item The raw data object for which an index must be determined. **/ - protected SnmpOid getIndex(Object context, List rawDatas, + protected SnmpOid getIndex(Object context, List rawDatas, int rank, Object item) { final String key = getKey(context,rawDatas,rank,item); final Object index = (names==null||key==null)?null:names.get(key); @@ -174,8 +174,8 @@ public abstract class SnmpNamedListTableCache extends SnmpListTableCache { * @param rawDatas The table datas from which the cached data will be * computed. **/ - protected SnmpCachedData updateCachedDatas(Object context, List rawDatas) { - TreeMap ctxt = new TreeMap(); + protected SnmpCachedData updateCachedDatas(Object context, List rawDatas) { + TreeMap ctxt = new TreeMap<>(); final SnmpCachedData result = super.updateCachedDatas(context,rawDatas); names = ctxt; @@ -191,7 +191,7 @@ public abstract class SnmpNamedListTableCache extends SnmpListTableCache { * the {@link JvmContextFactory}. * **/ - protected abstract List loadRawDatas(Map userData); + protected abstract List loadRawDatas(Map userData); /** *The name under which the raw data is to be found/put in @@ -212,16 +212,16 @@ public abstract class SnmpNamedListTableCache extends SnmpListTableCache { * the request contextual cache. * **/ - protected List getRawDatas(Map userData, String key) { - List rawDatas = null; + protected List getRawDatas(Map userData, String key) { + List rawDatas = null; // Look for memory manager list in request contextual cache. if (userData != null) - rawDatas = (List) userData.get(key); + rawDatas = (List)userData.get(key); if (rawDatas == null) { // No list in contextual cache, get it from API - rawDatas = loadRawDatas(userData); + rawDatas = loadRawDatas(userData); // Put list in cache... @@ -250,12 +250,12 @@ public abstract class SnmpNamedListTableCache extends SnmpListTableCache { (context instanceof Map)?Util.>cast(context):null; // Look for memory manager list in request contextual cache. - final List rawDatas = getRawDatas(userData,getRawDatasKey()); + final List rawDatas = getRawDatas(userData,getRawDatasKey()); log.debug("updateCachedDatas","rawDatas.size()=" + ((rawDatas==null)?"":""+rawDatas.size())); - TreeMap ctxt = new TreeMap(); + TreeMap ctxt = new TreeMap<>(); final SnmpCachedData result = super.updateCachedDatas(ctxt,rawDatas); names = ctxt; diff --git a/jdk/src/share/classes/sun/management/snmp/util/SnmpTableCache.java b/jdk/src/share/classes/sun/management/snmp/util/SnmpTableCache.java index d65e5afe9f0..0786f210b57 100644 --- a/jdk/src/share/classes/sun/management/snmp/util/SnmpTableCache.java +++ b/jdk/src/share/classes/sun/management/snmp/util/SnmpTableCache.java @@ -98,7 +98,7 @@ public abstract class SnmpTableCache implements Serializable { final SnmpCachedData cached = getCachedDatas(); if (cached != null) return cached; final SnmpCachedData computedDatas = updateCachedDatas(context); - if (validity != 0) datas = new WeakReference(computedDatas); + if (validity != 0) datas = new WeakReference<>(computedDatas); return computedDatas; } From 3d0da40b0d2b54b06c67b43060ba40cdd9228f9c Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Tue, 17 Jan 2012 17:14:44 -0800 Subject: [PATCH 46/96] 7127924: langtools regression tests sometimes fail en-masse on windows Reviewed-by: jjg --- langtools/test/tools/javac/diags/CheckExamples.java | 7 +++++-- langtools/test/tools/javac/diags/MessageInfo.java | 7 +++++-- langtools/test/tools/javac/diags/RunExamples.java | 7 +++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/langtools/test/tools/javac/diags/CheckExamples.java b/langtools/test/tools/javac/diags/CheckExamples.java index b29c5447b97..648f9833e6c 100644 --- a/langtools/test/tools/javac/diags/CheckExamples.java +++ b/langtools/test/tools/javac/diags/CheckExamples.java @@ -23,10 +23,13 @@ /* * @test - * @bug 6968063 + * @bug 6968063, 7127924 * @summary provide examples of code that generate diagnostics * @build Example CheckExamples - * @run main CheckExamples + * @run main/othervm CheckExamples + */ +/* + * See CR 7127924 for info on why othervm is used. */ import java.io.*; diff --git a/langtools/test/tools/javac/diags/MessageInfo.java b/langtools/test/tools/javac/diags/MessageInfo.java index 885183cd1d8..8e40670efca 100644 --- a/langtools/test/tools/javac/diags/MessageInfo.java +++ b/langtools/test/tools/javac/diags/MessageInfo.java @@ -23,10 +23,13 @@ /** * @test - * @bug 7013272 + * @bug 7013272, 7127924 * @summary Automatically generate info about how compiler resource keys are used * @build Example ArgTypeCompilerFactory MessageFile MessageInfo - * @run main MessageInfo + * @run main/othervm MessageInfo + */ +/* + * See CR 7127924 for info on why othervm is used. */ import java.io.*; diff --git a/langtools/test/tools/javac/diags/RunExamples.java b/langtools/test/tools/javac/diags/RunExamples.java index e4234d53a3b..c09947cdf3e 100644 --- a/langtools/test/tools/javac/diags/RunExamples.java +++ b/langtools/test/tools/javac/diags/RunExamples.java @@ -23,10 +23,13 @@ /** * @test - * @bug 6968063 + * @bug 6968063, 7127924 * @summary provide examples of code that generate diagnostics * @build ArgTypeCompilerFactory Example HTMLWriter RunExamples - * @run main RunExamples + * @run main/othervm RunExamples + */ +/* + * See CR 7127924 for info on why othervm is used. */ import java.io.*; From d5d6252e5bb0d248471b412dd43dfebb5242b011 Mon Sep 17 00:00:00 2001 From: Matt Smith Date: Wed, 18 Jan 2012 19:09:26 +0400 Subject: [PATCH 47/96] 7130662: GTK file dialog crashes with a NPE Guard adding a back slash to the directory name with an if (!= null) check Reviewed-by: anthony, art --- .../solaris/classes/sun/awt/X11/GtkFileDialogPeer.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java b/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java index 41f5398a788..ebd434a96df 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java @@ -76,9 +76,12 @@ class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer { accessor.setFiles(fd, null, null); } else { // Fix 6987233: add the trailing slash if it's absent - accessor.setDirectory(fd, directory + - (directory.endsWith(File.separator) ? - "" : File.separator)); + String with_separator = directory; + if (directory != null) { + with_separator = directory.endsWith(File.separator) ? + directory : (directory + File.separator); + } + accessor.setDirectory(fd, with_separator); accessor.setFile(fd, filenames[0]); accessor.setFiles(fd, directory, filenames); } From b11b6e4ddae3ea2ca190bca39a6e8d11d637e31e Mon Sep 17 00:00:00 2001 From: Bertrand Delsart Date: Wed, 18 Jan 2012 16:18:31 +0100 Subject: [PATCH 48/96] 7120448: Fix FP values for compiled frames in frame::describe Fix for debug method frame::describe Reviewed-by: never, kvn --- .../src/cpu/sparc/vm/frame_sparc.inline.hpp | 4 +++- hotspot/src/cpu/x86/vm/frame_x86.cpp | 20 ++++++++++++++++++- hotspot/src/cpu/x86/vm/frame_x86.hpp | 3 ++- hotspot/src/cpu/zero/vm/frame_zero.inline.hpp | 6 +++++- hotspot/src/share/vm/runtime/frame.cpp | 19 ++++++++---------- hotspot/src/share/vm/runtime/frame.hpp | 11 +++++++++- 6 files changed, 47 insertions(+), 16 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp index 3a8bc79b823..381f235d26f 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,6 +82,8 @@ inline address* frame::O0_addr() const { return (address*) &younger_sp()[ I0->s inline intptr_t* frame::sender_sp() const { return fp(); } +inline intptr_t* frame::real_fp() const { return fp(); } + // Used only in frame::oopmapreg_to_location // This return a value in VMRegImpl::slot_size inline int frame::pd_oop_map_offset_adjustment() const { diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp index 5d4da62607e..94166ea0fef 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -675,3 +675,21 @@ intptr_t *frame::initial_deoptimization_info() { // used to reset the saved FP return fp(); } + +intptr_t* frame::real_fp() const { + if (_cb != NULL) { + // use the frame size if valid + int size = _cb->frame_size(); + if ((size > 0) && + (! is_ricochet_frame())) { + // Work-around: ricochet explicitly excluded because frame size is not + // constant for the ricochet blob but its frame_size could not, for + // some reasons, be declared as <= 0. This potentially confusing + // size declaration should be fixed as another CR. + return unextended_sp() + size; + } + } + // else rely on fp() + assert(! is_compiled_frame(), "unknown compiled frame size"); + return fp(); +} diff --git a/hotspot/src/cpu/x86/vm/frame_x86.hpp b/hotspot/src/cpu/x86/vm/frame_x86.hpp index a307a340428..01f6e6cc822 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,6 +188,7 @@ frame(intptr_t* sp, intptr_t* fp); // accessors for the instance variables + // Note: not necessarily the real 'frame pointer' (see real_fp) intptr_t* fp() const { return _fp; } inline address* sender_pc_addr() const; diff --git a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp index 9ad237de945..d4c272b1191 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -72,6 +72,10 @@ inline intptr_t* frame::sender_sp() const { return fp() + 1; } +inline intptr_t* frame::real_fp() const { + return fp(); +} + inline intptr_t* frame::link() const { ShouldNotCallThis(); } diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index c3a08529a38..7f4a2ac6558 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1334,24 +1334,21 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const { void frame::describe(FrameValues& values, int frame_no) { + intptr_t* frame_pointer = real_fp(); if (is_entry_frame() || is_compiled_frame() || is_interpreted_frame() || is_native_frame()) { // Label values common to most frames values.describe(-1, unextended_sp(), err_msg("unextended_sp for #%d", frame_no)); values.describe(-1, sp(), err_msg("sp for #%d", frame_no)); - if (is_compiled_frame()) { - values.describe(-1, sp() + _cb->frame_size(), err_msg("computed fp for #%d", frame_no)); - } else { - values.describe(-1, fp(), err_msg("fp for #%d", frame_no)); - } + values.describe(-1, frame_pointer, err_msg("frame pointer for #%d", frame_no)); } if (is_interpreted_frame()) { methodOop m = interpreter_frame_method(); int bci = interpreter_frame_bci(); // Label the method and current bci - values.describe(-1, MAX2(sp(), fp()), + values.describe(-1, MAX2(sp(), frame_pointer), FormatBuffer<1024>("#%d method %s @ %d", frame_no, m->name_and_sig_as_C_string(), bci), 2); - values.describe(-1, MAX2(sp(), fp()), + values.describe(-1, MAX2(sp(), frame_pointer), err_msg("- %d locals %d max stack", m->max_locals(), m->max_stack()), 1); if (m->max_locals() > 0) { intptr_t* l0 = interpreter_frame_local_at(0); @@ -1383,18 +1380,18 @@ void frame::describe(FrameValues& values, int frame_no) { } } else if (is_entry_frame()) { // For now just label the frame - values.describe(-1, MAX2(sp(), fp()), err_msg("#%d entry frame", frame_no), 2); + values.describe(-1, MAX2(sp(), frame_pointer), err_msg("#%d entry frame", frame_no), 2); } else if (is_compiled_frame()) { // For now just label the frame nmethod* nm = cb()->as_nmethod_or_null(); - values.describe(-1, MAX2(sp(), fp()), + values.describe(-1, MAX2(sp(), frame_pointer), FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method %s%s", frame_no, nm, nm->method()->name_and_sig_as_C_string(), is_deoptimized_frame() ? " (deoptimized" : ""), 2); } else if (is_native_frame()) { // For now just label the frame nmethod* nm = cb()->as_nmethod_or_null(); - values.describe(-1, MAX2(sp(), fp()), + values.describe(-1, MAX2(sp(), frame_pointer), FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for native method %s", frame_no, nm, nm->method()->name_and_sig_as_C_string()), 2); } diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index ec00e3a68b3..02e06d160a4 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -221,6 +221,15 @@ class frame VALUE_OBJ_CLASS_SPEC { // returns the stack pointer of the calling frame intptr_t* sender_sp() const; + // Returns the real 'frame pointer' for the current frame. + // This is the value expected by the platform ABI when it defines a + // frame pointer register. It may differ from the effective value of + // the FP register when that register is used in the JVM for other + // purposes (like compiled frames on some platforms). + // On other platforms, it is defined so that the stack area used by + // this frame goes from real_fp() to sp(). + intptr_t* real_fp() const; + // Deoptimization info, if needed (platform dependent). // Stored in the initial_info field of the unroll info, to be used by // the platform dependent deoptimization blobs. From dce4a696bfad7cbd77ef2bc490b939fcb91b03e6 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Wed, 18 Jan 2012 11:45:14 -0500 Subject: [PATCH 49/96] 7131050: fix for "7071311 Decoder enhancement" does not build on MacOS X Decoder API changes did not reflect in os_bsd Reviewed-by: kamg, dcubed --- hotspot/src/os/bsd/vm/os_bsd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index c6e27b273fd..2526e65f229 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -1920,7 +1920,7 @@ bool os::dll_address_to_function_name(address addr, char *buf, return true; } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + buf, buflen, offset, dlinfo.dli_fname)) { return true; } } From c569749a21865c071db7b7669b4ff8c172c0c20c Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 18 Jan 2012 16:43:59 -0800 Subject: [PATCH 50/96] 7130768: Clarify behavior of Element.getEnclosingElements in subtypes Reviewed-by: mcimadamore, jjg --- .../javax/lang/model/element/Element.java | 17 +++++++++-------- .../lang/model/element/PackageElement.java | 18 ++++++++++++++++-- .../javax/lang/model/element/TypeElement.java | 10 ++++++++-- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/langtools/src/share/classes/javax/lang/model/element/Element.java b/langtools/src/share/classes/javax/lang/model/element/Element.java index 06500d2afaf..6d2743ca324 100644 --- a/langtools/src/share/classes/javax/lang/model/element/Element.java +++ b/langtools/src/share/classes/javax/lang/model/element/Element.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -214,14 +214,13 @@ public interface Element { * Returns the elements that are, loosely speaking, directly * enclosed by this element. * - * A class or interface is considered to enclose the fields, - * methods, constructors, and member types that it directly - * declares. This includes any (implicit) default constructor and - * the implicit {@code values} and {@code valueOf} methods of an - * enum type. + * A {@linkplain TypeElement#getEnclosedElements class or + * interface} is considered to enclose the fields, methods, + * constructors, and member types that it directly declares. * - * A package encloses the top-level classes and interfaces within - * it, but is not considered to enclose subpackages. + * A {@linkplain PackageElement#getEnclosedElements package} + * encloses the top-level classes and interfaces within it, but is + * not considered to enclose subpackages. * * Other kinds of elements are not currently considered to enclose * any elements; however, that may change as this API or the @@ -231,6 +230,8 @@ public interface Element { * methods in {@link ElementFilter}. * * @return the enclosed elements, or an empty list if none + * @see PackageElement#getEnclosedElements + * @see TypeElement#getEnclosedElements * @see Elements#getAllMembers * @jls 8.8.9 Default Constructor * @jls 8.9 Enums diff --git a/langtools/src/share/classes/javax/lang/model/element/PackageElement.java b/langtools/src/share/classes/javax/lang/model/element/PackageElement.java index 66f13863ff0..1aafd3476f9 100644 --- a/langtools/src/share/classes/javax/lang/model/element/PackageElement.java +++ b/langtools/src/share/classes/javax/lang/model/element/PackageElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package javax.lang.model.element; +import java.util.List; + /** * Represents a package program element. Provides access to information * about the package and its members. @@ -49,7 +51,7 @@ public interface PackageElement extends Element, QualifiedNameable { /** * Returns the simple name of this package. For an unnamed - * package, an empty name is returned + * package, an empty name is returned. * * @return the simple name of this package or an empty name if * this is an unnamed package @@ -57,6 +59,18 @@ public interface PackageElement extends Element, QualifiedNameable { @Override Name getSimpleName(); + /** + * Returns the {@linkplain NestingKind#TOP_LEVEL top-level} + * classes and interfaces within this package. Note that + * subpackages are not considered to be enclosed by a + * package. + * + * @return the top-level classes and interfaces within this + * package + */ + @Override + List getEnclosedElements(); + /** * Returns {@code true} is this is an unnamed package and {@code * false} otherwise. diff --git a/langtools/src/share/classes/javax/lang/model/element/TypeElement.java b/langtools/src/share/classes/javax/lang/model/element/TypeElement.java index d73adfeec7e..a86db829b21 100644 --- a/langtools/src/share/classes/javax/lang/model/element/TypeElement.java +++ b/langtools/src/share/classes/javax/lang/model/element/TypeElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,12 @@ import javax.lang.model.util.*; */ public interface TypeElement extends Element, Parameterizable, QualifiedNameable { /** - * {@inheritDoc} + * Returns the fields, methods, constructors, and member types + * that are directly declared in this class or interface. + * + * This includes any (implicit) default constructor and + * the implicit {@code values} and {@code valueOf} methods of an + * enum type. * *

    Note that as a particular instance of the {@linkplain * javax.lang.model.element general accuracy requirements} and the @@ -75,6 +80,7 @@ public interface TypeElement extends Element, Parameterizable, QualifiedNameable * * @return the enclosed elements in proper order, or an empty list if none */ + @Override List getEnclosedElements(); /** From ef856f2fe0812a8a38e409e643b12a30a2d5d1f9 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Wed, 18 Jan 2012 17:34:29 -0800 Subject: [PATCH 51/96] 7117167: Misc warnings in java.lang.invoke and sun.invoke.* Reviewed-by: smarks --- .../java/lang/invoke/AdapterMethodHandle.java | 4 + .../classes/java/lang/invoke/MemberName.java | 2 +- .../java/lang/invoke/MethodHandleImpl.java | 61 +++++++------ .../java/lang/invoke/MethodHandleProxies.java | 2 +- .../java/lang/invoke/MethodHandles.java | 1 + .../sun/invoke/util/ValueConversions.java | 8 +- .../classes/sun/invoke/util/Wrapper.java | 4 +- jdk/test/java/lang/invoke/CallSiteTest.java | 2 +- jdk/test/java/lang/invoke/ClassValueTest.java | 4 - .../java/lang/invoke/InvokeGenericTest.java | 34 +++---- .../java/lang/invoke/JavaDocExamplesTest.java | 2 + .../java/lang/invoke/MethodHandlesTest.java | 89 ++++++++++--------- jdk/test/java/lang/invoke/MethodTypeTest.java | 5 +- .../java/lang/invoke/PermuteArgsTest.java | 14 +-- jdk/test/java/lang/invoke/RicochetTest.java | 18 ++-- .../java/lang/invoke/ThrowExceptionsTest.java | 6 +- .../sun/invoke/util/ValueConversionsTest.java | 7 +- 17 files changed, 137 insertions(+), 126 deletions(-) diff --git a/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java index 7cfc7740627..82ac5704403 100644 --- a/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java @@ -378,6 +378,7 @@ class AdapterMethodHandle extends BoundMethodHandle { } /** Construct an adapter conversion descriptor for a single-argument conversion. */ + @SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings private static long makeConv(int convOp, int argnum, int src, int dest) { assert(src == (src & CONV_TYPE_MASK)); assert(dest == (dest & CONV_TYPE_MASK)); @@ -390,6 +391,7 @@ class AdapterMethodHandle extends BoundMethodHandle { insertStackMove(stackMove) ); } + @SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings private static long makeDupConv(int convOp, int argnum, int stackMove) { // simple argument motion, requiring one slot to specify assert(convOp == OP_DUP_ARGS || convOp == OP_DROP_ARGS); @@ -401,6 +403,7 @@ class AdapterMethodHandle extends BoundMethodHandle { insertStackMove(stackMove) ); } + @SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings private static long makeSwapConv(int convOp, int srcArg, byte srcType, int destSlot, byte destType) { // more complex argument motion, requiring two slots to specify assert(convOp == OP_SWAP_ARGS || convOp == OP_ROT_ARGS); @@ -411,6 +414,7 @@ class AdapterMethodHandle extends BoundMethodHandle { (int) destSlot << CONV_VMINFO_SHIFT ); } + @SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings private static long makeSpreadConv(int convOp, int argnum, int src, int dest, int stackMove) { // spreading or collecting, at a particular slot location assert(convOp == OP_SPREAD_ARGS || convOp == OP_COLLECT_ARGS || convOp == OP_FOLD_ARGS); diff --git a/jdk/src/share/classes/java/lang/invoke/MemberName.java b/jdk/src/share/classes/java/lang/invoke/MemberName.java index bf72c5bce2d..5a431a53a8b 100644 --- a/jdk/src/share/classes/java/lang/invoke/MemberName.java +++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java @@ -353,7 +353,7 @@ import static java.lang.invoke.MethodHandleStatics.*; assert(isResolved()); } /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */ - public MemberName(Constructor ctor) { + public MemberName(Constructor ctor) { Object[] typeInfo = { void.class, ctor.getParameterTypes() }; init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers())); // fill in vmtarget, vmindex while we have ctor in hand: diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java index c0beb39fd9f..2c5adb3e9e5 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -112,7 +112,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; assert(cookedConstructor.type().equals(ctype)); ctype = ctype.dropParameterTypes(0, 1); cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true); - MethodHandle allocator = new AllocateObject(allocateClass); + AllocateObject allocator = new AllocateObject(allocateClass); // allocate() => new C(void) assert(allocator.type().equals(MethodType.methodType(allocateClass))); ctype = ctype.dropParameterTypes(0, 1); @@ -120,19 +120,19 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return fold; } - static final class AllocateObject extends BoundMethodHandle { + static final class AllocateObject /**/ extends BoundMethodHandle { private static final Unsafe unsafe = Unsafe.getUnsafe(); - private final Class allocateClass; + private final Class /**/ allocateClass; // for allocation only: - private AllocateObject(Class allocateClass) { + private AllocateObject(Class /**/ allocateClass) { super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class))); this.allocateClass = allocateClass; } @SuppressWarnings("unchecked") - private C allocate() throws InstantiationException { - return (C) unsafe.allocateInstance(allocateClass); + private Object /*C*/ allocate() throws InstantiationException { + return unsafe.allocateInstance(allocateClass); } static final MethodHandle ALLOCATE; static { @@ -148,8 +148,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MethodHandle accessField(MemberName member, boolean isSetter, Class lookupClass) { // Use sun. misc.Unsafe to dig up the dirt on the field. - MethodHandle mh = new FieldAccessor(member, isSetter); - return mh; + FieldAccessor accessor = new FieldAccessor(member, isSetter); + return accessor; } static @@ -175,7 +175,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return mhs[isSetter ? 1 : 0]; } - static final class FieldAccessor extends BoundMethodHandle { + static final class FieldAccessor /**/ extends BoundMethodHandle { private static final Unsafe unsafe = Unsafe.getUnsafe(); final Object base; // for static refs only final long offset; @@ -190,26 +190,24 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; @Override String debugString() { return addTypeString(name, this); } - int getFieldI(C obj) { return unsafe.getInt(obj, offset); } - void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); } - long getFieldJ(C obj) { return unsafe.getLong(obj, offset); } - void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); } - float getFieldF(C obj) { return unsafe.getFloat(obj, offset); } - void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); } - double getFieldD(C obj) { return unsafe.getDouble(obj, offset); } - void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); } - boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); } - void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); } - byte getFieldB(C obj) { return unsafe.getByte(obj, offset); } - void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); } - short getFieldS(C obj) { return unsafe.getShort(obj, offset); } - void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); } - char getFieldC(C obj) { return unsafe.getChar(obj, offset); } - void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); } - @SuppressWarnings("unchecked") - V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); } - @SuppressWarnings("unchecked") - void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); } + int getFieldI(Object /*C*/ obj) { return unsafe.getInt(obj, offset); } + void setFieldI(Object /*C*/ obj, int x) { unsafe.putInt(obj, offset, x); } + long getFieldJ(Object /*C*/ obj) { return unsafe.getLong(obj, offset); } + void setFieldJ(Object /*C*/ obj, long x) { unsafe.putLong(obj, offset, x); } + float getFieldF(Object /*C*/ obj) { return unsafe.getFloat(obj, offset); } + void setFieldF(Object /*C*/ obj, float x) { unsafe.putFloat(obj, offset, x); } + double getFieldD(Object /*C*/ obj) { return unsafe.getDouble(obj, offset); } + void setFieldD(Object /*C*/ obj, double x) { unsafe.putDouble(obj, offset, x); } + boolean getFieldZ(Object /*C*/ obj) { return unsafe.getBoolean(obj, offset); } + void setFieldZ(Object /*C*/ obj, boolean x) { unsafe.putBoolean(obj, offset, x); } + byte getFieldB(Object /*C*/ obj) { return unsafe.getByte(obj, offset); } + void setFieldB(Object /*C*/ obj, byte x) { unsafe.putByte(obj, offset, x); } + short getFieldS(Object /*C*/ obj) { return unsafe.getShort(obj, offset); } + void setFieldS(Object /*C*/ obj, short x) { unsafe.putShort(obj, offset, x); } + char getFieldC(Object /*C*/ obj) { return unsafe.getChar(obj, offset); } + void setFieldC(Object /*C*/ obj, char x) { unsafe.putChar(obj, offset, x); } + Object /*V*/ getFieldL(Object /*C*/ obj) { return unsafe.getObject(obj, offset); } + void setFieldL(Object /*C*/ obj, Object /*V*/ x) { unsafe.putObject(obj, offset, x); } // cast (V) is OK here, since we wrap convertArguments around the MH. static Object staticBase(final MemberName field) { @@ -244,8 +242,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; void setStaticS(short x) { unsafe.putShort(base, offset, x); } char getStaticC() { return unsafe.getChar(base, offset); } void setStaticC(char x) { unsafe.putChar(base, offset, x); } - V getStaticL() { return (V) unsafe.getObject(base, offset); } - void setStaticL(V x) { unsafe.putObject(base, offset, x); } + @SuppressWarnings("unchecked") // (V) is for internal clarity but triggers warning + Object /*V*/ getStaticL() { return unsafe.getObject(base, offset); } + void setStaticL(Object /*V*/ x) { unsafe.putObject(base, offset, x); } static String fname(Class vclass, boolean isSetter, boolean isStatic) { String stem; diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java index 46be8a9fdc8..8e068238b1f 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -150,7 +150,7 @@ public class MethodHandleProxies { } return intfc.cast(Proxy.newProxyInstance( intfc.getClassLoader(), - new Class[]{ intfc, WrapperInstance.class }, + new Class[]{ intfc, WrapperInstance.class }, new InvocationHandler() { private Object getArg(String name) { if ((Object)name == "getWrapperInstanceTarget") return target; diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java index e49169d0bef..700f433bc86 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java @@ -1006,6 +1006,7 @@ return mh1; * is set and {@code asVarargsCollector} fails * @throws NullPointerException if the argument is null */ + @SuppressWarnings("rawtypes") // Will be Constructor after JSR 292 MR public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException { MemberName ctor = new MemberName(c); assert(ctor.isConstructor()); diff --git a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java index cab961a0ff2..5fd1e8b15c4 100644 --- a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java +++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java @@ -55,9 +55,9 @@ public class ValueConversions { private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); private static EnumMap[] newWrapperCaches(int n) { - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") // generic array creation EnumMap[] caches - = (EnumMap[]) new EnumMap[n]; // unchecked warning expected here + = (EnumMap[]) new EnumMap[n]; for (int i = 0; i < n; i++) caches[i] = new EnumMap<>(Wrapper.class); return caches; @@ -1097,7 +1097,7 @@ public class ValueConversions { } private static MethodHandle buildNewArray(int nargs) { - return MethodHandles.insertArguments(NEW_ARRAY, 0, (int) nargs); + return MethodHandles.insertArguments(NEW_ARRAY, 0, nargs); } private static final MethodHandle[] FILLERS = new MethodHandle[MAX_ARITY+1]; @@ -1122,7 +1122,7 @@ public class ValueConversions { } MethodHandle leftFill = filler(leftLen); // recursive fill MethodHandle rightFill = FILL_ARRAYS[rightLen]; - rightFill = MethodHandles.insertArguments(rightFill, 1, (int) leftLen); // [leftLen..nargs-1] + rightFill = MethodHandles.insertArguments(rightFill, 1, leftLen); // [leftLen..nargs-1] // Combine the two fills: right(left(newArray(nargs), x1..x20), x21..x23) MethodHandle mh = filler(0); // identity function produces result diff --git a/jdk/src/share/classes/sun/invoke/util/Wrapper.java b/jdk/src/share/classes/sun/invoke/util/Wrapper.java index f1344bd469a..927322bf06f 100644 --- a/jdk/src/share/classes/sun/invoke/util/Wrapper.java +++ b/jdk/src/share/classes/sun/invoke/util/Wrapper.java @@ -31,7 +31,7 @@ public enum Wrapper { BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, new byte[0], Format.signed(8)), SHORT(Short.class, short.class, 'S', (Short)(short)0, new short[0], Format.signed(16)), CHAR(Character.class, char.class, 'C', (Character)(char)0, new char[0], Format.unsigned(16)), - INT(Integer.class, int.class, 'I', (Integer)(int)0, new int[0], Format.signed(32)), + INT(Integer.class, int.class, 'I', (Integer)/*(int)*/0, new int[0], Format.signed(32)), LONG(Long.class, long.class, 'J', (Long)(long)0, new long[0], Format.signed(64)), FLOAT(Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)), DOUBLE(Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)), @@ -539,7 +539,7 @@ public enum Wrapper { switch (basicTypeChar) { case 'L': throw newIllegalArgumentException("cannot wrap to object type"); case 'V': return null; - case 'I': return Integer.valueOf((int)x); + case 'I': return Integer.valueOf(x); case 'J': return Long.valueOf(x); case 'F': return Float.valueOf(x); case 'D': return Double.valueOf(x); diff --git a/jdk/test/java/lang/invoke/CallSiteTest.java b/jdk/test/java/lang/invoke/CallSiteTest.java index ee604994cc6..5e0a875e561 100644 --- a/jdk/test/java/lang/invoke/CallSiteTest.java +++ b/jdk/test/java/lang/invoke/CallSiteTest.java @@ -43,7 +43,7 @@ import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; public class CallSiteTest { - private final static Class CLASS = CallSiteTest.class; + private final static Class CLASS = CallSiteTest.class; private static CallSite mcs; private static CallSite vcs; diff --git a/jdk/test/java/lang/invoke/ClassValueTest.java b/jdk/test/java/lang/invoke/ClassValueTest.java index 121c260dfa1..c357efaf434 100644 --- a/jdk/test/java/lang/invoke/ClassValueTest.java +++ b/jdk/test/java/lang/invoke/ClassValueTest.java @@ -38,10 +38,6 @@ package test.java.lang.invoke; -import java.util.*; - -import java.lang.invoke.*; - import org.junit.*; import static org.junit.Assert.*; diff --git a/jdk/test/java/lang/invoke/InvokeGenericTest.java b/jdk/test/java/lang/invoke/InvokeGenericTest.java index 87393b4055f..b95a5d34f8a 100644 --- a/jdk/test/java/lang/invoke/InvokeGenericTest.java +++ b/jdk/test/java/lang/invoke/InvokeGenericTest.java @@ -45,6 +45,7 @@ import static org.junit.Assume.*; * * @author jrose */ +@SuppressWarnings("cast") // various casts help emphasize arguments to invokeExact public class InvokeGenericTest { // How much output? static int verbosity = 0; @@ -129,7 +130,7 @@ public class InvokeGenericTest { } } - static List calledLog = new ArrayList(); + static List calledLog = new ArrayList<>(); static Object logEntry(String name, Object... args) { return Arrays.asList(name, Arrays.asList(args)); } @@ -237,8 +238,7 @@ public class InvokeGenericTest { else try { return param.newInstance(); - } catch (InstantiationException ex) { - } catch (IllegalAccessException ex) { + } catch (InstantiationException | IllegalAccessException ex) { } return null; // random class not Object, String, Integer, etc. } @@ -274,9 +274,11 @@ public class InvokeGenericTest { return zeroArgs(params.toArray(new Class[0])); } + @SafeVarargs @SuppressWarnings("varargs") static T[] array(Class atype, E... a) { return Arrays.copyOf(a, a.length, atype); } + @SafeVarargs @SuppressWarnings("varargs") static T[] cat(T[] a, T... b) { int alen = a.length, blen = b.length; if (blen == 0) return a; @@ -311,7 +313,7 @@ public class InvokeGenericTest { int beg, int end, Class argType) { MethodType targetType = target.type(); end = Math.min(end, targetType.parameterCount()); - ArrayList> argTypes = new ArrayList>(targetType.parameterList()); + ArrayList> argTypes = new ArrayList<>(targetType.parameterList()); Collections.fill(argTypes.subList(beg, end), argType); MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); return target.asType(ttype2); @@ -320,7 +322,7 @@ public class InvokeGenericTest { // This lookup is good for all members in and under InvokeGenericTest. static final Lookup LOOKUP = MethodHandles.lookup(); - Map>, MethodHandle> CALLABLES = new HashMap>, MethodHandle>(); + Map>, MethodHandle> CALLABLES = new HashMap<>(); MethodHandle callable(List> params) { MethodHandle mh = CALLABLES.get(params); if (mh == null) { @@ -353,8 +355,8 @@ public class InvokeGenericTest { countTest(); String[] args = { "one", "two" }; MethodHandle mh = callable(Object.class, String.class); - Object res; List resl; - res = resl = (List) mh.invoke((String)args[0], (Object)args[1]); + Object res; List resl; + res = resl = (List) mh.invoke((String)args[0], (Object)args[1]); //System.out.println(res); assertEquals(Arrays.asList(args), res); } @@ -365,8 +367,8 @@ public class InvokeGenericTest { countTest(); int[] args = { 1, 2 }; MethodHandle mh = callable(Object.class, Object.class); - Object res; List resl; - res = resl = (List) mh.invoke(args[0], args[1]); + Object res; List resl; + res = resl = (List) mh.invoke(args[0], args[1]); //System.out.println(res); assertEquals(Arrays.toString(args), res.toString()); } @@ -377,8 +379,8 @@ public class InvokeGenericTest { countTest(); String[] args = { "one", "two" }; MethodHandle mh = callable(Object.class, String.class); - Object res; List resl; - res = resl = (List) mh.invoke((String)args[0], (Object)args[1]); + Object res; List resl; + res = resl = (List) mh.invoke((String)args[0], (Object)args[1]); //System.out.println(res); assertEquals(Arrays.asList(args), res); } @@ -440,9 +442,9 @@ public class InvokeGenericTest { * A void return type is possible iff the first type is void.class. */ static List allMethodTypes(int minargc, int maxargc, Class... types) { - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); if (types.length > 0) { - ArrayList argcTypes = new ArrayList(); + ArrayList argcTypes = new ArrayList<>(); // build arity-zero types first for (Class rtype : types) { argcTypes.add(MethodType.methodType(rtype)); @@ -456,7 +458,7 @@ public class InvokeGenericTest { if (argc >= maxargc) break; ArrayList prevTypes = argcTypes; - argcTypes = new ArrayList(); + argcTypes = new ArrayList<>(); for (MethodType prevType : prevTypes) { for (Class ptype : types) { argcTypes.add(prevType.insertParameterTypes(argc, ptype)); @@ -524,8 +526,8 @@ public class InvokeGenericTest { countTest(); Object[] args = { 1, 2 }; MethodHandle mh = callable(Object.class, int.class); - Object res; List resl; int resi; - res = resl = (List) mh.invoke((int)args[0], (Object)args[1]); + Object res; List resl; int resi; + res = resl = (List) mh.invoke((int)args[0], (Object)args[1]); //System.out.println(res); assertEquals(Arrays.asList(args), res); mh = MethodHandles.identity(int.class); diff --git a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java index 5206df988e9..9c10f6aa17e 100644 --- a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java +++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java @@ -54,6 +54,7 @@ import static org.junit.Assert.*; /** * @author jrose */ +@SuppressWarnings("LocalVariableHidesMemberVariable") public class JavaDocExamplesTest { /** Wrapper for running the JUnit tests in this module. * Put JUnit on the classpath! @@ -336,6 +337,7 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); }} } + @SuppressWarnings("rawtypes") @Test public void testAsVarargsCollector() throws Throwable { {{ {} /// JAVADOC diff --git a/jdk/test/java/lang/invoke/MethodHandlesTest.java b/jdk/test/java/lang/invoke/MethodHandlesTest.java index bea81b6ddac..7f04ee07550 100644 --- a/jdk/test/java/lang/invoke/MethodHandlesTest.java +++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java @@ -176,7 +176,7 @@ public class MethodHandlesTest { } } - static List calledLog = new ArrayList(); + static List calledLog = new ArrayList<>(); static Object logEntry(String name, Object... args) { return Arrays.asList(name, Arrays.asList(args)); } @@ -211,6 +211,7 @@ public class MethodHandlesTest { return dst.cast(value); } + @SuppressWarnings("cast") // primitive cast to (long) is part of the pattern static Object castToWrapperOrNull(long value, Class dst) { if (dst == int.class || dst == Integer.class) return (int)(value); @@ -284,8 +285,7 @@ public class MethodHandlesTest { else try { return param.newInstance(); - } catch (InstantiationException ex) { - } catch (IllegalAccessException ex) { + } catch (InstantiationException | IllegalAccessException ex) { } return null; // random class not Object, String, Integer, etc. } @@ -302,9 +302,11 @@ public class MethodHandlesTest { return args; } + @SafeVarargs @SuppressWarnings("varargs") static T[] array(Class atype, E... a) { return Arrays.copyOf(a, a.length, atype); } + @SafeVarargs @SuppressWarnings("varargs") static T[] cat(T[] a, T... b) { int alen = a.length, blen = b.length; if (blen == 0) return a; @@ -354,14 +356,14 @@ public class MethodHandlesTest { try { LIST_TO_STRING = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToString", MethodType.methodType(String.class, List.class)); - } catch (Exception ex) { throw new RuntimeException(ex); } + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } list = MethodHandles.filterReturnValue(list, LIST_TO_STRING); } else if (rtype.isPrimitive()) { if (LIST_TO_INT == null) try { LIST_TO_INT = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToInt", MethodType.methodType(int.class, List.class)); - } catch (Exception ex) { throw new RuntimeException(ex); } + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } list = MethodHandles.filterReturnValue(list, LIST_TO_INT); list = MethodHandles.explicitCastArguments(list, listType); } else { @@ -370,8 +372,8 @@ public class MethodHandlesTest { return list.asType(listType); } private static MethodHandle LIST_TO_STRING, LIST_TO_INT; - private static String listToString(List x) { return x.toString(); } - private static int listToInt(List x) { return x.toString().hashCode(); } + private static String listToString(List x) { return x.toString(); } + private static int listToInt(List x) { return x.toString().hashCode(); } static MethodHandle changeArgTypes(MethodHandle target, Class argType) { return changeArgTypes(target, 0, 999, argType); @@ -380,7 +382,7 @@ public class MethodHandlesTest { int beg, int end, Class argType) { MethodType targetType = target.type(); end = Math.min(end, targetType.parameterCount()); - ArrayList> argTypes = new ArrayList>(targetType.parameterList()); + ArrayList> argTypes = new ArrayList<>(targetType.parameterList()); Collections.fill(argTypes.subList(beg, end), argType); MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); return target.asType(ttype2); @@ -405,6 +407,7 @@ public class MethodHandlesTest { final String name; public Example() { name = "Example#"+nextArg(); } protected Example(String name) { this.name = name; } + @SuppressWarnings("LeakingThisInConstructor") protected Example(int x) { this(); called("protected ", this, x); } @Override public String toString() { return name; } @@ -441,6 +444,7 @@ public class MethodHandlesTest { static class SubExample extends Example { @Override public void v0() { called("Sub/v0", this); } @Override void pkg_v0() { called("Sub/pkg_v0", this); } + @SuppressWarnings("LeakingThisInConstructor") private SubExample(int x) { called("", this, x); } public SubExample() { super("SubExample#"+nextArg()); } } @@ -912,7 +916,7 @@ public class MethodHandlesTest { static final Object[][] CASES; static { - ArrayList cases = new ArrayList(); + ArrayList cases = new ArrayList<>(); Object types[][] = { {'L',Object.class}, {'R',String.class}, {'I',int.class}, {'J',long.class}, @@ -931,12 +935,12 @@ public class MethodHandlesTest { Field field; try { field = HasFields.class.getDeclaredField(name); - } catch (Exception ex) { + } catch (NoSuchFieldException | SecurityException ex) { throw new InternalError("no field HasFields."+name); } try { value = field.get(fields); - } catch (Exception ex) { + } catch (IllegalArgumentException | IllegalAccessException ex) { throw new InternalError("cannot fetch field HasFields."+name); } if (type == float.class) { @@ -1257,7 +1261,7 @@ public class MethodHandlesTest { List array2list(Object array) { int length = Array.getLength(array); - ArrayList model = new ArrayList(length); + ArrayList model = new ArrayList<>(length); for (int i = 0; i < length; i++) model.add(Array.get(array, i)); return model; @@ -1288,7 +1292,7 @@ public class MethodHandlesTest { String name = pfx+"id"; try { return PRIVATE.findStatic(Callee.class, name, type); - } catch (Exception ex) { + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } } @@ -1365,7 +1369,7 @@ public class MethodHandlesTest { MethodHandle vac = vac0.asVarargsCollector(Object[].class); testConvert(true, vac.asType(MethodType.genericMethodType(0)), null, "vac"); testConvert(true, vac.asType(MethodType.genericMethodType(0)), null, "vac"); - for (Class at : new Class[] { Object.class, String.class, Integer.class }) { + for (Class at : new Class[] { Object.class, String.class, Integer.class }) { testConvert(true, vac.asType(MethodType.genericMethodType(1)), null, "vac", at); testConvert(true, vac.asType(MethodType.genericMethodType(2)), null, "vac", at, at); } @@ -1514,7 +1518,7 @@ public class MethodHandlesTest { public void testSpreadArguments() throws Throwable { if (CAN_SKIP_WORKING) return; startTest("spreadArguments"); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { if (verbosity >= 3) System.out.println("spreadArguments "+argType); for (int nargs = 0; nargs < 50; nargs++) { @@ -1538,7 +1542,7 @@ public class MethodHandlesTest { Object[] args = randomArgs(target2.type().parameterArray()); // make sure the target does what we think it does: if (pos == 0 && nargs < 5 && !argType.isPrimitive()) { - Object[] check = (Object[]) (Object) target.invokeWithArguments(args); + Object[] check = (Object[]) target.invokeWithArguments(args); assertArrayEquals(args, check); switch (nargs) { case 0: @@ -1555,7 +1559,7 @@ public class MethodHandlesTest { break; } } - List> newParams = new ArrayList>(target2.type().parameterList()); + List> newParams = new ArrayList<>(target2.type().parameterList()); { // modify newParams in place List> spreadParams = newParams.subList(pos, nargs); spreadParams.clear(); spreadParams.add(arrayType); @@ -1608,7 +1612,7 @@ public class MethodHandlesTest { public void testCollectArguments() throws Throwable { if (CAN_SKIP_WORKING) return; startTest("collectArguments"); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { if (verbosity >= 3) System.out.println("collectArguments "+argType); for (int nargs = 0; nargs < 50; nargs++) { @@ -1670,12 +1674,13 @@ public class MethodHandlesTest { MethodHandle target = varargsArray(nargs + ins); Object[] args = randomArgs(target.type().parameterArray()); List resList = Arrays.asList(args); - List argsToPass = new ArrayList(resList); + List argsToPass = new ArrayList<>(resList); List argsToInsert = argsToPass.subList(pos, pos + ins); if (verbosity >= 3) System.out.println("insert: "+argsToInsert+" into "+target); + @SuppressWarnings("cast") // cast to spread Object... is helpful MethodHandle target2 = MethodHandles.insertArguments(target, pos, - (Object[]) argsToInsert.toArray()); + (Object[]/*...*/) argsToInsert.toArray()); argsToInsert.clear(); // remove from argsToInsert Object res2 = target2.invokeWithArguments(argsToPass); Object res2List = Arrays.asList((Object[])res2); @@ -1693,7 +1698,7 @@ public class MethodHandlesTest { Class classOfVCList = varargsList(1).invokeWithArguments(0).getClass(); assertTrue(List.class.isAssignableFrom(classOfVCList)); for (int nargs = 0; nargs <= 3; nargs++) { - for (Class rtype : new Class[] { Object.class, + for (Class rtype : new Class[] { Object.class, List.class, int.class, byte.class, @@ -1790,7 +1795,7 @@ public class MethodHandlesTest { System.out.println("fold "+target+" with "+combine); MethodHandle target2 = MethodHandles.foldArguments(target, combine); // Simulate expected effect of combiner on arglist: - List expected = new ArrayList(argsToPass); + List expected = new ArrayList<>(argsToPass); List argsToFold = expected.subList(pos, pos + fold); if (verbosity >= 3) System.out.println("fold: "+argsToFold+" into "+target2); @@ -1822,9 +1827,9 @@ public class MethodHandlesTest { MethodHandle target = varargsArray(nargs); Object[] args = randomArgs(target.type().parameterArray()); MethodHandle target2 = MethodHandles.dropArguments(target, pos, - Collections.nCopies(drop, Object.class).toArray(new Class[0])); + Collections.nCopies(drop, Object.class).toArray(new Class[0])); List resList = Arrays.asList(args); - List argsToDrop = new ArrayList(resList); + List argsToDrop = new ArrayList<>(resList); for (int i = drop; i > 0; i--) { argsToDrop.add(pos, "blort#"+i); } @@ -1840,11 +1845,11 @@ public class MethodHandlesTest { if (CAN_SKIP_WORKING) return; startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker"); // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker - Set done = new HashSet(); + Set done = new HashSet<>(); for (int i = 0; i <= 6; i++) { if (CAN_TEST_LIGHTLY && i > 3) break; MethodType gtype = MethodType.genericMethodType(i); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { for (int j = -1; j < i; j++) { MethodType type = gtype; if (j < 0) @@ -1873,7 +1878,7 @@ public class MethodHandlesTest { assertTrue(target.isVarargsCollector()); target = target.asType(type); Object[] args = randomArgs(type.parameterArray()); - List targetPlusArgs = new ArrayList(Arrays.asList(args)); + List targetPlusArgs = new ArrayList<>(Arrays.asList(args)); targetPlusArgs.add(0, target); int code = (Integer) invokee(args); Object log = logEntry("invokee", args); @@ -1960,7 +1965,7 @@ public class MethodHandlesTest { .appendParameterTypes(Object[].class) .insertParameterTypes(0, MethodHandle.class)); assertEquals(expType, inv.type()); - List targetPlusVarArgs = new ArrayList(targetPlusArgs); + List targetPlusVarArgs = new ArrayList<>(targetPlusArgs); List tailList = targetPlusVarArgs.subList(1+k, 1+nargs); Object[] tail = tailList.toArray(); tailList.clear(); tailList.add(tail); @@ -2191,7 +2196,7 @@ public class MethodHandlesTest { if (throwMode == THROW_NOTHING) { assertSame(arg0, returned); } else if (throwMode == THROW_CAUGHT) { - List catchArgs = new ArrayList(Arrays.asList(args)); + List catchArgs = new ArrayList<>(Arrays.asList(args)); // catcher receives an initial subsequence of target arguments: catchArgs.subList(nargs - catchDrops, nargs).clear(); // catcher also receives the exception, prepended: @@ -2317,12 +2322,13 @@ public class MethodHandlesTest { INT_IDENTITY = PRIVATE.findStatic( Surprise.class, "intIdentity", MethodType.methodType(int.class, int.class)); - } catch (Exception ex) { + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } } } + @SuppressWarnings("ConvertToStringSwitch") void testCastFailure(String mode, int okCount) throws Throwable { countTest(false); if (verbosity > 2) System.out.println("mode="+mode); @@ -2418,13 +2424,14 @@ public class MethodHandlesTest { } public interface Fooable { // overloads: - Object foo(Object x, String y); - List foo(String x, int y); - Object foo(String x); + Object foo(Object x, String y); + List foo(String x, int y); + Object foo(String x); } static Object fooForFooable(String x, Object... y) { return called("fooForFooable/"+x, y); } + @SuppressWarnings("serial") // not really a public API, just a test case public static class MyCheckedException extends Exception { } public interface WillThrow { @@ -2453,7 +2460,7 @@ public class MethodHandlesTest { { countTest(); if (verbosity >= 2) System.out.println("Appendable"); - ArrayList appendResults = new ArrayList(); + ArrayList> appendResults = new ArrayList<>(); MethodHandle append = lookup.bind(appendResults, "add", MethodType.methodType(boolean.class, Object.class)); append = append.asType(MethodType.methodType(void.class, List.class)); // specialize the type MethodHandle asList = lookup.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class)); @@ -2475,11 +2482,11 @@ public class MethodHandlesTest { formatter.format(fmt, fmtArgs); String actual = ""; if (verbosity >= 3) System.out.println("appendResults="+appendResults); - for (List l : appendResults) { + for (List l : appendResults) { Object x = l.get(0); switch (l.size()) { case 1: actual += x; continue; - case 3: actual += ((String)x).substring((int)l.get(1), (int)l.get(2)); continue; + case 3: actual += ((String)x).substring((int)(Object)l.get(1), (int)(Object)l.get(2)); continue; } actual += l; } @@ -2551,7 +2558,7 @@ public class MethodHandlesTest { } } // Test error checking on bad interfaces: - for (Class nonSMI : new Class[] { Object.class, + for (Class nonSMI : new Class[] { Object.class, String.class, CharSequence.class, java.io.Serializable.class, @@ -2579,7 +2586,7 @@ public class MethodHandlesTest { } } // Test error checking on interfaces with the wrong method type: - for (Class intfc : new Class[] { Runnable.class /*arity 0*/, + for (Class intfc : new Class[] { Runnable.class /*arity 0*/, Fooable.class /*arity 1 & 2*/ }) { int badArity = 1; // known to be incompatible if (verbosity > 2) System.out.println(intfc.getName()); @@ -2657,7 +2664,7 @@ class ValueConversions { Object a8, Object a9) { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } static MethodHandle[] makeArrays() { - ArrayList arrays = new ArrayList(); + ArrayList arrays = new ArrayList<>(); MethodHandles.Lookup lookup = IMPL_LOOKUP; for (;;) { int nargs = arrays.size(); @@ -2746,7 +2753,7 @@ class ValueConversions { Object a8, Object a9) { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } static MethodHandle[] makeLists() { - ArrayList lists = new ArrayList(); + ArrayList lists = new ArrayList<>(); MethodHandles.Lookup lookup = IMPL_LOOKUP; for (;;) { int nargs = lists.size(); @@ -2769,7 +2776,7 @@ class ValueConversions { static { try { AS_LIST = IMPL_LOOKUP.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class)); - } catch (Exception ex) { throw new RuntimeException(ex); } + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } } /** Return a method handle that takes the indicated number of Object diff --git a/jdk/test/java/lang/invoke/MethodTypeTest.java b/jdk/test/java/lang/invoke/MethodTypeTest.java index aa540b0c89c..d8d460fd191 100644 --- a/jdk/test/java/lang/invoke/MethodTypeTest.java +++ b/jdk/test/java/lang/invoke/MethodTypeTest.java @@ -29,6 +29,7 @@ package test.java.lang.invoke; +import java.io.IOException; import java.lang.invoke.MethodType; import java.lang.reflect.Method; @@ -378,7 +379,7 @@ public class MethodTypeTest { public void testHashCode() { System.out.println("hashCode"); MethodType instance = mt_viS; - ArrayList> types = new ArrayList>(); + ArrayList> types = new ArrayList<>(); types.add(instance.returnType()); types.addAll(instance.parameterList()); int expResult = types.hashCode(); @@ -556,7 +557,7 @@ public class MethodTypeTest { Object decode; try { decode = readSerial(wire); - } catch (Exception ex) { + } catch (IOException | ClassNotFoundException ex) { decode = ex; // oops! } assertEquals(mt, decode); diff --git a/jdk/test/java/lang/invoke/PermuteArgsTest.java b/jdk/test/java/lang/invoke/PermuteArgsTest.java index e02137e2560..07cbbe59ec9 100644 --- a/jdk/test/java/lang/invoke/PermuteArgsTest.java +++ b/jdk/test/java/lang/invoke/PermuteArgsTest.java @@ -45,7 +45,7 @@ import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; public class PermuteArgsTest { - private static final Class CLASS = PermuteArgsTest.class; + private static final Class CLASS = PermuteArgsTest.class; private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 8); private static final boolean DRY_RUN = Boolean.getBoolean(CLASS.getSimpleName()+".DRY_RUN"); private static final boolean VERBOSE = Boolean.getBoolean(CLASS.getSimpleName()+".VERBOSE") || DRY_RUN; @@ -99,12 +99,12 @@ public class PermuteArgsTest { return Arrays.asList(w, x, y, z); } static Object listI_etc(int... va) { - ArrayList res = new ArrayList(); + ArrayList res = new ArrayList<>(); for (int x : va) res.add(x); return res; } static Object listIJL_etc(int x, long y, Object z, Object... va) { - ArrayList res = new ArrayList(); + ArrayList res = new ArrayList<>(); res.addAll(Arrays.asList(x, y, z)); res.addAll(Arrays.asList(va)); return res; @@ -168,7 +168,7 @@ public class PermuteArgsTest { mh1 = adjustArity(mh, arity); } catch (IllegalArgumentException ex) { System.out.println("*** mh = "+name+" : "+mh+"; arity = "+arity+" => "+ex); - ex.printStackTrace(); + ex.printStackTrace(System.out); break; // cannot get this arity for this type } test("("+arity+")"+name, mh1); @@ -213,7 +213,7 @@ public class PermuteArgsTest { } static void testPermutations(MethodHandle mh) throws Throwable { - HashSet done = new HashSet(); + HashSet done = new HashSet<>(); MethodType mt = mh.type(); int[] perm = nullPerm(mt.parameterCount()); final int MARGIN = (perm.length <= 10 ? 2 : 0); @@ -326,8 +326,8 @@ public class PermuteArgsTest { Class pt = ptypes[i]; Object arg; if (pt == Void.class) arg = null; - else if (pt == int.class) arg = (int) i + 101; - else if (pt == long.class) arg = (long) i + 10_000_000_001L; + else if (pt == int.class) arg = i + 101; + else if (pt == long.class) arg = i + 10_000_000_001L; else arg = "#" + (i + 1); args[i] = arg; } diff --git a/jdk/test/java/lang/invoke/RicochetTest.java b/jdk/test/java/lang/invoke/RicochetTest.java index bc59ae345c0..d260375ec61 100644 --- a/jdk/test/java/lang/invoke/RicochetTest.java +++ b/jdk/test/java/lang/invoke/RicochetTest.java @@ -40,7 +40,6 @@ import org.junit.*; import static java.lang.invoke.MethodType.*; import static java.lang.invoke.MethodHandles.*; import static org.junit.Assert.*; -import static org.junit.Assume.*; /** @@ -48,7 +47,7 @@ import static org.junit.Assume.*; * @author jrose */ public class RicochetTest { - private static final Class CLASS = RicochetTest.class; + private static final Class CLASS = RicochetTest.class; private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40); public static void main(String... av) throws Throwable { @@ -148,7 +147,7 @@ public class RicochetTest { for (int nargs = 0; nargs <= MAX; nargs++) { if (nargs > 30 && nargs < MAX-20) nargs += 10; int[] args = new int[nargs]; - for (int j = 0; j < args.length; j++) args[j] = (int)(j + 11); + for (int j = 0; j < args.length; j++) args[j] = j + 11; //System.out.println("testIntSpreads "+Arrays.toString(args)); int[] args1 = (int[]) id.invokeExact(args); assertArrayEquals(args, args1); @@ -388,6 +387,7 @@ public class RicochetTest { java.util.Random random; final MethodHandle[] fns; int depth; + @SuppressWarnings("LeakingThisInConstructor") RFCB(int seed) throws Throwable { this.random = new java.util.Random(seed); this.fns = new MethodHandle[Math.max(29, (1 << MAX_DEPTH-2)/3)]; @@ -408,7 +408,7 @@ public class RicochetTest { case 1: Throwable ex = new RuntimeException(); ex.fillInStackTrace(); - if (VERBOSITY >= 2) ex.printStackTrace(); + if (VERBOSITY >= 2) ex.printStackTrace(System.out); x = "ST; " + x; break; case 2: @@ -467,7 +467,7 @@ public class RicochetTest { return mh.invokeWithArguments(args); } catch (Throwable ex) { System.out.println("threw: "+mh+Arrays.asList(args)); - ex.printStackTrace(); + ex.printStackTrace(System.out); return ex; } } @@ -515,8 +515,8 @@ public class RicochetTest { private static long opJ(long x) { return (long) opI((int)x); } private static Object opL2(Object x, Object y) { return (Object) opI2((int)x, (int)y); } private static Object opL(Object x) { return (Object) opI((int)x); } - private static int opL2_I(Object x, Object y) { return (int) opI2((int)x, (int)y); } - private static int opL_I(Object x) { return (int) opI((int)x); } + private static int opL2_I(Object x, Object y) { return opI2((int)x, (int)y); } + private static int opL_I(Object x) { return opI((int)x); } private static long opL_J(Object x) { return (long) opI((int)x); } private static final MethodHandle opI, opI2, opI3, opI4, opI_L, opJ, opJ2, opJ3, opL2, opL, opL2_I, opL_I, opL_J; static { @@ -570,8 +570,8 @@ public class RicochetTest { INT_LISTERS[i] = lister; LONG_LISTERS[i] = llister; if (i == 0) break; - lister = insertArguments(lister, i-1, (int)0); - llister = insertArguments(llister, i-1, (long)0); + lister = insertArguments(lister, i-1, 0); + llister = insertArguments(llister, i-1, 0L); } } diff --git a/jdk/test/java/lang/invoke/ThrowExceptionsTest.java b/jdk/test/java/lang/invoke/ThrowExceptionsTest.java index 0065e92d47c..772901542c5 100644 --- a/jdk/test/java/lang/invoke/ThrowExceptionsTest.java +++ b/jdk/test/java/lang/invoke/ThrowExceptionsTest.java @@ -40,7 +40,7 @@ import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; public class ThrowExceptionsTest { - private static final Class CLASS = ThrowExceptionsTest.class; + private static final Class CLASS = ThrowExceptionsTest.class; private static final Lookup LOOKUP = lookup(); public static void main(String argv[]) throws Throwable { @@ -132,9 +132,9 @@ public class ThrowExceptionsTest { int tc = testCases; try { m.invoke(this); - } catch (Throwable ex) { + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { System.out.println("*** "+ex); - ex.printStackTrace(); + ex.printStackTrace(System.out); } if (testCases == tc) testCases++; } diff --git a/jdk/test/sun/invoke/util/ValueConversionsTest.java b/jdk/test/sun/invoke/util/ValueConversionsTest.java index 6b1253e77b2..57205f89805 100644 --- a/jdk/test/sun/invoke/util/ValueConversionsTest.java +++ b/jdk/test/sun/invoke/util/ValueConversionsTest.java @@ -27,11 +27,9 @@ import sun.invoke.util.ValueConversions; import sun.invoke.util.Wrapper; import java.lang.invoke.MethodType; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; import java.io.Serializable; import java.util.Arrays; import java.util.Collections; -import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.*; @@ -52,7 +50,7 @@ import static org.junit.Assert.*; * @author jrose */ public class ValueConversionsTest { - private static final Class CLASS = ValueConversionsTest.class; + private static final Class CLASS = ValueConversionsTest.class; private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40); private static final int START_ARITY = Integer.getInteger(CLASS.getSimpleName()+".START_ARITY", 0); private static final boolean EXHAUSTIVE = Boolean.getBoolean(CLASS.getSimpleName()+".EXHAUSTIVE"); @@ -165,7 +163,7 @@ public class ValueConversionsTest { Object expResult = box; Object result = null; switch (w) { - case INT: result = boxer.invokeExact((int)n); break; + case INT: result = boxer.invokeExact(/*int*/n); break; case LONG: result = boxer.invokeExact((long)n); break; case FLOAT: result = boxer.invokeExact((float)n); break; case DOUBLE: result = boxer.invokeExact((double)n); break; @@ -361,6 +359,7 @@ public class ValueConversionsTest { assert(stype == MethodType.methodType(arrayType, arrayType)); if (nargs <= 5) { // invoke target as a spreader also: + @SuppressWarnings("cast") Object res2 = spreader.invokeWithArguments((Object)res); String res2String = toArrayString(res2); assertEquals(Arrays.toString(args), res2String); From 1c49ad8a033a88f9da13b51d112e31ece467ce08 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Wed, 18 Jan 2012 17:34:30 -0800 Subject: [PATCH 52/96] 7077803: java.lang.InternalError in java.lang.invoke.MethodHandleNatives.init Use correct access token for unreflecting MHs where setAccessible(true) Reviewed-by: never, twisti --- .../java/lang/invoke/MethodHandles.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java index 700f433bc86..58b7e6d507f 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java @@ -948,10 +948,11 @@ return mh1; public MethodHandle unreflect(Method m) throws IllegalAccessException { MemberName method = new MemberName(m); assert(method.isMethod()); - if (!m.isAccessible()) checkMethod(method.getDeclaringClass(), method, method.isStatic()); + if (m.isAccessible()) + return MethodHandleImpl.findMethod(method, true, /*no lookupClass*/ null); + checkMethod(method.getDeclaringClass(), method, method.isStatic()); MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull()); - if (!m.isAccessible()) mh = restrictProtectedReceiver(method, mh); - return mh; + return restrictProtectedReceiver(method, mh); } /** @@ -1010,8 +1011,13 @@ return mh1; public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException { MemberName ctor = new MemberName(c); assert(ctor.isConstructor()); - if (!c.isAccessible()) checkAccess(c.getDeclaringClass(), ctor); - MethodHandle rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull()); + MethodHandle rawCtor; + if (c.isAccessible()) { + rawCtor = MethodHandleImpl.findMethod(ctor, false, /*no lookupClass*/ null); + } else { + checkAccess(c.getDeclaringClass(), ctor); + rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull()); + } MethodHandle allocator = MethodHandleImpl.makeAllocator(rawCtor); return fixVarargs(allocator, rawCtor); } @@ -1226,7 +1232,7 @@ return mh1; ? "expected a static field" : "expected a non-static field", this); if (trusted) - return MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull()); + return MethodHandleImpl.accessField(field, isSetter, /*no lookupClass*/ null); checkAccess(refc, field); MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull()); return restrictProtectedReceiver(field, mh); From cec41c4c9d984e34926f41ef270de32cd2b8de67 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Wed, 18 Jan 2012 17:34:32 -0800 Subject: [PATCH 53/96] 7030453: JSR 292 ClassValue.get method is too slow Implement ClassValue cooperatively with Class like ThreadLocal with Thread. Reviewed-by: twisti, mduigou --- jdk/src/share/classes/java/lang/Class.java | 5 + .../share/classes/java/lang/ClassValue.java | 648 ++++++++++++++++-- jdk/test/java/lang/invoke/ClassValueTest.java | 18 +- 3 files changed, 595 insertions(+), 76 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index f762d16707e..b636f5ade15 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -3118,4 +3118,9 @@ public final AnnotationType getAnnotationType() { return annotationType; } + + /* Backing store of user-defined values pertaining to this class. + * Maintained by the ClassValue class. + */ + transient ClassValue.ClassValueMap classValueMap; } diff --git a/jdk/src/share/classes/java/lang/ClassValue.java b/jdk/src/share/classes/java/lang/ClassValue.java index 02cf34f59da..6a824bcc459 100644 --- a/jdk/src/share/classes/java/lang/ClassValue.java +++ b/jdk/src/share/classes/java/lang/ClassValue.java @@ -25,9 +25,14 @@ package java.lang; +import java.lang.ClassValue.ClassValueMap; import java.util.WeakHashMap; +import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicInteger; +import static java.lang.ClassValue.ClassValueMap.probeHomeLocation; +import static java.lang.ClassValue.ClassValueMap.probeBackupLocations; + /** * Lazily associate a computed value with (potentially) every type. * For example, if a dynamic language needs to construct a message dispatch @@ -92,14 +97,22 @@ public abstract class ClassValue { * @see #computeValue */ public T get(Class type) { - ClassValueMap map = getMap(type); - if (map != null) { - Object x = map.get(this); - if (x != null) { - return (T) map.unmaskNull(x); - } - } - return setComputedValue(type); + // non-racing this.hashCodeForCache : final int + Entry[] cache; + Entry e = probeHomeLocation(cache = getCacheCarefully(type), this); + // racing e : current value <=> stale value from current cache or from stale cache + // invariant: e is null or an Entry with readable Entry.version and Entry.value + if (match(e)) + // invariant: No false positive matches. False negatives are OK if rare. + // The key fact that makes this work: if this.version == e.version, + // then this thread has a right to observe (final) e.value. + return e.value(); + // The fast path can fail for any of these reasons: + // 1. no entry has been computed yet + // 2. hash code collision (before or after reduction mod cache.length) + // 3. an entry has been removed (either on this type or another) + // 4. the GC has somehow managed to delete e.version and clear the reference + return getFromBackup(cache, type); } /** @@ -157,83 +170,582 @@ public abstract class ClassValue { */ public void remove(Class type) { ClassValueMap map = getMap(type); - if (map != null) { - synchronized (map) { - map.remove(this); - } - } + map.removeEntry(this); } - /// Implementation... - // FIXME: Use a data structure here similar that of ThreadLocal (7030453). - - private static final AtomicInteger STORE_BARRIER = new AtomicInteger(); - - /** Slow path for {@link #get}. */ - private T setComputedValue(Class type) { + // Possible functionality for JSR 292 MR 1 + /*public*/ void put(Class type, T value) { ClassValueMap map = getMap(type); - if (map == null) { - map = initializeMap(type); - } - T value = computeValue(type); - STORE_BARRIER.lazySet(0); - // All stores pending from computeValue are completed. - synchronized (map) { - // Warm up the table with a null entry. - map.preInitializeEntry(this); - } - STORE_BARRIER.lazySet(0); - // All stores pending from table expansion are completed. - synchronized (map) { - value = (T) map.initializeEntry(this, value); - // One might fear a possible race condition here - // if the code for map.put has flushed the write - // to map.table[*] before the writes to the Map.Entry - // are done. This is not possible, since we have - // warmed up the table with an empty entry. - } - return value; + map.changeEntry(this, value); } - // Replace this map by a per-class slot. - private static final WeakHashMap, ClassValueMap> ROOT - = new WeakHashMap, ClassValueMap>(); + /// -------- + /// Implementation... + /// -------- + /** Return the cache, if it exists, else a dummy empty cache. */ + private static Entry[] getCacheCarefully(Class type) { + // racing type.classValueMap{.cacheArray} : null => new Entry[X] <=> new Entry[Y] + ClassValueMap map = type.classValueMap; + if (map == null) return EMPTY_CACHE; + Entry[] cache = map.getCache(); + return cache; + // invariant: returned value is safe to dereference and check for an Entry + } + + /** Initial, one-element, empty cache used by all Class instances. Must never be filled. */ + private static final Entry[] EMPTY_CACHE = { null }; + + /** + * Slow tail of ClassValue.get to retry at nearby locations in the cache, + * or take a slow lock and check the hash table. + * Called only if the first probe was empty or a collision. + * This is a separate method, so compilers can process it independently. + */ + private T getFromBackup(Entry[] cache, Class type) { + Entry e = probeBackupLocations(cache, this); + if (e != null) + return e.value(); + return getFromHashMap(type); + } + + // Hack to suppress warnings on the (T) cast, which is a no-op. + @SuppressWarnings("unchecked") + Entry castEntry(Entry e) { return (Entry) e; } + + /** Called when the fast path of get fails, and cache reprobe also fails. + */ + private T getFromHashMap(Class type) { + // The fail-safe recovery is to fall back to the underlying classValueMap. + ClassValueMap map = getMap(type); + for (;;) { + Entry e = map.startEntry(this); + if (!e.isPromise()) + return e.value(); + try { + // Try to make a real entry for the promised version. + e = makeEntry(e.version(), computeValue(type)); + } finally { + // Whether computeValue throws or returns normally, + // be sure to remove the empty entry. + e = map.finishEntry(this, e); + } + if (e != null) + return e.value(); + // else try again, in case a racing thread called remove (so e == null) + } + } + + /** Check that e is non-null, matches this ClassValue, and is live. */ + boolean match(Entry e) { + // racing e.version : null (blank) => unique Version token => null (GC-ed version) + // non-racing this.version : v1 => v2 => ... (updates are read faithfully from volatile) + return (e != null && e.get() == this.version); + // invariant: No false positives on version match. Null is OK for false negative. + // invariant: If version matches, then e.value is readable (final set in Entry.) + } + + /** Internal hash code for accessing Class.classValueMap.cacheArray. */ + final int hashCodeForCache = nextHashCode.getAndAdd(HASH_INCREMENT) & HASH_MASK; + + /** Value stream for hashCodeForCache. See similar structure in ThreadLocal. */ + private static final AtomicInteger nextHashCode = new AtomicInteger(); + + /** Good for power-of-two tables. See similar structure in ThreadLocal. */ + private static final int HASH_INCREMENT = 0x61c88647; + + /** Mask a hash code to be positive but not too large, to prevent wraparound. */ + static final int HASH_MASK = (-1 >>> 2); + + /** + * Private key for retrieval of this object from ClassValueMap. + */ + static class Identity { + } + /** + * This ClassValue's identity, expressed as an opaque object. + * The main object {@code ClassValue.this} is incorrect since + * subclasses may override {@code ClassValue.equals}, which + * could confuse keys in the ClassValueMap. + */ + final Identity identity = new Identity(); + + /** + * Current version for retrieving this class value from the cache. + * Any number of computeValue calls can be cached in association with one version. + * But the version changes when a remove (on any type) is executed. + * A version change invalidates all cache entries for the affected ClassValue, + * by marking them as stale. Stale cache entries do not force another call + * to computeValue, but they do require a synchronized visit to a backing map. + *

    + * All user-visible state changes on the ClassValue take place under + * a lock inside the synchronized methods of ClassValueMap. + * Readers (of ClassValue.get) are notified of such state changes + * when this.version is bumped to a new token. + * This variable must be volatile so that an unsynchronized reader + * will receive the notification without delay. + *

    + * If version were not volatile, one thread T1 could persistently hold onto + * a stale value this.value == V1, while while another thread T2 advances + * (under a lock) to this.value == V2. This will typically be harmless, + * but if T1 and T2 interact causally via some other channel, such that + * T1's further actions are constrained (in the JMM) to happen after + * the V2 event, then T1's observation of V1 will be an error. + *

    + * The practical effect of making this.version be volatile is that it cannot + * be hoisted out of a loop (by an optimizing JIT) or otherwise cached. + * Some machines may also require a barrier instruction to execute + * before this.version. + */ + private volatile Version version = new Version<>(this); + Version version() { return version; } + void bumpVersion() { version = new Version<>(this); } + static class Version { + private final ClassValue classValue; + private final Entry promise = new Entry<>(this); + Version(ClassValue classValue) { this.classValue = classValue; } + ClassValue classValue() { return classValue; } + Entry promise() { return promise; } + boolean isLive() { return classValue.version() == this; } + } + + /** One binding of a value to a class via a ClassValue. + * States are:

      + *
    • promise if value == Entry.this + *
    • else dead if version == null + *
    • else stale if version != classValue.version + *
    • else live
    + * Promises are never put into the cache; they only live in the + * backing map while a computeValue call is in flight. + * Once an entry goes stale, it can be reset at any time + * into the dead state. + */ + static class Entry extends WeakReference> { + final Object value; // usually of type T, but sometimes (Entry)this + Entry(Version version, T value) { + super(version); + this.value = value; // for a regular entry, value is of type T + } + private void assertNotPromise() { assert(!isPromise()); } + /** For creating a promise. */ + Entry(Version version) { + super(version); + this.value = this; // for a promise, value is not of type T, but Entry! + } + /** Fetch the value. This entry must not be a promise. */ + @SuppressWarnings("unchecked") // if !isPromise, type is T + T value() { assertNotPromise(); return (T) value; } + boolean isPromise() { return value == this; } + Version version() { return get(); } + ClassValue classValueOrNull() { + Version v = version(); + return (v == null) ? null : v.classValue(); + } + boolean isLive() { + Version v = version(); + if (v == null) return false; + if (v.isLive()) return true; + clear(); + return false; + } + Entry refreshVersion(Version v2) { + assertNotPromise(); + @SuppressWarnings("unchecked") // if !isPromise, type is T + Entry e2 = new Entry<>(v2, (T) value); + clear(); + // value = null -- caller must drop + return e2; + } + static final Entry DEAD_ENTRY = new Entry<>(null, null); + } + + /** Return the backing map associated with this type. */ private static ClassValueMap getMap(Class type) { - type.getClass(); // test for null - return ROOT.get(type); + // racing type.classValueMap : null (blank) => unique ClassValueMap + // if a null is observed, a map is created (lazily, synchronously, uniquely) + // all further access to that map is synchronized + ClassValueMap map = type.classValueMap; + if (map != null) return map; + return initializeMap(type); } + private static final Object CRITICAL_SECTION = new Object(); private static ClassValueMap initializeMap(Class type) { - synchronized (ClassValue.class) { - ClassValueMap map = ROOT.get(type); - if (map == null) - ROOT.put(type, map = new ClassValueMap()); + ClassValueMap map; + synchronized (CRITICAL_SECTION) { // private object to avoid deadlocks + // happens about once per type + if ((map = type.classValueMap) == null) + type.classValueMap = map = new ClassValueMap(type); + } return map; } + + static Entry makeEntry(Version explicitVersion, T value) { + // Note that explicitVersion might be different from this.version. + return new Entry<>(explicitVersion, value); + + // As soon as the Entry is put into the cache, the value will be + // reachable via a data race (as defined by the Java Memory Model). + // This race is benign, assuming the value object itself can be + // read safely by multiple threads. This is up to the user. + // + // The entry and version fields themselves can be safely read via + // a race because they are either final or have controlled states. + // If the pointer from the entry to the version is still null, + // or if the version goes immediately dead and is nulled out, + // the reader will take the slow path and retry under a lock. } - static class ClassValueMap extends WeakHashMap { - /** Make sure this table contains an Entry for the given key, even if it is empty. */ - void preInitializeEntry(ClassValue key) { - if (!this.containsKey(key)) - this.put(key, null); - } - /** Make sure this table contains a non-empty Entry for the given key. */ - Object initializeEntry(ClassValue key, Object value) { - Object prior = this.get(key); - if (prior != null) { - return unmaskNull(prior); - } - this.put(key, maskNull(value)); - return value; + // The following class could also be top level and non-public: + + /** A backing map for all ClassValues, relative a single given type. + * Gives a fully serialized "true state" for each pair (ClassValue cv, Class type). + * Also manages an unserialized fast-path cache. + */ + static class ClassValueMap extends WeakHashMap> { + private final Class type; + private Entry[] cacheArray; + private int cacheLoad, cacheLoadLimit; + + /** Number of entries initially allocated to each type when first used with any ClassValue. + * It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves. + * Must be a power of 2. + */ + private static final int INITIAL_ENTRIES = 32; + + /** Build a backing map for ClassValues, relative the given type. + * Also, create an empty cache array and install it on the class. + */ + ClassValueMap(Class type) { + this.type = type; + sizeCache(INITIAL_ENTRIES); } - Object maskNull(Object x) { - return x == null ? this : x; + Entry[] getCache() { return cacheArray; } + + /** Initiate a query. Store a promise (placeholder) if there is no value yet. */ + synchronized + Entry startEntry(ClassValue classValue) { + @SuppressWarnings("unchecked") // one map has entries for all value types + Entry e = (Entry) get(classValue.identity); + Version v = classValue.version(); + if (e == null) { + e = v.promise(); + // The presence of a promise means that a value is pending for v. + // Eventually, finishEntry will overwrite the promise. + put(classValue.identity, e); + // Note that the promise is never entered into the cache! + return e; + } else if (e.isPromise()) { + // Somebody else has asked the same question. + // Let the races begin! + if (e.version() != v) { + e = v.promise(); + put(classValue.identity, e); + } + return e; + } else { + // there is already a completed entry here; report it + if (e.version() != v) { + // There is a stale but valid entry here; make it fresh again. + // Once an entry is in the hash table, we don't care what its version is. + e = e.refreshVersion(v); + put(classValue.identity, e); + } + // Add to the cache, to enable the fast path, next time. + checkCacheLoad(); + addToCache(classValue, e); + return e; + } } - Object unmaskNull(Object x) { - return x == this ? null : x; + + /** Finish a query. Overwrite a matching placeholder. Drop stale incoming values. */ + synchronized + Entry finishEntry(ClassValue classValue, Entry e) { + @SuppressWarnings("unchecked") // one map has entries for all value types + Entry e0 = (Entry) get(classValue.identity); + if (e == e0) { + // We can get here during exception processing, unwinding from computeValue. + assert(e.isPromise()); + remove(classValue.identity); + return null; + } else if (e0 != null && e0.isPromise() && e0.version() == e.version()) { + // If e0 matches the intended entry, there has not been a remove call + // between the previous startEntry and now. So now overwrite e0. + Version v = classValue.version(); + if (e.version() != v) + e = e.refreshVersion(v); + put(classValue.identity, e); + // Add to the cache, to enable the fast path, next time. + checkCacheLoad(); + addToCache(classValue, e); + return e; + } else { + // Some sort of mismatch; caller must try again. + return null; + } } + + /** Remove an entry. */ + synchronized + void removeEntry(ClassValue classValue) { + // make all cache elements for this guy go stale: + if (remove(classValue.identity) != null) { + classValue.bumpVersion(); + removeStaleEntries(classValue); + } + } + + /** Change the value for an entry. */ + synchronized + void changeEntry(ClassValue classValue, T value) { + @SuppressWarnings("unchecked") // one map has entries for all value types + Entry e0 = (Entry) get(classValue.identity); + Version version = classValue.version(); + if (e0 != null) { + if (e0.version() == version && e0.value() == value) + // no value change => no version change needed + return; + classValue.bumpVersion(); + removeStaleEntries(classValue); + } + Entry e = makeEntry(version, value); + put(classValue.identity, e); + // Add to the cache, to enable the fast path, next time. + checkCacheLoad(); + addToCache(classValue, e); + } + + /// -------- + /// Cache management. + /// -------- + + // Statics do not need synchronization. + + /** Load the cache entry at the given (hashed) location. */ + static Entry loadFromCache(Entry[] cache, int i) { + // non-racing cache.length : constant + // racing cache[i & (mask)] : null <=> Entry + return cache[i & (cache.length-1)]; + // invariant: returned value is null or well-constructed (ready to match) + } + + /** Look in the cache, at the home location for the given ClassValue. */ + static Entry probeHomeLocation(Entry[] cache, ClassValue classValue) { + return classValue.castEntry(loadFromCache(cache, classValue.hashCodeForCache)); + } + + /** Given that first probe was a collision, retry at nearby locations. */ + static Entry probeBackupLocations(Entry[] cache, ClassValue classValue) { + if (PROBE_LIMIT <= 0) return null; + // Probe the cache carefully, in a range of slots. + int mask = (cache.length-1); + int home = (classValue.hashCodeForCache & mask); + Entry e2 = cache[home]; // victim, if we find the real guy + if (e2 == null) { + return null; // if nobody is at home, no need to search nearby + } + // assume !classValue.match(e2), but do not assert, because of races + int pos2 = -1; + for (int i = home + 1; i < home + PROBE_LIMIT; i++) { + Entry e = cache[i & mask]; + if (e == null) { + break; // only search within non-null runs + } + if (classValue.match(e)) { + // relocate colliding entry e2 (from cache[home]) to first empty slot + cache[home] = e; + if (pos2 >= 0) { + cache[i & mask] = Entry.DEAD_ENTRY; + } else { + pos2 = i; + } + cache[pos2 & mask] = ((entryDislocation(cache, pos2, e2) < PROBE_LIMIT) + ? e2 // put e2 here if it fits + : Entry.DEAD_ENTRY); + return classValue.castEntry(e); + } + // Remember first empty slot, if any: + if (!e.isLive() && pos2 < 0) pos2 = i; + } + return null; + } + + /** How far out of place is e? */ + private static int entryDislocation(Entry[] cache, int pos, Entry e) { + ClassValue cv = e.classValueOrNull(); + if (cv == null) return 0; // entry is not live! + int mask = (cache.length-1); + return (pos - cv.hashCodeForCache) & mask; + } + + /// -------- + /// Below this line all functions are private, and assume synchronized access. + /// -------- + + private void sizeCache(int length) { + assert((length & (length-1)) == 0); // must be power of 2 + cacheLoad = 0; + cacheLoadLimit = (int) ((double) length * CACHE_LOAD_LIMIT / 100); + cacheArray = new Entry[length]; + } + + /** Make sure the cache load stays below its limit, if possible. */ + private void checkCacheLoad() { + if (cacheLoad >= cacheLoadLimit) { + reduceCacheLoad(); + } + } + private void reduceCacheLoad() { + removeStaleEntries(); + if (cacheLoad < cacheLoadLimit) + return; // win + Entry[] oldCache = getCache(); + if (oldCache.length > HASH_MASK) + return; // lose + sizeCache(oldCache.length * 2); + for (Entry e : oldCache) { + if (e != null && e.isLive()) { + addToCache(e); + } + } + } + + /** Remove stale entries in the given range. + * Should be executed under a Map lock. + */ + private void removeStaleEntries(Entry[] cache, int begin, int count) { + if (PROBE_LIMIT <= 0) return; + int mask = (cache.length-1); + int removed = 0; + for (int i = begin; i < begin + count; i++) { + Entry e = cache[i & mask]; + if (e == null || e.isLive()) + continue; // skip null and live entries + Entry replacement = null; + if (PROBE_LIMIT > 1) { + // avoid breaking up a non-null run + replacement = findReplacement(cache, i); + } + cache[i & mask] = replacement; + if (replacement == null) removed += 1; + } + cacheLoad = Math.max(0, cacheLoad - removed); + } + + /** Clearing a cache slot risks disconnecting following entries + * from the head of a non-null run, which would allow them + * to be found via reprobes. Find an entry after cache[begin] + * to plug into the hole, or return null if none is needed. + */ + private Entry findReplacement(Entry[] cache, int home1) { + Entry replacement = null; + int haveReplacement = -1, replacementPos = 0; + int mask = (cache.length-1); + for (int i2 = home1 + 1; i2 < home1 + PROBE_LIMIT; i2++) { + Entry e2 = cache[i2 & mask]; + if (e2 == null) break; // End of non-null run. + if (!e2.isLive()) continue; // Doomed anyway. + int dis2 = entryDislocation(cache, i2, e2); + if (dis2 == 0) continue; // e2 already optimally placed + int home2 = i2 - dis2; + if (home2 <= home1) { + // e2 can replace entry at cache[home1] + if (home2 == home1) { + // Put e2 exactly where he belongs. + haveReplacement = 1; + replacementPos = i2; + replacement = e2; + } else if (haveReplacement <= 0) { + haveReplacement = 0; + replacementPos = i2; + replacement = e2; + } + // And keep going, so we can favor larger dislocations. + } + } + if (haveReplacement >= 0) { + if (cache[(replacementPos+1) & mask] != null) { + // Be conservative, to avoid breaking up a non-null run. + cache[replacementPos & mask] = (Entry) Entry.DEAD_ENTRY; + } else { + cache[replacementPos & mask] = null; + cacheLoad -= 1; + } + } + return replacement; + } + + /** Remove stale entries in the range near classValue. */ + private void removeStaleEntries(ClassValue classValue) { + removeStaleEntries(getCache(), classValue.hashCodeForCache, PROBE_LIMIT); + } + + /** Remove all stale entries, everywhere. */ + private void removeStaleEntries() { + Entry[] cache = getCache(); + removeStaleEntries(cache, 0, cache.length + PROBE_LIMIT - 1); + } + + /** Add the given entry to the cache, in its home location, unless it is out of date. */ + private void addToCache(Entry e) { + ClassValue classValue = e.classValueOrNull(); + if (classValue != null) + addToCache(classValue, e); + } + + /** Add the given entry to the cache, in its home location. */ + private void addToCache(ClassValue classValue, Entry e) { + if (PROBE_LIMIT <= 0) return; // do not fill cache + // Add e to the cache. + Entry[] cache = getCache(); + int mask = (cache.length-1); + int home = classValue.hashCodeForCache & mask; + Entry e2 = placeInCache(cache, home, e, false); + if (e2 == null) return; // done + if (PROBE_LIMIT > 1) { + // try to move e2 somewhere else in his probe range + int dis2 = entryDislocation(cache, home, e2); + int home2 = home - dis2; + for (int i2 = home2; i2 < home2 + PROBE_LIMIT; i2++) { + if (placeInCache(cache, i2 & mask, e2, true) == null) { + return; + } + } + } + // Note: At this point, e2 is just dropped from the cache. + } + + /** Store the given entry. Update cacheLoad, and return any live victim. + * 'Gently' means return self rather than dislocating a live victim. + */ + private Entry placeInCache(Entry[] cache, int pos, Entry e, boolean gently) { + Entry e2 = overwrittenEntry(cache[pos]); + if (gently && e2 != null) { + // do not overwrite a live entry + return e; + } else { + cache[pos] = e; + return e2; + } + } + + /** Note an entry that is about to be overwritten. + * If it is not live, quietly replace it by null. + * If it is an actual null, increment cacheLoad, + * because the caller is going to store something + * in its place. + */ + private Entry overwrittenEntry(Entry e2) { + if (e2 == null) cacheLoad += 1; + else if (e2.isLive()) return e2; + return null; + } + + /** Percent loading of cache before resize. */ + private static final int CACHE_LOAD_LIMIT = 67; // 0..100 + /** Maximum number of probes to attempt. */ + private static final int PROBE_LIMIT = 6; // 1.. + // N.B. Set PROBE_LIMIT=0 to disable all fast paths. } } diff --git a/jdk/test/java/lang/invoke/ClassValueTest.java b/jdk/test/java/lang/invoke/ClassValueTest.java index c357efaf434..56b577159d5 100644 --- a/jdk/test/java/lang/invoke/ClassValueTest.java +++ b/jdk/test/java/lang/invoke/ClassValueTest.java @@ -57,7 +57,7 @@ public class ClassValueTest { } } - static final Class[] CLASSES = { + static final Class[] CLASSES = { String.class, Integer.class, int.class, @@ -69,11 +69,11 @@ public class ClassValueTest { @Test public void testGet() { countForCV1 = 0; - for (Class c : CLASSES) { + for (Class c : CLASSES) { assertEquals(nameForCV1(c), CV1.get(c)); } assertEquals(CLASSES.length, countForCV1); - for (Class c : CLASSES) { + for (Class c : CLASSES) { assertEquals(nameForCV1(c), CV1.get(c)); } assertEquals(CLASSES.length, countForCV1); @@ -81,7 +81,7 @@ public class ClassValueTest { @Test public void testRemove() { - for (Class c : CLASSES) { + for (Class c : CLASSES) { CV1.get(c); } countForCV1 = 0; @@ -90,7 +90,7 @@ public class ClassValueTest { CV1.remove(CLASSES[i]); } assertEquals(0, countForCV1); // no change - for (Class c : CLASSES) { + for (Class c : CLASSES) { assertEquals(nameForCV1(c), CV1.get(c)); } assertEquals(REMCOUNT, countForCV1); @@ -120,7 +120,7 @@ public class ClassValueTest { for (int pass = 0; pass <= 2; pass++) { for (int i1 = 0; i1 < CVN_COUNT1; i1++) { eachClass: - for (Class c : CLASSES) { + for (Class c : CLASSES) { for (int i2 = 0; i2 < CVN_COUNT2; i2++) { int n = i1*CVN_COUNT2 + i2; assertEquals(0, countForCVN); @@ -152,8 +152,10 @@ public class ClassValueTest { } } assertEquals(countForCVN, 0); - for (int n = 0; n < cvns.length; n++) { - for (Class c : CLASSES) { + System.out.println("[rechecking values]"); + for (int i = 0; i < cvns.length * 10; i++) { + int n = i % cvns.length; + for (Class c : CLASSES) { assertEquals(nameForCVN(c, n), cvns[n].get(c)); } } From 323665eec5a90c577876e6783a2899ac192e274f Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Wed, 18 Jan 2012 18:26:36 -0800 Subject: [PATCH 54/96] 7131308: Three regression tests fail due to bad fix for 7127924 Reviewed-by: jjg --- langtools/test/tools/javac/diags/CheckExamples.java | 2 +- langtools/test/tools/javac/diags/MessageInfo.java | 2 +- langtools/test/tools/javac/diags/RunExamples.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/langtools/test/tools/javac/diags/CheckExamples.java b/langtools/test/tools/javac/diags/CheckExamples.java index 648f9833e6c..aa35fc1589b 100644 --- a/langtools/test/tools/javac/diags/CheckExamples.java +++ b/langtools/test/tools/javac/diags/CheckExamples.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6968063, 7127924 + * @bug 6968063 7127924 * @summary provide examples of code that generate diagnostics * @build Example CheckExamples * @run main/othervm CheckExamples diff --git a/langtools/test/tools/javac/diags/MessageInfo.java b/langtools/test/tools/javac/diags/MessageInfo.java index 8e40670efca..f053b3da3be 100644 --- a/langtools/test/tools/javac/diags/MessageInfo.java +++ b/langtools/test/tools/javac/diags/MessageInfo.java @@ -23,7 +23,7 @@ /** * @test - * @bug 7013272, 7127924 + * @bug 7013272 7127924 * @summary Automatically generate info about how compiler resource keys are used * @build Example ArgTypeCompilerFactory MessageFile MessageInfo * @run main/othervm MessageInfo diff --git a/langtools/test/tools/javac/diags/RunExamples.java b/langtools/test/tools/javac/diags/RunExamples.java index c09947cdf3e..858948387a6 100644 --- a/langtools/test/tools/javac/diags/RunExamples.java +++ b/langtools/test/tools/javac/diags/RunExamples.java @@ -23,7 +23,7 @@ /** * @test - * @bug 6968063, 7127924 + * @bug 6968063 7127924 * @summary provide examples of code that generate diagnostics * @build ArgTypeCompilerFactory Example HTMLWriter RunExamples * @run main/othervm RunExamples From c21cf7cf4bf1db5310046493a3ba147cf9198b02 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Thu, 19 Jan 2012 10:56:51 -0800 Subject: [PATCH 55/96] 7131288: COMPILE SKIPPED: deopt handler overflow (retry at different tier) Fix exception handler stub size, enable guarantees to check for the correct deopt and exception stub sizes in the future Reviewed-by: kvn, never, twisti --- hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 5 ++--- hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp | 4 ++-- hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 5 ++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 96953eebf5a..565fdee6565 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -391,7 +391,7 @@ int LIR_Assembler::emit_exception_handler() { __ call(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id), relocInfo::runtime_call_type); __ delayed()->nop(); __ should_not_reach_here(); - assert(code_offset() - offset <= exception_handler_size, "overflow"); + guarantee(code_offset() - offset <= exception_handler_size, "overflow"); __ end_a_stub(); return offset; @@ -474,8 +474,7 @@ int LIR_Assembler::emit_deopt_handler() { AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack()); __ JUMP(deopt_blob, G3_scratch, 0); // sethi;jmp __ delayed()->nop(); - assert(code_offset() - offset <= deopt_handler_size, "overflow"); - debug_only(__ stop("should have gone to the caller");) + guarantee(code_offset() - offset <= deopt_handler_size, "overflow"); __ end_a_stub(); return offset; diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp index 386159c89b8..1fa8e24565c 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp @@ -69,7 +69,7 @@ enum { #else call_stub_size = 20, #endif // _LP64 - exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(10*4), - deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(10*4) }; + exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128), + deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64) }; #endif // CPU_SPARC_VM_C1_LIRASSEMBLER_SPARC_HPP diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 3c24feb724b..c745ade299f 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -406,7 +406,7 @@ int LIR_Assembler::emit_exception_handler() { // search an exception handler (rax: exception oop, rdx: throwing pc) __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id))); __ should_not_reach_here(); - assert(code_offset() - offset <= exception_handler_size, "overflow"); + guarantee(code_offset() - offset <= exception_handler_size, "overflow"); __ end_a_stub(); return offset; @@ -490,8 +490,7 @@ int LIR_Assembler::emit_deopt_handler() { __ pushptr(here.addr()); __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); - - assert(code_offset() - offset <= deopt_handler_size, "overflow"); + guarantee(code_offset() - offset <= deopt_handler_size, "overflow"); __ end_a_stub(); return offset; From e323998c19d4002302dfa0102b5868a1205aae16 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Thu, 19 Jan 2012 13:00:11 -0800 Subject: [PATCH 56/96] 7111138: delete the obsolete flag -XX:+UseRicochetFrames Reviewed-by: dholmes, bdelsart, kvn, twisti --- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 2 +- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 4 +- .../src/cpu/zero/vm/methodHandles_zero.hpp | 40 ------------- hotspot/src/share/vm/prims/methodHandles.cpp | 58 +------------------ hotspot/src/share/vm/prims/methodHandles.hpp | 40 ------------- hotspot/src/share/vm/runtime/globals.hpp | 4 -- .../src/share/vm/runtime/sharedRuntime.cpp | 2 - 7 files changed, 6 insertions(+), 144 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index 5bdf88e53ba..1627685dad7 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -1045,7 +1045,7 @@ int MethodHandles::adapter_conversion_ops_supported_mask() { |(1<is_in((address) rfp->saved_args_base())) { + if (Universe::heap()->is_in((address) rfp->saved_args_base())) { // Probably an interpreter frame. base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset]; } @@ -1104,7 +1104,7 @@ int MethodHandles::adapter_conversion_ops_supported_mask() { |(1<.cpp -frame MethodHandles::ricochet_frame_sender(const frame& fr, RegisterMap *map) { - ShouldNotCallThis(); - return fr; -} -void MethodHandles::ricochet_frame_oops_do(const frame& fr, OopClosure* f, const RegisterMap* reg_map) { - ShouldNotCallThis(); -} -#endif //TARGET_ARCH_NYI_6939861 - - //------------------------------------------------------------------------------ // MethodHandles::ek_supported // @@ -251,28 +236,11 @@ bool MethodHandles::ek_supported(MethodHandles::EntryKind ek) { case _adapter_unused_13: return false; // not defined yet case _adapter_prim_to_ref: - return UseRicochetFrames && conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF); + return conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF); case _adapter_collect_args: - return UseRicochetFrames && conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS); + return conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS); case _adapter_fold_args: - return UseRicochetFrames && conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS); - case _adapter_opt_return_any: - return UseRicochetFrames; -#ifdef TARGET_ARCH_NYI_6939861 - // ports before 6939861 supported only three kinds of spread ops - case _adapter_spread_args: - // restrict spreads to three kinds: - switch (ek) { - case _adapter_opt_spread_0: - case _adapter_opt_spread_1: - case _adapter_opt_spread_more: - break; - default: - return false; - break; - } - break; -#endif //TARGET_ARCH_NYI_6939861 + return conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS); } return true; } @@ -1988,9 +1956,6 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) { case _adapter_prim_to_ref: // boxer MH to use case _adapter_collect_args: // method handle which collects the args case _adapter_fold_args: // method handle which collects the args - if (!UseRicochetFrames) { - { err = "box/collect/fold operators are not supported"; break; } - } if (!java_lang_invoke_MethodHandle::is_instance(argument())) { err = "MethodHandle adapter argument required"; break; } arg_mtype = Handle(THREAD, java_lang_invoke_MethodHandle::type(argument())); @@ -2370,7 +2335,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu case _adapter_prim_to_ref: { - assert(UseRicochetFrames, "else don't come here"); // vminfo will be the location to insert the return value vminfo = argslot; ek_opt = _adapter_opt_collect_ref; @@ -2436,20 +2400,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu case _adapter_spread_args: { -#ifdef TARGET_ARCH_NYI_6939861 - // ports before 6939861 supported only three kinds of spread ops - if (!UseRicochetFrames) { - int array_size = slots_pushed + 1; - assert(array_size >= 0, ""); - vminfo = array_size; - switch (array_size) { - case 0: ek_opt = _adapter_opt_spread_0; break; - case 1: ek_opt = _adapter_opt_spread_1; break; - default: ek_opt = _adapter_opt_spread_more; break; - } - break; - } -#endif //TARGET_ARCH_NYI_6939861 // vminfo will be the required length of the array int array_size = (slots_pushed + 1) / (type2size[dest] == 2 ? 2 : 1); vminfo = array_size; @@ -2494,7 +2444,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu case _adapter_collect_args: { - assert(UseRicochetFrames, "else don't come here"); int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); // vminfo will be the location to insert the return value vminfo = argslot; @@ -2563,7 +2512,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu case _adapter_fold_args: { - assert(UseRicochetFrames, "else don't come here"); int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); // vminfo will be the location to insert the return value vminfo = argslot + elem_slots; diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index f1c44ba7b4d..514ba6aa93a 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -738,46 +738,6 @@ public: #ifdef TARGET_ARCH_ppc # include "methodHandles_ppc.hpp" #endif - -#ifdef TARGET_ARCH_NYI_6939861 - // Here are some backward compatible declarations until the 6939861 ports are updated. - #define _adapter_flyby (_EK_LIMIT + 10) - #define _adapter_ricochet (_EK_LIMIT + 11) - #define _adapter_opt_spread_1 _adapter_opt_spread_1_ref - #define _adapter_opt_spread_more _adapter_opt_spread_ref - enum { - _INSERT_NO_MASK = -1, - _INSERT_REF_MASK = 0, - _INSERT_INT_MASK = 1, - _INSERT_LONG_MASK = 3 - }; - static void get_ek_bound_mh_info(EntryKind ek, BasicType& arg_type, int& arg_mask, int& arg_slots) { - arg_type = ek_bound_mh_arg_type(ek); - arg_mask = 0; - arg_slots = type2size[arg_type];; - } - static void get_ek_adapter_opt_swap_rot_info(EntryKind ek, int& swap_bytes, int& rotate) { - int swap_slots = ek_adapter_opt_swap_slots(ek); - rotate = ek_adapter_opt_swap_mode(ek); - swap_bytes = swap_slots * Interpreter::stackElementSize; - } - static int get_ek_adapter_opt_spread_info(EntryKind ek) { - return ek_adapter_opt_spread_count(ek); - } - - static void insert_arg_slots(MacroAssembler* _masm, - RegisterOrConstant arg_slots, - int arg_mask, - Register argslot_reg, - Register temp_reg, Register temp2_reg, Register temp3_reg = noreg); - - static void remove_arg_slots(MacroAssembler* _masm, - RegisterOrConstant arg_slots, - Register argslot_reg, - Register temp_reg, Register temp2_reg, Register temp3_reg = noreg); - - static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN; -#endif //TARGET_ARCH_NYI_6939861 }; diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 02311e215a9..88e59385098 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3826,10 +3826,6 @@ class CommandLineFlags { develop(bool, StressMethodHandleWalk, false, \ "Process all method handles with MethodHandleWalk") \ \ - diagnostic(bool, UseRicochetFrames, true, \ - "use ricochet stack frames for method handle combination, " \ - "if the platform supports them") \ - \ experimental(bool, TrustFinalNonStaticFields, false, \ "trust final non-static declarations for constant folding") \ \ diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 486c21dcfc0..bea5e6bfd87 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -121,7 +121,6 @@ void SharedRuntime::generate_stubs() { void SharedRuntime::generate_ricochet_blob() { if (!EnableInvokeDynamic) return; // leave it as a null -#ifndef TARGET_ARCH_NYI_6939861 // allocate space for the code ResourceMark rm; // setup code generation tools @@ -142,7 +141,6 @@ void SharedRuntime::generate_ricochet_blob() { } _ricochet_blob = RicochetBlob::create(&buffer, bounce_offset, exception_offset, frame_size_in_words); -#endif } From 5b3f2efc2e87a9af17645f2daf7da93024487a28 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 20 Jan 2012 09:43:06 -0800 Subject: [PATCH 57/96] 7131302: connode.cpp:205 Error: ShouldNotReachHere() Add Value() methods to short and byte Load nodes to truncate constants which does not fit. Reviewed-by: jrose --- hotspot/src/share/vm/opto/memnode.cpp | 56 ++++++++++++++++++++++++++- hotspot/src/share/vm/opto/memnode.hpp | 30 +++++++------- 2 files changed, 72 insertions(+), 14 deletions(-) diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index bd144751d42..bf4189921eb 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -1718,8 +1718,10 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { bool is_instance = (tinst != NULL) && tinst->is_known_instance_field(); if (ReduceFieldZeroing || is_instance) { Node* value = can_see_stored_value(mem,phase); - if (value != NULL && value->is_Con()) + if (value != NULL && value->is_Con()) { + assert(value->bottom_type()->higher_equal(_type),"sanity"); return value->bottom_type(); + } } if (is_instance) { @@ -1759,6 +1761,19 @@ Node *LoadBNode::Ideal(PhaseGVN *phase, bool can_reshape) { return LoadNode::Ideal(phase, can_reshape); } +const Type* LoadBNode::Value(PhaseTransform *phase) const { + Node* mem = in(MemNode::Memory); + Node* value = can_see_stored_value(mem,phase); + if (value != NULL && value->is_Con()) { + // If the input to the store does not fit with the load's result type, + // it must be truncated. We can't delay until Ideal call since + // a singleton Value is needed for split_thru_phi optimization. + int con = value->get_int(); + return TypeInt::make((con << 24) >> 24); + } + return LoadNode::Value(phase); +} + //--------------------------LoadUBNode::Ideal------------------------------------- // // If the previous store is to the same address as this load, @@ -1775,6 +1790,19 @@ Node* LoadUBNode::Ideal(PhaseGVN* phase, bool can_reshape) { return LoadNode::Ideal(phase, can_reshape); } +const Type* LoadUBNode::Value(PhaseTransform *phase) const { + Node* mem = in(MemNode::Memory); + Node* value = can_see_stored_value(mem,phase); + if (value != NULL && value->is_Con()) { + // If the input to the store does not fit with the load's result type, + // it must be truncated. We can't delay until Ideal call since + // a singleton Value is needed for split_thru_phi optimization. + int con = value->get_int(); + return TypeInt::make(con & 0xFF); + } + return LoadNode::Value(phase); +} + //--------------------------LoadUSNode::Ideal------------------------------------- // // If the previous store is to the same address as this load, @@ -1791,6 +1819,19 @@ Node *LoadUSNode::Ideal(PhaseGVN *phase, bool can_reshape) { return LoadNode::Ideal(phase, can_reshape); } +const Type* LoadUSNode::Value(PhaseTransform *phase) const { + Node* mem = in(MemNode::Memory); + Node* value = can_see_stored_value(mem,phase); + if (value != NULL && value->is_Con()) { + // If the input to the store does not fit with the load's result type, + // it must be truncated. We can't delay until Ideal call since + // a singleton Value is needed for split_thru_phi optimization. + int con = value->get_int(); + return TypeInt::make(con & 0xFFFF); + } + return LoadNode::Value(phase); +} + //--------------------------LoadSNode::Ideal-------------------------------------- // // If the previous store is to the same address as this load, @@ -1809,6 +1850,19 @@ Node *LoadSNode::Ideal(PhaseGVN *phase, bool can_reshape) { return LoadNode::Ideal(phase, can_reshape); } +const Type* LoadSNode::Value(PhaseTransform *phase) const { + Node* mem = in(MemNode::Memory); + Node* value = can_see_stored_value(mem,phase); + if (value != NULL && value->is_Con()) { + // If the input to the store does not fit with the load's result type, + // it must be truncated. We can't delay until Ideal call since + // a singleton Value is needed for split_thru_phi optimization. + int con = value->get_int(); + return TypeInt::make((con << 16) >> 16); + } + return LoadNode::Value(phase); +} + //============================================================================= //----------------------------LoadKlassNode::make------------------------------ // Polymorphic factory method: diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index f15d4986bd0..36623a87a6d 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -215,6 +215,7 @@ public: virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual const Type *Value(PhaseTransform *phase) const; virtual int store_Opcode() const { return Op_StoreB; } virtual BasicType memory_type() const { return T_BYTE; } }; @@ -228,6 +229,7 @@ public: virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); + virtual const Type *Value(PhaseTransform *phase) const; virtual int store_Opcode() const { return Op_StoreB; } virtual BasicType memory_type() const { return T_BYTE; } }; @@ -241,10 +243,25 @@ public: virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual const Type *Value(PhaseTransform *phase) const; virtual int store_Opcode() const { return Op_StoreC; } virtual BasicType memory_type() const { return T_CHAR; } }; +//------------------------------LoadSNode-------------------------------------- +// Load a short (16bits signed) from memory +class LoadSNode : public LoadNode { +public: + LoadSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::SHORT ) + : LoadNode(c,mem,adr,at,ti) {} + virtual int Opcode() const; + virtual uint ideal_reg() const { return Op_RegI; } + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual const Type *Value(PhaseTransform *phase) const; + virtual int store_Opcode() const { return Op_StoreC; } + virtual BasicType memory_type() const { return T_SHORT; } +}; + //------------------------------LoadINode-------------------------------------- // Load an integer from memory class LoadINode : public LoadNode { @@ -433,19 +450,6 @@ public: }; -//------------------------------LoadSNode-------------------------------------- -// Load a short (16bits signed) from memory -class LoadSNode : public LoadNode { -public: - LoadSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::SHORT ) - : LoadNode(c,mem,adr,at,ti) {} - virtual int Opcode() const; - virtual uint ideal_reg() const { return Op_RegI; } - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); - virtual int store_Opcode() const { return Op_StoreC; } - virtual BasicType memory_type() const { return T_SHORT; } -}; - //------------------------------StoreNode-------------------------------------- // Store value; requires Store, Address and Value class StoreNode : public MemNode { From a95f19a9f31038784b454129aa30ae8fdb379227 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 20 Jan 2012 13:08:40 -0800 Subject: [PATCH 58/96] Added tag jdk8-b22 for changeset ca3137c9be77 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index a531df300ad..bb12895c257 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -143,3 +143,4 @@ a4f28069d44a379cda99dd1d921d19f819726d22 jdk8-b15 237bc29afbfc6f56a4fe4a6008e2befb59c44bac jdk8-b19 5a5eaf6374bcbe23530899579fed17a05b7705f3 jdk8-b20 cc771d92284f71765eca14d6d08703c4af254c04 jdk8-b21 +7ad075c809952e355d25030605da6af30456ed74 jdk8-b22 From 10e49d5a1e15d8fd95d66c15b504f891d7943dc2 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 20 Jan 2012 13:08:41 -0800 Subject: [PATCH 59/96] Added tag jdk8-b22 for changeset 5df4cdb80642 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 372ce57ef2a..afe42c25fa3 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -143,3 +143,4 @@ e59c47de1ad8982ff3b0e843773a6902b36c2337 jdk8-b14 e1366c5d84ef984095a332bcee70b3938232d07d jdk8-b19 51d8b6cb18c0978ecfa4f33e1537d35ee01b69fa jdk8-b20 f157fc2a71a38ce44007a6f18d5b011824dce705 jdk8-b21 +a11d0062c445d5f36651c78650ab88aa594bcbff jdk8-b22 From 106518995c27e69781752c0336ac8d062efc5017 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 20 Jan 2012 13:08:43 -0800 Subject: [PATCH 60/96] Added tag jdk8-b22 for changeset 8b2993f4f9c6 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 214b0ee6025..ed98513d18a 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -211,3 +211,4 @@ a2fef924d8e6f37dac2a887315e3502876cc8e24 hs23-b08 fe2c8764998112b7fefcd7d41599714813ae4327 jdk8-b20 9952d1c439d64c5fd4ad1236a63a62bd5a49d4c3 jdk8-b21 513351373923f74a7c91755748b95c9771e59f96 hs23-b10 +24727fb37561779077fdfa5a33342246f20e5c0f jdk8-b22 From 1599f28a1f94de46aab30fdde0ac1d9b6bd94b24 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 20 Jan 2012 13:08:44 -0800 Subject: [PATCH 61/96] Added tag jdk8-b22 for changeset 99a092d22c70 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index a999a2ba6fc..462530760e6 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -143,3 +143,4 @@ ebec6a7e8d4e481d205a2109ddeea8121d76db7f jdk8-b18 dffeb62b1a7fc8b316bf58fe5479323f3661894e jdk8-b19 f052abb8f37444ba77858913887d0d92795dd6b8 jdk8-b20 d41eeadf5c1344b88c5051a997aec9e1ad7ce1db jdk8-b21 +cf9d6ec44f891236ad18451021d6dcd57dc82f7b jdk8-b22 From ae6fa39b205bcba1863a593399becbdb6540a162 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 20 Jan 2012 13:08:45 -0800 Subject: [PATCH 62/96] Added tag jdk8-b22 for changeset 0a4b26cf7553 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 188e7da72a7..639ceef74ca 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -143,3 +143,4 @@ c9ab96ff23d52d85d5dcce1f9c0fd7a3de418c74 jdk8-b15 b73b733214aa43648d69a2da51e6b48fda902a2d jdk8-b19 2b2818e3386f4510c390f6aea90d77e1c6a5bf9e jdk8-b20 c266cab0e3fff05f2048c23046c14d60f7102175 jdk8-b21 +8d3df89b0f2d3c603b2edb0f5e24af1245397cc6 jdk8-b22 From 6f9ada3843068a6c8afdd13bb22a69d8ca4ce540 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 20 Jan 2012 13:08:48 -0800 Subject: [PATCH 63/96] Added tag jdk8-b22 for changeset 054ae6fb4346 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 58e1636aaaf..da0c9215a8f 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -143,3 +143,4 @@ b71d1acfae5240d8c1359443cd02b5ddb587231c jdk8-b17 3778f85773055e81eab6c5ef828935ecca241810 jdk8-b19 39e938cd1b82ec3aab0a9aa66fd8a0457cd0c9c2 jdk8-b20 664fa4fb0ee411ef048903c479f8b962fcdb2f4b jdk8-b21 +dda27c73d8db4a9c7a23872b6f0c5106edcb2021 jdk8-b22 From 8d4b04a36509475380486cb0563dec305542d67c Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 20 Jan 2012 13:08:51 -0800 Subject: [PATCH 64/96] Added tag jdk8-b22 for changeset e6809c7d1735 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 509ea02f948..d4c24a7c411 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -143,3 +143,4 @@ ab1b1cc7857716914f2bb20b3128e5a8978290f7 jdk8-b18 77b2c066084cbc75150efc6603a713c558329813 jdk8-b19 ffd294128a48cbb90ce8f0569f82b61f1f164a18 jdk8-b20 bcb21abf1c4177baf4574f99709513dcd4474727 jdk8-b21 +390a7828ae18324030c0546b6452d51093ffa451 jdk8-b22 From 55c9a74046c035a244da13f49b597fd5d01c5b4d Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Fri, 20 Jan 2012 15:02:12 -0800 Subject: [PATCH 65/96] 7131028: Switch statement takes wrong path Pass correct type to branch in LIRGenerator::do_SwitchRanges() Reviewed-by: kvn, never --- hotspot/src/share/vm/c1/c1_LIR.hpp | 5 +++-- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index c440b71374f..7220c335d09 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -1354,9 +1354,10 @@ class LIR_OpBranch: public LIR_Op { CodeStub* _stub; // if this is a branch to a stub, this is the stub public: - LIR_OpBranch(LIR_Condition cond, Label* lbl) + LIR_OpBranch(LIR_Condition cond, BasicType type, Label* lbl) : LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*) NULL) , _cond(cond) + , _type(type) , _label(lbl) , _block(NULL) , _ublock(NULL) @@ -2053,7 +2054,7 @@ class LIR_List: public CompilationResourceObj { void jump(CodeStub* stub) { append(new LIR_OpBranch(lir_cond_always, T_ILLEGAL, stub)); } - void branch(LIR_Condition cond, Label* lbl) { append(new LIR_OpBranch(cond, lbl)); } + void branch(LIR_Condition cond, BasicType type, Label* lbl) { append(new LIR_OpBranch(cond, type, lbl)); } void branch(LIR_Condition cond, BasicType type, BlockBegin* block) { assert(type != T_FLOAT && type != T_DOUBLE, "no fp comparisons"); append(new LIR_OpBranch(cond, type, block)); diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 5f3155d412a..d92d919865c 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2350,7 +2350,7 @@ void LIRGenerator::do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegi } else { LabelObj* L = new LabelObj(); __ cmp(lir_cond_less, value, low_key); - __ branch(lir_cond_less, L->label()); + __ branch(lir_cond_less, T_INT, L->label()); __ cmp(lir_cond_lessEqual, value, high_key); __ branch(lir_cond_lessEqual, T_INT, dest); __ branch_destination(L->label()); From f0908fd16bc005d9c8af2239a2bb3dc812f229ee Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 20 Jan 2012 16:56:31 -0800 Subject: [PATCH 66/96] Added tag hs23-b11 for changeset ad2a7ae4f3b0 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index ed98513d18a..383edfe958d 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -212,3 +212,4 @@ fe2c8764998112b7fefcd7d41599714813ae4327 jdk8-b20 9952d1c439d64c5fd4ad1236a63a62bd5a49d4c3 jdk8-b21 513351373923f74a7c91755748b95c9771e59f96 hs23-b10 24727fb37561779077fdfa5a33342246f20e5c0f jdk8-b22 +dcc292399a39113957eebbd3e487b7e05e2c79fc hs23-b11 From 63b889aba655062f22de4eb0968a1bd8914db22f Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 20 Jan 2012 17:07:33 -0800 Subject: [PATCH 67/96] 7131979: new hotspot build - hs23-b12 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 82956ba6a29..5a1698988bd 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011 HS_MAJOR_VER=23 HS_MINOR_VER=0 -HS_BUILD_NUMBER=11 +HS_BUILD_NUMBER=12 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From af9f0733746026a673e636d40e144c66e4c45403 Mon Sep 17 00:00:00 2001 From: Bill Pittore Date: Sat, 21 Jan 2012 23:02:40 -0500 Subject: [PATCH 68/96] 6972759: Step over not working after thrown exception and Pop Reset jvmtithreadstate exception state after frame pop and forceearlyreturn processed Reviewed-by: minqi, dholmes, dlong --- .../src/share/vm/prims/jvmtiThreadState.cpp | 18 ++++++++++++++++++ .../src/share/vm/prims/jvmtiThreadState.hpp | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/hotspot/src/share/vm/prims/jvmtiThreadState.cpp b/hotspot/src/share/vm/prims/jvmtiThreadState.cpp index faf9de7c2ff..398043b0fc8 100644 --- a/hotspot/src/share/vm/prims/jvmtiThreadState.cpp +++ b/hotspot/src/share/vm/prims/jvmtiThreadState.cpp @@ -319,6 +319,15 @@ void JvmtiThreadState::process_pending_step_for_popframe() { // clearing the flag indicates we are done with the PopFrame() dance clr_pending_step_for_popframe(); + // If exception was thrown in this frame, need to reset jvmti thread state. + // Single stepping may not get enabled correctly by the agent since + // exception state is passed in MethodExit event which may be sent at some + // time in the future. JDWP agent ignores MethodExit events if caused by + // an exception. + // + if (is_exception_detected()) { + clear_exception_detected(); + } // If step is pending for popframe then it may not be // a repeat step. The new_bci and method_id is same as current_bci // and current method_id after pop and step for recursive calls. @@ -385,6 +394,15 @@ void JvmtiThreadState::process_pending_step_for_earlyret() { // the ForceEarlyReturn() dance clr_pending_step_for_earlyret(); + // If exception was thrown in this frame, need to reset jvmti thread state. + // Single stepping may not get enabled correctly by the agent since + // exception state is passed in MethodExit event which may be sent at some + // time in the future. JDWP agent ignores MethodExit events if caused by + // an exception. + // + if (is_exception_detected()) { + clear_exception_detected(); + } // If step is pending for earlyret then it may not be a repeat step. // The new_bci and method_id is same as current_bci and current // method_id after earlyret and step for recursive calls. diff --git a/hotspot/src/share/vm/prims/jvmtiThreadState.hpp b/hotspot/src/share/vm/prims/jvmtiThreadState.hpp index 669420aa352..87d2f0b03a4 100644 --- a/hotspot/src/share/vm/prims/jvmtiThreadState.hpp +++ b/hotspot/src/share/vm/prims/jvmtiThreadState.hpp @@ -165,6 +165,10 @@ class JvmtiThreadState : public CHeapObj { inline bool is_exception_caught() { return _exception_caught; } inline void set_exception_detected() { _exception_detected = true; _exception_caught = false; } + inline void clear_exception_detected() { + _exception_detected = false; + assert(_exception_caught == false, "_exception_caught is out of phase"); + } inline void set_exception_caught() { _exception_caught = true; _exception_detected = false; } From 52979e620623fc51d843a39fd899dd5eaaa603c6 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Sun, 22 Jan 2012 14:03:20 -0800 Subject: [PATCH 69/96] 7130676: Tiered: assert(bci == 0 || 0<= bci && bci= trace_chunk_size) { methodHandle mhandle(THREAD, method); expand(CHECK); @@ -1574,8 +1580,13 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t int chunk_count = 0; for (;!st.at_end(); st.next()) { - // add element - bcis->ushort_at_put(chunk_count, st.bci()); + // Add entry and smear the -1 bci to 0 since the array only holds + // unsigned shorts. The later line number lookup would just smear + // the -1 to a 0 even if it could be recorded. + int bci = st.bci(); + if (bci == SynchronizationEntryBCI) bci = 0; + assert(bci == (jushort)bci, "doesn't fit"); + bcis->ushort_at_put(chunk_count, bci); methods->obj_at_put(chunk_count, st.method()); chunk_count++; From 77ad1e47c155b72d31681bbd056c701f40081622 Mon Sep 17 00:00:00 2001 From: Mark Reinhold Date: Mon, 23 Jan 2012 12:39:41 -0800 Subject: [PATCH 70/96] 7110396: Sound code fails to build with gcc 4.6 on multiarch Linux systems Reviewed-by: ohair --- jdk/make/javax/sound/jsoundalsa/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/make/javax/sound/jsoundalsa/Makefile b/jdk/make/javax/sound/jsoundalsa/Makefile index 11b4987dc88..5fa0124cc68 100644 --- a/jdk/make/javax/sound/jsoundalsa/Makefile +++ b/jdk/make/javax/sound/jsoundalsa/Makefile @@ -65,7 +65,7 @@ FILES_export = \ $(MIDIFILES_export) \ $(PORTFILES_export) -LDFLAGS += -lasound +OTHER_LDLIBS += -lasound CPPFLAGS += \ -DUSE_DAUDIO=TRUE \ From 3f08a21500523129180b9d045f0c21cde42457a4 Mon Sep 17 00:00:00 2001 From: Bertrand Delsart Date: Tue, 24 Jan 2012 15:41:17 +0100 Subject: [PATCH 71/96] 7120450: complete information dumped by frame_describe Improvements of frame_describe Reviewed-by: never, twisti --- hotspot/src/cpu/sparc/vm/frame_sparc.cpp | 13 ++++-- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 20 ++++++++- .../src/cpu/sparc/vm/methodHandles_sparc.hpp | 4 +- hotspot/src/cpu/x86/vm/frame_x86.cpp | 5 ++- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 22 +++++++++- hotspot/src/cpu/x86/vm/methodHandles_x86.hpp | 4 +- hotspot/src/share/vm/runtime/frame.cpp | 43 +++++++++++++++---- 7 files changed, 93 insertions(+), 18 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp index 83fd37182ca..fdcfffef804 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -820,11 +820,19 @@ void frame::describe_pd(FrameValues& values, int frame_no) { values.describe(frame_no, sp() + w, err_msg("register save area word %d", w), 1); } - if (is_interpreted_frame()) { + if (is_ricochet_frame()) { + MethodHandles::RicochetFrame::describe(this, values, frame_no); + } else if (is_interpreted_frame()) { DESCRIBE_FP_OFFSET(interpreter_frame_d_scratch_fp); DESCRIBE_FP_OFFSET(interpreter_frame_l_scratch_fp); DESCRIBE_FP_OFFSET(interpreter_frame_padding); DESCRIBE_FP_OFFSET(interpreter_frame_oop_temp); + + // esp, according to Lesp (e.g. not depending on bci), if seems valid + intptr_t* esp = *interpreter_frame_esp_addr(); + if ((esp >= sp()) && (esp < fp())) { + values.describe(-1, esp, "*Lesp"); + } } if (!is_compiled_frame()) { @@ -844,4 +852,3 @@ intptr_t *frame::initial_deoptimization_info() { // unused... but returns fp() to minimize changes introduced by 7087445 return fp(); } - diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index 1627685dad7..96b8ff8594d 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1000,6 +1000,24 @@ void MethodHandles::move_return_value(MacroAssembler* _masm, BasicType type, BLOCK_COMMENT("} move_return_value"); } +#ifdef ASSERT +void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) { + RicochetFrame* rf = new RicochetFrame(*fr); + + // ricochet slots (kept in registers for sparc) + values.describe(frame_no, rf->register_addr(I5_savedSP), err_msg("exact_sender_sp reg for #%d", frame_no)); + values.describe(frame_no, rf->register_addr(L5_conversion), err_msg("conversion reg for #%d", frame_no)); + values.describe(frame_no, rf->register_addr(L4_saved_args_base), err_msg("saved_args_base reg for #%d", frame_no)); + values.describe(frame_no, rf->register_addr(L3_saved_args_layout), err_msg("saved_args_layout reg for #%d", frame_no)); + values.describe(frame_no, rf->register_addr(L2_saved_target), err_msg("saved_target reg for #%d", frame_no)); + values.describe(frame_no, rf->register_addr(L1_continuation), err_msg("continuation reg for #%d", frame_no)); + + // relevant ricochet targets (in caller frame) + values.describe(-1, rf->saved_args_base(), err_msg("*saved_args_base for #%d", frame_no)); + values.describe(-1, (intptr_t *)(STACK_BIAS+(uintptr_t)rf->exact_sender_sp()), err_msg("*exact_sender_sp+STACK_BIAS for #%d", frame_no)); +} +#endif // ASSERT + #ifndef PRODUCT extern "C" void print_method_handle(oop mh); void trace_method_handle_stub(const char* adaptername, diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp index 0c285100254..2c3d810b813 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,6 +145,8 @@ class RicochetFrame : public ResourceObj { } static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN; + + static void describe(const frame* fr, FrameValues& values, int frame_no) NOT_DEBUG_RETURN; }; // Additional helper methods for MethodHandles code generation: diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp index 94166ea0fef..4051cdf59ce 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp @@ -657,7 +657,9 @@ intptr_t* frame::interpreter_frame_tos_at(jint offset) const { values.describe(frame_no, fp() + frame::name##_offset, #name) void frame::describe_pd(FrameValues& values, int frame_no) { - if (is_interpreted_frame()) { + if (is_ricochet_frame()) { + MethodHandles::RicochetFrame::describe(this, values, frame_no); + } else if (is_interpreted_frame()) { DESCRIBE_FP_OFFSET(interpreter_frame_sender_sp); DESCRIBE_FP_OFFSET(interpreter_frame_last_sp); DESCRIBE_FP_OFFSET(interpreter_frame_method); @@ -667,7 +669,6 @@ void frame::describe_pd(FrameValues& values, int frame_no) { DESCRIBE_FP_OFFSET(interpreter_frame_bcx); DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp); } - } #endif diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index acd65fb9463..38694718b7a 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -990,6 +990,26 @@ void MethodHandles::move_return_value(MacroAssembler* _masm, BasicType type, BLOCK_COMMENT("} move_return_value"); } +#ifdef ASSERT +#define DESCRIBE_RICOCHET_OFFSET(rf, name) \ + values.describe(frame_no, (intptr_t *) (((uintptr_t)rf) + MethodHandles::RicochetFrame::name##_offset_in_bytes()), #name) + +void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) { + address bp = (address) fr->fp(); + RicochetFrame* rf = (RicochetFrame*)(bp - sender_link_offset_in_bytes()); + + // ricochet slots + DESCRIBE_RICOCHET_OFFSET(rf, exact_sender_sp); + DESCRIBE_RICOCHET_OFFSET(rf, conversion); + DESCRIBE_RICOCHET_OFFSET(rf, saved_args_base); + DESCRIBE_RICOCHET_OFFSET(rf, saved_args_layout); + DESCRIBE_RICOCHET_OFFSET(rf, saved_target); + DESCRIBE_RICOCHET_OFFSET(rf, continuation); + + // relevant ricochet targets (in caller frame) + values.describe(-1, rf->saved_args_base(), err_msg("*saved_args_base for #%d", frame_no)); +} +#endif // ASSERT #ifndef PRODUCT extern "C" void print_method_handle(oop mh); diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp index 4cb6662abf3..9f8e1a56035 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -224,6 +224,8 @@ class RicochetFrame { } static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN; + + static void describe(const frame* fr, FrameValues& values, int frame_no) NOT_DEBUG_RETURN; }; // Additional helper methods for MethodHandles code generation: diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 7f4a2ac6558..897c7276e5d 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -1334,21 +1334,31 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const { void frame::describe(FrameValues& values, int frame_no) { - intptr_t* frame_pointer = real_fp(); + // boundaries: sp and the 'real' frame pointer + values.describe(-1, sp(), err_msg("sp for #%d", frame_no), 1); + intptr_t* frame_pointer = real_fp(); // Note: may differ from fp() + + // print frame info at the highest boundary + intptr_t* info_address = MAX2(sp(), frame_pointer); + + if (info_address != frame_pointer) { + // print frame_pointer explicitly if not marked by the frame info + values.describe(-1, frame_pointer, err_msg("frame pointer for #%d", frame_no), 1); + } + if (is_entry_frame() || is_compiled_frame() || is_interpreted_frame() || is_native_frame()) { // Label values common to most frames values.describe(-1, unextended_sp(), err_msg("unextended_sp for #%d", frame_no)); - values.describe(-1, sp(), err_msg("sp for #%d", frame_no)); - values.describe(-1, frame_pointer, err_msg("frame pointer for #%d", frame_no)); } + if (is_interpreted_frame()) { methodOop m = interpreter_frame_method(); int bci = interpreter_frame_bci(); // Label the method and current bci - values.describe(-1, MAX2(sp(), frame_pointer), + values.describe(-1, info_address, FormatBuffer<1024>("#%d method %s @ %d", frame_no, m->name_and_sig_as_C_string(), bci), 2); - values.describe(-1, MAX2(sp(), frame_pointer), + values.describe(-1, info_address, err_msg("- %d locals %d max stack", m->max_locals(), m->max_stack()), 1); if (m->max_locals() > 0) { intptr_t* l0 = interpreter_frame_local_at(0); @@ -1380,21 +1390,36 @@ void frame::describe(FrameValues& values, int frame_no) { } } else if (is_entry_frame()) { // For now just label the frame - values.describe(-1, MAX2(sp(), frame_pointer), err_msg("#%d entry frame", frame_no), 2); + values.describe(-1, info_address, err_msg("#%d entry frame", frame_no), 2); } else if (is_compiled_frame()) { // For now just label the frame nmethod* nm = cb()->as_nmethod_or_null(); - values.describe(-1, MAX2(sp(), frame_pointer), + values.describe(-1, info_address, FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method %s%s", frame_no, nm, nm->method()->name_and_sig_as_C_string(), - is_deoptimized_frame() ? " (deoptimized" : ""), 2); + (_deopt_state == is_deoptimized) ? + " (deoptimized)" : + ((_deopt_state == unknown) ? " (state unknown)" : "")), + 2); } else if (is_native_frame()) { // For now just label the frame nmethod* nm = cb()->as_nmethod_or_null(); - values.describe(-1, MAX2(sp(), frame_pointer), + values.describe(-1, info_address, FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for native method %s", frame_no, nm, nm->method()->name_and_sig_as_C_string()), 2); + } else if (is_ricochet_frame()) { + values.describe(-1, info_address, err_msg("#%d ricochet frame", frame_no), 2); + } else { + // provide default info if not handled before + char *info = (char *) "special frame"; + if ((_cb != NULL) && + (_cb->name() != NULL)) { + info = (char *)_cb->name(); + } + values.describe(-1, info_address, err_msg("#%d <%s>", frame_no, info), 2); } + + // platform dependent additional data describe_pd(values, frame_no); } From cba74d62085dc39035238bbca1edcd03d744501c Mon Sep 17 00:00:00 2001 From: James Melvin Date: Tue, 24 Jan 2012 14:07:03 -0500 Subject: [PATCH 72/96] 7126732: MAC: Require Mac OS X builds/tests for JPRT integrate jobs for HotSpot Modify jprt.properties to run OSX builds and tests. Reviewed-by: dcubed, kamg, ohair, dholmes --- hotspot/make/jprt.properties | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index aac31d0dbb2..3185f2d5ffb 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -174,6 +174,10 @@ jprt.my.linux.armsflt.ejdk6=linux_armsflt_2.6 jprt.my.linux.armsflt.ejdk7=linux_armsflt_2.6 jprt.my.linux.armsflt=${jprt.my.linux.armsflt.${jprt.tools.default.release}} +jprt.my.macosx.x64.jdk8=macosx_x64_10.7 +jprt.my.macosx.x64.jdk7=macosx_x64_10.7 +jprt.my.macosx.x64=${jprt.my.macosx.x64.${jprt.tools.default.release}} + jprt.my.windows.i586.jdk8=windows_i586_5.1 jprt.my.windows.i586.jdk7=windows_i586_5.1 jprt.my.windows.i586.jdk7b107=windows_i586_5.0 @@ -211,6 +215,7 @@ jprt.build.targets.standard= \ ${jprt.my.solaris.x64}-{product|fastdebug|debug}, \ ${jprt.my.linux.i586}-{product|fastdebug|debug}, \ ${jprt.my.linux.x64}-{product|fastdebug}, \ + ${jprt.my.macosx.x64}-{product|fastdebug|debug}, \ ${jprt.my.windows.i586}-{product|fastdebug|debug}, \ ${jprt.my.windows.x64}-{product|fastdebug|debug} @@ -416,6 +421,30 @@ jprt.my.linux.x64.test.targets = \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_G1, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParOldGC +jprt.my.macosx.x64.test.targets = \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jvm98, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jvm98_nontiered, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-scimark, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_default, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_CMS, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_G1, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_default, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_CMS, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_G1, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_ParOldGC \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_default, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_default_tiered, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_G1, \ + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_ParOldGC + jprt.my.windows.i586.test.targets = \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.windows.i586}-{product|fastdebug}-c2-jvm98_nontiered, \ @@ -492,6 +521,7 @@ jprt.test.targets.standard = \ ${jprt.my.solaris.x64.test.targets}, \ ${jprt.my.linux.i586.test.targets}, \ ${jprt.my.linux.x64.test.targets}, \ + ${jprt.my.macosx.x64.test.targets}, \ ${jprt.my.windows.i586.test.targets}, \ ${jprt.my.windows.x64.test.targets}, \ ${jprt.test.targets.open} @@ -538,6 +568,7 @@ jprt.make.rule.test.targets.standard.server = \ ${jprt.my.solaris.x64}-*-c2-servertest, \ ${jprt.my.linux.i586}-*-c2-servertest, \ ${jprt.my.linux.x64}-*-c2-servertest, \ + ${jprt.my.macosx.x64}-*-c2-servertest, \ ${jprt.my.windows.i586}-*-c2-servertest, \ ${jprt.my.windows.x64}-*-c2-servertest @@ -548,6 +579,7 @@ jprt.make.rule.test.targets.standard.internalvmtests = \ ${jprt.my.solaris.x64}-fastdebug-c2-internalvmtests, \ ${jprt.my.linux.i586}-fastdebug-c2-internalvmtests, \ ${jprt.my.linux.x64}-fastdebug-c2-internalvmtests, \ + ${jprt.my.macosx.x64}-fastdebug-c2-internalvmtests, \ ${jprt.my.windows.i586}-fastdebug-c2-internalvmtests, \ ${jprt.my.windows.x64}-fastdebug-c2-internalvmtests From 501bad4fd6f4039063c7b73da8b52ee7bb262ff3 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Wed, 25 Jan 2012 02:29:05 +0400 Subject: [PATCH 73/96] 7066129: GarbageCollectorMXBean#getLastGcInfo leaks native memory Make GCStatInfo a resource object Reviewed-by: phh, coleenp --- hotspot/src/share/vm/services/gcNotifier.cpp | 3 ++- hotspot/src/share/vm/services/management.cpp | 16 ++++++++-------- hotspot/src/share/vm/services/memoryManager.cpp | 4 ++-- hotspot/src/share/vm/services/memoryManager.hpp | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/services/gcNotifier.cpp b/hotspot/src/share/vm/services/gcNotifier.cpp index f74692033ff..b282980e0ae 100644 --- a/hotspot/src/share/vm/services/gcNotifier.cpp +++ b/hotspot/src/share/vm/services/gcNotifier.cpp @@ -44,7 +44,8 @@ void GCNotifier::pushNotification(GCMemoryManager *mgr, const char *action, cons // Make a copy of the last GC statistics // GC may occur between now and the creation of the notification int num_pools = MemoryService::num_memory_pools(); - GCStatInfo* stat = new GCStatInfo(num_pools); + // stat is deallocated inside GCNotificationRequest + GCStatInfo* stat = new(ResourceObj::C_HEAP) GCStatInfo(num_pools); mgr->get_last_gc_stat(stat); GCNotificationRequest *request = new GCNotificationRequest(os::javaTimeMillis(),mgr,action,cause,stat); addRequest(request); diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp index 680c5d389fc..5decfaa9994 100644 --- a/hotspot/src/share/vm/services/management.cpp +++ b/hotspot/src/share/vm/services/management.cpp @@ -2047,15 +2047,15 @@ JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat)) // Make a copy of the last GC statistics // GC may occur while constructing the last GC information int num_pools = MemoryService::num_memory_pools(); - GCStatInfo* stat = new GCStatInfo(num_pools); - if (mgr->get_last_gc_stat(stat) == 0) { + GCStatInfo stat(num_pools); + if (mgr->get_last_gc_stat(&stat) == 0) { gc_stat->gc_index = 0; return; } - gc_stat->gc_index = stat->gc_index(); - gc_stat->start_time = Management::ticks_to_ms(stat->start_time()); - gc_stat->end_time = Management::ticks_to_ms(stat->end_time()); + gc_stat->gc_index = stat.gc_index(); + gc_stat->start_time = Management::ticks_to_ms(stat.start_time()); + gc_stat->end_time = Management::ticks_to_ms(stat.end_time()); // Current implementation does not have GC extension attributes gc_stat->num_gc_ext_attributes = 0; @@ -2073,17 +2073,17 @@ JVM_ENTRY(void, jmm_GetLastGCStat(JNIEnv *env, jobject obj, jmmGCStat *gc_stat)) objArrayHandle usage_after_gc_ah(THREAD, au); for (int i = 0; i < num_pools; i++) { - Handle before_usage = MemoryService::create_MemoryUsage_obj(stat->before_gc_usage_for_pool(i), CHECK); + Handle before_usage = MemoryService::create_MemoryUsage_obj(stat.before_gc_usage_for_pool(i), CHECK); Handle after_usage; - MemoryUsage u = stat->after_gc_usage_for_pool(i); + MemoryUsage u = stat.after_gc_usage_for_pool(i); if (u.max_size() == 0 && u.used() > 0) { // If max size == 0, this pool is a survivor space. // Set max size = -1 since the pools will be swapped after GC. MemoryUsage usage(u.init_size(), u.used(), u.committed(), (size_t)-1); after_usage = MemoryService::create_MemoryUsage_obj(usage, CHECK); } else { - after_usage = MemoryService::create_MemoryUsage_obj(stat->after_gc_usage_for_pool(i), CHECK); + after_usage = MemoryService::create_MemoryUsage_obj(stat.after_gc_usage_for_pool(i), CHECK); } usage_before_gc_ah->obj_at_put(i, before_usage()); usage_after_gc_ah->obj_at_put(i, after_usage()); diff --git a/hotspot/src/share/vm/services/memoryManager.cpp b/hotspot/src/share/vm/services/memoryManager.cpp index 418716460f6..0666223bed5 100644 --- a/hotspot/src/share/vm/services/memoryManager.cpp +++ b/hotspot/src/share/vm/services/memoryManager.cpp @@ -214,8 +214,8 @@ GCMemoryManager::~GCMemoryManager() { void GCMemoryManager::initialize_gc_stat_info() { assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools"); - _last_gc_stat = new GCStatInfo(MemoryService::num_memory_pools()); - _current_gc_stat = new GCStatInfo(MemoryService::num_memory_pools()); + _last_gc_stat = new(ResourceObj::C_HEAP) GCStatInfo(MemoryService::num_memory_pools()); + _current_gc_stat = new(ResourceObj::C_HEAP) GCStatInfo(MemoryService::num_memory_pools()); // tracking concurrent collections we need two objects: one to update, and one to // hold the publicly available "last (completed) gc" information. } diff --git a/hotspot/src/share/vm/services/memoryManager.hpp b/hotspot/src/share/vm/services/memoryManager.hpp index cd4d953bfe2..eb0d9699c1f 100644 --- a/hotspot/src/share/vm/services/memoryManager.hpp +++ b/hotspot/src/share/vm/services/memoryManager.hpp @@ -108,7 +108,7 @@ public: const char* name() { return "CodeCacheManager"; } }; -class GCStatInfo : public CHeapObj { +class GCStatInfo : public ResourceObj { private: size_t _index; jlong _start_time; From ccf7d491f7fe45edb67650e479a04f5ee1c203a1 Mon Sep 17 00:00:00 2001 From: James Melvin Date: Tue, 24 Jan 2012 19:33:14 -0500 Subject: [PATCH 74/96] 7125793: MAC: test_gamma should always work Fix gamma launcher on Mac OS X and reconcile test_gamma script on Unix platforms Reviewed-by: dcubed, ohair, jcoomes, dholmes, ksrini --- hotspot/make/bsd/Makefile | 2 +- hotspot/make/bsd/makefiles/buildtree.make | 98 +++++++++++++------ hotspot/make/bsd/makefiles/defs.make | 2 +- hotspot/make/bsd/makefiles/launcher.make | 19 +++- hotspot/make/bsd/makefiles/vm.make | 4 +- hotspot/make/linux/makefiles/buildtree.make | 82 +++++++++++++--- hotspot/make/solaris/makefiles/buildtree.make | 90 ++++++++++++++--- hotspot/src/os/bsd/vm/os_bsd.cpp | 45 ++++++--- hotspot/src/os/posix/launcher/java_md.c | 10 +- 9 files changed, 278 insertions(+), 74 deletions(-) diff --git a/hotspot/make/bsd/Makefile b/hotspot/make/bsd/Makefile index cef9d7c9177..9660f4abcec 100644 --- a/hotspot/make/bsd/Makefile +++ b/hotspot/make/bsd/Makefile @@ -208,7 +208,7 @@ TARGETS_ZERO = $(addsuffix zero,$(TARGETS)) TARGETS_SHARK = $(addsuffix shark,$(TARGETS)) BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make -BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) +BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) LIBRARY_SUFFIX=$(LIBRARY_SUFFIX) BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) BUILDTREE = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS) diff --git a/hotspot/make/bsd/makefiles/buildtree.make b/hotspot/make/bsd/makefiles/buildtree.make index 4d7c25ac0cb..960a382bb11 100644 --- a/hotspot/make/bsd/makefiles/buildtree.make +++ b/hotspot/make/bsd/makefiles/buildtree.make @@ -162,20 +162,6 @@ ifndef HOTSPOT_VM_DISTRO endif endif -ifeq ($(OS_VENDOR), Darwin) - # MACOSX FIXME: we should be able to run test_gamma (see MACOSX_PORT-214) - ifeq ($(ALWAYS_PASS_TEST_GAMMA),) - # ALWAYS_PASS_TEST_GAMMA wasn't set so we default to true on MacOS X - # until MACOSX_PORT-214 is fixed - ALWAYS_PASS_TEST_GAMMA=true - endif -endif -ifeq ($(ALWAYS_PASS_TEST_GAMMA), true) - TEST_GAMMA_STATUS= echo 'exit 0'; -else - TEST_GAMMA_STATUS= -endif - BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HS_BUILD_VER) HOTSPOT_BUILD_VERSION= JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) BUILDTREE = \ @@ -353,12 +339,10 @@ env.sh: $(BUILDTREE_MAKE) $(BUILDTREE_COMMENT); \ [ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \ { \ - echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ - echo "DYLD_LIBRARY_PATH=.:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \ echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \ - echo "export JAVA_HOME LD_LIBRARY_PATH DYLD_LIBRARY_PATH CLASSPATH HOTSPOT_BUILD_USER"; \ + echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \ ) > $@ env.csh: env.sh @@ -412,7 +396,7 @@ JAVA_FLAG/32 = -d32 JAVA_FLAG/64 = -d64 WRONG_DATA_MODE_MSG = \ - echo "JAVA_HOME must point to $(DATA_MODE)bit JDK." + echo "JAVA_HOME must point to a $(DATA_MODE)-bit OpenJDK." CROSS_COMPILING_MSG = \ echo "Cross compiling for ARCH $(CROSS_COMPILE_ARCH), skipping gamma run." @@ -420,20 +404,78 @@ CROSS_COMPILING_MSG = \ test_gamma: $(BUILDTREE_MAKE) $(GAMMADIR)/make/test/Queens.java @echo Creating $@ ... $(QUIETLY) ( \ - echo '#!/bin/sh'; \ + echo "#!/bin/sh"; \ + echo ""; \ $(BUILDTREE_COMMENT); \ - echo '. ./env.sh'; \ - echo "if [ \"$(CROSS_COMPILE_ARCH)\" != \"\" ]; then { $(CROSS_COMPILING_MSG); exit 0; }; fi"; \ - echo "if [ -z \$$JAVA_HOME ]; then { $(NO_JAVA_HOME_MSG); exit 0; }; fi"; \ - echo "if ! \$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion 2>&1 > /dev/null"; \ - echo "then"; \ - echo " $(WRONG_DATA_MODE_MSG); exit 0;"; \ + echo ""; \ + echo "# Include environment settings for gamma run"; \ + echo ""; \ + echo ". ./env.sh"; \ + echo ""; \ + echo "# Do not run gamma test for cross compiles"; \ + echo ""; \ + echo "if [ -n \"$(CROSS_COMPILE_ARCH)\" ]; then "; \ + echo " $(CROSS_COMPILING_MSG)"; \ + echo " exit 0"; \ echo "fi"; \ + echo ""; \ + echo "# Make sure JAVA_HOME is set as it is required for gamma"; \ + echo ""; \ + echo "if [ -z \"\$${JAVA_HOME}\" ]; then "; \ + echo " $(NO_JAVA_HOME_MSG)"; \ + echo " exit 0"; \ + echo "fi"; \ + echo ""; \ + echo "# Check JAVA_HOME version to be used for the test"; \ + echo ""; \ + echo "\$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion > /dev/null 2>&1"; \ + echo "if [ \$$? -ne 0 ]; then "; \ + echo " $(WRONG_DATA_MODE_MSG)"; \ + echo " exit 0"; \ + echo "fi"; \ + echo ""; \ + echo "# Use gamma_g if it exists"; \ + echo ""; \ + echo "GAMMA_PROG=gamma"; \ + echo "if [ -f gamma_g ]; then "; \ + echo " GAMMA_PROG=gamma_g"; \ + echo "fi"; \ + echo ""; \ + echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \ + echo " # Ensure architecture for gamma and JAVA_HOME is the same."; \ + echo " # NOTE: gamma assumes the OpenJDK directory layout."; \ + echo ""; \ + echo " GAMMA_ARCH=\"\`file \$${GAMMA_PROG} | awk '{print \$$NF}'\`\""; \ + echo " JVM_LIB=\"\$${JAVA_HOME}/jre/lib/libjava.$(LIBRARY_SUFFIX)\""; \ + echo " if [ ! -f \$${JVM_LIB} ]; then"; \ + echo " JVM_LIB=\"\$${JAVA_HOME}/jre/lib/$${LIBARCH}/libjava.$(LIBRARY_SUFFIX)\""; \ + echo " fi"; \ + echo " if [ ! -f \$${JVM_LIB} ] || [ -z \"\`file \$${JVM_LIB} | grep \$${GAMMA_ARCH}\`\" ]; then "; \ + echo " $(WRONG_DATA_MODE_MSG)"; \ + echo " exit 0"; \ + echo " fi"; \ + echo "fi"; \ + echo ""; \ + echo "# Compile Queens program for test"; \ + echo ""; \ echo "rm -f Queens.class"; \ echo "\$${JAVA_HOME}/bin/javac -d . $(GAMMADIR)/make/test/Queens.java"; \ - echo '[ -f gamma_g ] && { gamma=gamma_g; }'; \ - echo './$${gamma:-gamma} $(TESTFLAGS) Queens < /dev/null'; \ - $(TEST_GAMMA_STATUS) \ + echo ""; \ + echo "# Set library path solely for gamma launcher test run"; \ + echo ""; \ + echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ + echo "export LD_LIBRARY_PATH"; \ + echo "unset LD_LIBRARY_PATH_32"; \ + echo "unset LD_LIBRARY_PATH_64"; \ + echo ""; \ + echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \ + echo " DYLD_LIBRARY_PATH=.:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/native_threads:\$${JAVA_HOME}/jre/lib:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ + echo " export DYLD_LIBRARY_PATH"; \ + echo "fi"; \ + echo ""; \ + echo "# Use the gamma launcher and JAVA_HOME to run the test"; \ + echo ""; \ + echo "./\$${GAMMA_PROG} $(TESTFLAGS) Queens < /dev/null"; \ ) > $@ $(QUIETLY) chmod +x $@ diff --git a/hotspot/make/bsd/makefiles/defs.make b/hotspot/make/bsd/makefiles/defs.make index 040cd7b21c5..2b160fefc45 100644 --- a/hotspot/make/bsd/makefiles/defs.make +++ b/hotspot/make/bsd/makefiles/defs.make @@ -142,6 +142,7 @@ EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html # client and server subdirectories have symbolic links to ../libjsig.so EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX) EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server +EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client ifndef BUILD_CLIENT_ONLY EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt @@ -150,7 +151,6 @@ endif ifneq ($(ZERO_BUILD), true) ifeq ($(ARCH_DATA_MODEL), 32) - EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX) endif diff --git a/hotspot/make/bsd/makefiles/launcher.make b/hotspot/make/bsd/makefiles/launcher.make index b405fbc7fca..d7218e57888 100644 --- a/hotspot/make/bsd/makefiles/launcher.make +++ b/hotspot/make/bsd/makefiles/launcher.make @@ -50,7 +50,24 @@ ifeq ($(LINK_INTO),AOUT) LIBS_LAUNCHER += $(STATIC_STDCXX) $(LIBS) else LAUNCHER.o = launcher.o - LFLAGS_LAUNCHER += -L`pwd` + LFLAGS_LAUNCHER += -L`pwd` + + # The gamma launcher runs the JDK from $JAVA_HOME, overriding the JVM with a + # freshly built JVM at ./libjvm.{so|dylib}. This is accomplished by setting + # the library searchpath using ({DY}LD_LIBRARY_PATH) to find the local JVM + # first. Gamma dlopen()s libjava from $JAVA_HOME/jre/lib{/$arch}, which is + # statically linked with CoreFoundation framework libs. Unfortunately, gamma's + # unique searchpath results in some unresolved symbols in the framework + # libraries, because JDK libraries are inadvertently discovered first on the + # searchpath, e.g. libjpeg. On Mac OS X, filenames are case *insensitive*. + # So, the actual filename collision is libjpeg.dylib and libJPEG.dylib. + # To resolve this, gamma needs to also statically link with the CoreFoundation + # framework libraries. + + ifeq ($(OS_VENDOR),Darwin) + LFLAGS_LAUNCHER += -framework CoreFoundation + endif + LIBS_LAUNCHER += -l$(JVM) $(LIBS) endif diff --git a/hotspot/make/bsd/makefiles/vm.make b/hotspot/make/bsd/makefiles/vm.make index 0fad0639727..fa6e5e4ec18 100644 --- a/hotspot/make/bsd/makefiles/vm.make +++ b/hotspot/make/bsd/makefiles/vm.make @@ -337,8 +337,8 @@ ifeq ($(OS_VENDOR), Darwin) $(LIBJVM).dSYM: $(LIBJVM) dsymutil $(LIBJVM) -# no launcher or libjvm_db for macosx -build: $(LIBJVM) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM +# no libjvm_db for macosx +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM echo "Doing vm.make build:" else build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) diff --git a/hotspot/make/linux/makefiles/buildtree.make b/hotspot/make/linux/makefiles/buildtree.make index b1eb00bb98c..5bc29368e5e 100644 --- a/hotspot/make/linux/makefiles/buildtree.make +++ b/hotspot/make/linux/makefiles/buildtree.make @@ -326,11 +326,10 @@ env.sh: $(BUILDTREE_MAKE) $(BUILDTREE_COMMENT); \ [ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \ { \ - echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \ echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \ - echo "export JAVA_HOME LD_LIBRARY_PATH CLASSPATH HOTSPOT_BUILD_USER"; \ + echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \ ) > $@ env.csh: env.sh @@ -384,7 +383,7 @@ JAVA_FLAG/32 = -d32 JAVA_FLAG/64 = -d64 WRONG_DATA_MODE_MSG = \ - echo "JAVA_HOME must point to $(DATA_MODE)bit JDK." + echo "JAVA_HOME must point to a $(DATA_MODE)-bit OpenJDK." CROSS_COMPILING_MSG = \ echo "Cross compiling for ARCH $(CROSS_COMPILE_ARCH), skipping gamma run." @@ -392,19 +391,78 @@ CROSS_COMPILING_MSG = \ test_gamma: $(BUILDTREE_MAKE) $(GAMMADIR)/make/test/Queens.java @echo Creating $@ ... $(QUIETLY) ( \ - echo '#!/bin/sh'; \ + echo "#!/bin/sh"; \ + echo ""; \ $(BUILDTREE_COMMENT); \ - echo '. ./env.sh'; \ - echo "if [ \"$(CROSS_COMPILE_ARCH)\" != \"\" ]; then { $(CROSS_COMPILING_MSG); exit 0; }; fi"; \ - echo "if [ -z \$$JAVA_HOME ]; then { $(NO_JAVA_HOME_MSG); exit 0; }; fi"; \ - echo "if ! \$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion 2>&1 > /dev/null"; \ - echo "then"; \ - echo " $(WRONG_DATA_MODE_MSG); exit 0;"; \ + echo ""; \ + echo "# Include environment settings for gamma run"; \ + echo ""; \ + echo ". ./env.sh"; \ + echo ""; \ + echo "# Do not run gamma test for cross compiles"; \ + echo ""; \ + echo "if [ -n \"$(CROSS_COMPILE_ARCH)\" ]; then "; \ + echo " $(CROSS_COMPILING_MSG)"; \ + echo " exit 0"; \ echo "fi"; \ + echo ""; \ + echo "# Make sure JAVA_HOME is set as it is required for gamma"; \ + echo ""; \ + echo "if [ -z \"\$${JAVA_HOME}\" ]; then "; \ + echo " $(NO_JAVA_HOME_MSG)"; \ + echo " exit 0"; \ + echo "fi"; \ + echo ""; \ + echo "# Check JAVA_HOME version to be used for the test"; \ + echo ""; \ + echo "\$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion > /dev/null 2>&1"; \ + echo "if [ \$$? -ne 0 ]; then "; \ + echo " $(WRONG_DATA_MODE_MSG)"; \ + echo " exit 0"; \ + echo "fi"; \ + echo ""; \ + echo "# Use gamma_g if it exists"; \ + echo ""; \ + echo "GAMMA_PROG=gamma"; \ + echo "if [ -f gamma_g ]; then "; \ + echo " GAMMA_PROG=gamma_g"; \ + echo "fi"; \ + echo ""; \ + echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \ + echo " # Ensure architecture for gamma and JAVA_HOME is the same."; \ + echo " # NOTE: gamma assumes the OpenJDK directory layout."; \ + echo ""; \ + echo " GAMMA_ARCH=\"\`file \$${GAMMA_PROG} | awk '{print \$$NF}'\`\""; \ + echo " JVM_LIB=\"\$${JAVA_HOME}/jre/lib/libjava.$(LIBRARY_SUFFIX)\""; \ + echo " if [ ! -f \$${JVM_LIB} ]; then"; \ + echo " JVM_LIB=\"\$${JAVA_HOME}/jre/lib/$${LIBARCH}/libjava.$(LIBRARY_SUFFIX)\""; \ + echo " fi"; \ + echo " if [ ! -f \$${JVM_LIB} ] || [ -z \"\`file \$${JVM_LIB} | grep \$${GAMMA_ARCH}\`\" ]; then "; \ + echo " $(WRONG_DATA_MODE_MSG)"; \ + echo " exit 0"; \ + echo " fi"; \ + echo "fi"; \ + echo ""; \ + echo "# Compile Queens program for test"; \ + echo ""; \ echo "rm -f Queens.class"; \ echo "\$${JAVA_HOME}/bin/javac -d . $(GAMMADIR)/make/test/Queens.java"; \ - echo '[ -f gamma_g ] && { gamma=gamma_g; }'; \ - echo './$${gamma:-gamma} $(TESTFLAGS) Queens < /dev/null'; \ + echo ""; \ + echo "# Set library path solely for gamma launcher test run"; \ + echo ""; \ + echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ + echo "export LD_LIBRARY_PATH"; \ + echo "unset LD_LIBRARY_PATH_32"; \ + echo "unset LD_LIBRARY_PATH_64"; \ + echo ""; \ + echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \ + echo " DYLD_LIBRARY_PATH=.:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/native_threads:\$${JAVA_HOME}/jre/lib:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ + echo " export DYLD_LIBRARY_PATH"; \ + echo "fi"; \ + echo ""; \ + echo "# Use the gamma launcher and JAVA_HOME to run the test"; \ + echo ""; \ + echo "./\$${GAMMA_PROG} $(TESTFLAGS) Queens < /dev/null"; \ ) > $@ $(QUIETLY) chmod +x $@ diff --git a/hotspot/make/solaris/makefiles/buildtree.make b/hotspot/make/solaris/makefiles/buildtree.make index a46d6b3378f..129a4849431 100644 --- a/hotspot/make/solaris/makefiles/buildtree.make +++ b/hotspot/make/solaris/makefiles/buildtree.make @@ -118,7 +118,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \ - env.ksh env.csh jdkpath.sh .dbxrc test_gamma + env.sh env.csh jdkpath.sh .dbxrc test_gamma BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -313,22 +313,19 @@ sa.make: $(BUILDTREE_MAKE) echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ -env.ksh: $(BUILDTREE_MAKE) +env.sh: $(BUILDTREE_MAKE) @echo Creating $@ ... $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ [ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \ { \ - echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ - echo "unset LD_LIBRARY_PATH_32"; \ - echo "unset LD_LIBRARY_PATH_64"; \ echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \ echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \ echo "export JAVA_HOME LD_LIBRARY_PATH CLASSPATH HOTSPOT_BUILD_USER"; \ ) > $@ -env.csh: env.ksh +env.csh: env.sh @echo Creating $@ ... $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ @@ -384,23 +381,86 @@ JAVA_FLAG/32 = -d32 JAVA_FLAG/64 = -d64 WRONG_DATA_MODE_MSG = \ - echo "JAVA_HOME must point to $(DATA_MODE)bit JDK." + echo "JAVA_HOME must point to a $(DATA_MODE)-bit OpenJDK." + +CROSS_COMPILING_MSG = \ + echo "Cross compiling for ARCH $(CROSS_COMPILE_ARCH), skipping gamma run." test_gamma: $(BUILDTREE_MAKE) $(GAMMADIR)/make/test/Queens.java @echo Creating $@ ... $(QUIETLY) ( \ - echo '#!/bin/ksh'; \ + echo "#!/bin/sh"; \ + echo ""; \ $(BUILDTREE_COMMENT); \ - echo '. ./env.ksh'; \ - echo "if [ -z \$$JAVA_HOME ]; then { $(NO_JAVA_HOME_MSG); exit 0; }; fi"; \ - echo "if ! \$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion 2>&1 > /dev/null"; \ - echo "then"; \ - echo " $(WRONG_DATA_MODE_MSG); exit 0;"; \ + echo ""; \ + echo "# Include environment settings for gamma run"; \ + echo ""; \ + echo ". ./env.sh"; \ + echo ""; \ + echo "# Do not run gamma test for cross compiles"; \ + echo ""; \ + echo "if [ -n \"$(CROSS_COMPILE_ARCH)\" ]; then "; \ + echo " $(CROSS_COMPILING_MSG)"; \ + echo " exit 0"; \ echo "fi"; \ + echo ""; \ + echo "# Make sure JAVA_HOME is set as it is required for gamma"; \ + echo ""; \ + echo "if [ -z \"\$${JAVA_HOME}\" ]; then "; \ + echo " $(NO_JAVA_HOME_MSG)"; \ + echo " exit 0"; \ + echo "fi"; \ + echo ""; \ + echo "# Check JAVA_HOME version to be used for the test"; \ + echo ""; \ + echo "\$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion > /dev/null 2>&1"; \ + echo "if [ \$$? -ne 0 ]; then "; \ + echo " $(WRONG_DATA_MODE_MSG)"; \ + echo " exit 0"; \ + echo "fi"; \ + echo ""; \ + echo "# Use gamma_g if it exists"; \ + echo ""; \ + echo "GAMMA_PROG=gamma"; \ + echo "if [ -f gamma_g ]; then "; \ + echo " GAMMA_PROG=gamma_g"; \ + echo "fi"; \ + echo ""; \ + echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \ + echo " # Ensure architecture for gamma and JAVA_HOME is the same."; \ + echo " # NOTE: gamma assumes the OpenJDK directory layout."; \ + echo ""; \ + echo " GAMMA_ARCH=\"\`file \$${GAMMA_PROG} | awk '{print \$$NF}'\`\""; \ + echo " JVM_LIB=\"\$${JAVA_HOME}/jre/lib/libjava.$(LIBRARY_SUFFIX)\""; \ + echo " if [ ! -f \$${JVM_LIB} ]; then"; \ + echo " JVM_LIB=\"\$${JAVA_HOME}/jre/lib/$${LIBARCH}/libjava.$(LIBRARY_SUFFIX)\""; \ + echo " fi"; \ + echo " if [ ! -f \$${JVM_LIB} ] || [ -z \"\`file \$${JVM_LIB} | grep \$${GAMMA_ARCH}\`\" ]; then "; \ + echo " $(WRONG_DATA_MODE_MSG)"; \ + echo " exit 0"; \ + echo " fi"; \ + echo "fi"; \ + echo ""; \ + echo "# Compile Queens program for test"; \ + echo ""; \ echo "rm -f Queens.class"; \ echo "\$${JAVA_HOME}/bin/javac -d . $(GAMMADIR)/make/test/Queens.java"; \ - echo '[ -f gamma_g ] && { gamma=gamma_g; }'; \ - echo './$${gamma:-gamma} $(TESTFLAGS) Queens < /dev/null'; \ + echo ""; \ + echo "# Set library path solely for gamma launcher test run"; \ + echo ""; \ + echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ + echo "export LD_LIBRARY_PATH"; \ + echo "unset LD_LIBRARY_PATH_32"; \ + echo "unset LD_LIBRARY_PATH_64"; \ + echo ""; \ + echo "if [ \"$(OS_VENDOR)\" = \"Darwin\" ]; then "; \ + echo " DYLD_LIBRARY_PATH=.:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/native_threads:\$${JAVA_HOME}/jre/lib:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ + echo " export DYLD_LIBRARY_PATH"; \ + echo "fi"; \ + echo ""; \ + echo "# Use the gamma launcher and JAVA_HOME to run the test"; \ + echo ""; \ + echo "./\$${GAMMA_PROG} $(TESTFLAGS) Queens < /dev/null"; \ ) > $@ $(QUIETLY) chmod +x $@ diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 2526e65f229..d0603bb8e71 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -301,6 +301,12 @@ static char cpu_arch[] = "sparc"; #error Add appropriate cpu_arch setting #endif +// Compiler variant +#ifdef COMPILER2 +#define COMPILER_VARIANT "server" +#else +#define COMPILER_VARIANT "client" +#endif #ifndef _ALLBSD_SOURCE // pid_t gettid() @@ -2507,7 +2513,7 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { static char saved_jvm_path[MAXPATHLEN] = {0}; -// Find the full path to the current module, libjvm.so or libjvm_g.so +// Find the full path to the current module, libjvm or libjvm_g void os::jvm_path(char *buf, jint buflen) { // Error checking. if (buflen < MAXPATHLEN) { @@ -2532,11 +2538,11 @@ void os::jvm_path(char *buf, jint buflen) { if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Typical value for buf is - // "/jre/lib///libjvm.so". If "/jre/lib/" appears at + // "/jre/lib///libjvm". If "/jre/lib/" appears at // the right place in the string, then assume we are installed in a JDK and - // we're done. Otherwise, check for a JAVA_HOME environment variable and fix - // up the path so it looks like libjvm.so is installed there (append a - // fake suffix hotspot/libjvm.so). + // we're done. Otherwise, check for a JAVA_HOME environment variable and + // construct a path to the JVM being overridden. + const char *p = buf + strlen(buf) - 1; for (int count = 0; p > buf && count < 5; ++count) { for (--p; p > buf && *p != '/'; --p) @@ -2550,7 +2556,7 @@ void os::jvm_path(char *buf, jint buflen) { char* jrelib_p; int len; - // Check the current module name "libjvm.so" or "libjvm_g.so". + // Check the current module name "libjvm" or "libjvm_g". p = strrchr(buf, '/'); assert(strstr(p, "/libjvm") == p, "invalid library name"); p = strstr(p, "_g") ? "_g" : ""; @@ -2563,19 +2569,32 @@ void os::jvm_path(char *buf, jint buflen) { // modules image doesn't have "jre" subdirectory len = strlen(buf); jrelib_p = buf + len; - snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch); + + // Add the appropriate library subdir + snprintf(jrelib_p, buflen-len, "/jre/lib"); if (0 != access(buf, F_OK)) { - snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch); + snprintf(jrelib_p, buflen-len, "/lib"); } + // Add the appropriate client or server subdir + len = strlen(buf); + jrelib_p = buf + len; + snprintf(jrelib_p, buflen-len, "/%s", COMPILER_VARIANT); + if (0 != access(buf, F_OK)) { + snprintf(jrelib_p, buflen-len, ""); + } + + // If the path exists within JAVA_HOME, add the JVM library name + // to complete the path to JVM being overridden. Otherwise fallback + // to the path to the current library. if (0 == access(buf, F_OK)) { - // Use current module name "libjvm[_g].so" instead of - // "libjvm"debug_only("_g")".so" since for fastdebug version - // we should have "libjvm.so" but debug_only("_g") adds "_g"! + // Use current module name "libjvm[_g]" instead of + // "libjvm"debug_only("_g")"" since for fastdebug version + // we should have "libjvm" but debug_only("_g") adds "_g"! len = strlen(buf); - snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p); + snprintf(buf + len, buflen-len, "/libjvm%s%s", p, JNI_LIB_SUFFIX); } else { - // Go back to path of .so + // Fall back to path of current library rp = realpath(dli_fname, buf); if (rp == NULL) return; diff --git a/hotspot/src/os/posix/launcher/java_md.c b/hotspot/src/os/posix/launcher/java_md.c index 63cee98e3e1..8b1542e8d9e 100644 --- a/hotspot/src/os/posix/launcher/java_md.c +++ b/hotspot/src/os/posix/launcher/java_md.c @@ -701,6 +701,14 @@ GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative) char libjava[MAXPATHLEN]; if (GetApplicationHome(path, pathsize)) { + + /* Is the JRE universal, i.e. no arch dir? */ + sprintf(libjava, "%s/jre/lib/" JAVA_DLL, path); + if (access(libjava, F_OK) == 0) { + strcat(path, "/jre"); + goto found; + } + /* Is JRE co-located with the application? */ sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch); if (access(libjava, F_OK) == 0) { @@ -734,7 +742,7 @@ LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs; return JNI_TRUE; #else - Dl_info dlinfo; + Dl_info dlinfo; void *libjvm; if (_launcher_debug) { From 7f44e3513439fc26b9539143759d6859005bb41d Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Tue, 24 Jan 2012 17:00:51 -0800 Subject: [PATCH 75/96] 7132945: Tiered: adjust OSR threshold of level 3 Change the value of Tier3BackEdgeThreshold from 7000 to 60000 Reviewed-by: kvn, never --- hotspot/src/share/vm/runtime/globals.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 88e59385098..d7de26b5cd4 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3574,7 +3574,7 @@ class CommandLineFlags { "Threshold at which tier 3 compilation is invoked (invocation " \ "minimum must be satisfied.") \ \ - product(intx, Tier3BackEdgeThreshold, 7000, \ + product(intx, Tier3BackEdgeThreshold, 60000, \ "Back edge threshold at which tier 3 OSR compilation is invoked") \ \ product(intx, Tier4InvocationThreshold, 5000, \ From 3770ecec6fa0d5f0f90936ace6e1adaf576b2e57 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 24 Jan 2012 17:04:51 -0800 Subject: [PATCH 76/96] 7132936: guarantee(t != NULL) failed: must be con Use !higher_equal() check to skip top and values which fit. Reviewed-by: never --- hotspot/src/share/vm/opto/memnode.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index bf4189921eb..8c40e9c0fe2 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -1764,7 +1764,8 @@ Node *LoadBNode::Ideal(PhaseGVN *phase, bool can_reshape) { const Type* LoadBNode::Value(PhaseTransform *phase) const { Node* mem = in(MemNode::Memory); Node* value = can_see_stored_value(mem,phase); - if (value != NULL && value->is_Con()) { + if (value != NULL && value->is_Con() && + !value->bottom_type()->higher_equal(_type)) { // If the input to the store does not fit with the load's result type, // it must be truncated. We can't delay until Ideal call since // a singleton Value is needed for split_thru_phi optimization. @@ -1793,7 +1794,8 @@ Node* LoadUBNode::Ideal(PhaseGVN* phase, bool can_reshape) { const Type* LoadUBNode::Value(PhaseTransform *phase) const { Node* mem = in(MemNode::Memory); Node* value = can_see_stored_value(mem,phase); - if (value != NULL && value->is_Con()) { + if (value != NULL && value->is_Con() && + !value->bottom_type()->higher_equal(_type)) { // If the input to the store does not fit with the load's result type, // it must be truncated. We can't delay until Ideal call since // a singleton Value is needed for split_thru_phi optimization. @@ -1822,7 +1824,8 @@ Node *LoadUSNode::Ideal(PhaseGVN *phase, bool can_reshape) { const Type* LoadUSNode::Value(PhaseTransform *phase) const { Node* mem = in(MemNode::Memory); Node* value = can_see_stored_value(mem,phase); - if (value != NULL && value->is_Con()) { + if (value != NULL && value->is_Con() && + !value->bottom_type()->higher_equal(_type)) { // If the input to the store does not fit with the load's result type, // it must be truncated. We can't delay until Ideal call since // a singleton Value is needed for split_thru_phi optimization. @@ -1853,7 +1856,8 @@ Node *LoadSNode::Ideal(PhaseGVN *phase, bool can_reshape) { const Type* LoadSNode::Value(PhaseTransform *phase) const { Node* mem = in(MemNode::Memory); Node* value = can_see_stored_value(mem,phase); - if (value != NULL && value->is_Con()) { + if (value != NULL && value->is_Con() && + !value->bottom_type()->higher_equal(_type)) { // If the input to the store does not fit with the load's result type, // it must be truncated. We can't delay until Ideal call since // a singleton Value is needed for split_thru_phi optimization. From f3ce53be679821538b822d081c485c74e82f99a0 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 25 Jan 2012 09:31:47 +0100 Subject: [PATCH 77/96] 7116050: C2/ARM: memory stomping error with DivideMcTests Block::schedule_local() may write beyond end of ready_cnt array Reviewed-by: never, kvn --- hotspot/src/share/vm/opto/block.hpp | 6 ++--- hotspot/src/share/vm/opto/gcm.cpp | 4 +-- hotspot/src/share/vm/opto/lcm.cpp | 39 +++++++++++++++++------------ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index ef5c8d6e4ae..e3d8d3ef0f3 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -284,13 +284,13 @@ class Block : public CFGElement { // helper function that adds caller save registers to MachProjNode void add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe); // Schedule a call next in the block - uint sched_call(Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_List &worklist, int *ready_cnt, MachCallNode *mcall, VectorSet &next_call); + uint sched_call(Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_List &worklist, GrowableArray &ready_cnt, MachCallNode *mcall, VectorSet &next_call); // Perform basic-block local scheduling - Node *select(PhaseCFG *cfg, Node_List &worklist, int *ready_cnt, VectorSet &next_call, uint sched_slot); + Node *select(PhaseCFG *cfg, Node_List &worklist, GrowableArray &ready_cnt, VectorSet &next_call, uint sched_slot); void set_next_call( Node *n, VectorSet &next_call, Block_Array &bbs ); void needed_for_next_call(Node *this_call, VectorSet &next_call, Block_Array &bbs); - bool schedule_local(PhaseCFG *cfg, Matcher &m, int *ready_cnt, VectorSet &next_call); + bool schedule_local(PhaseCFG *cfg, Matcher &m, GrowableArray &ready_cnt, VectorSet &next_call); // Cleanup if any code lands between a Call and his Catch void call_catch_cleanup(Block_Array &bbs); // Detect implicit-null-check opportunities. Basically, find NULL checks diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index be6850ebe5f..8b8f3115729 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -1344,8 +1344,8 @@ void PhaseCFG::GlobalCodeMotion( Matcher &matcher, uint unique, Node_List &proj_ // Schedule locally. Right now a simple topological sort. // Later, do a real latency aware scheduler. - int *ready_cnt = NEW_RESOURCE_ARRAY(int,C->unique()); - memset( ready_cnt, -1, C->unique() * sizeof(int) ); + uint max_idx = C->unique(); + GrowableArray ready_cnt(max_idx, max_idx, -1); visited.Clear(); for (i = 0; i < _num_blocks; i++) { if (!_blocks[i]->schedule_local(this, matcher, ready_cnt, visited)) { diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 287b6ed0526..1ad9f0b1f0c 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -404,7 +404,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe // remaining cases (most), choose the instruction with the greatest latency // (that is, the most number of pseudo-cycles required to the end of the // routine). If there is a tie, choose the instruction with the most inputs. -Node *Block::select(PhaseCFG *cfg, Node_List &worklist, int *ready_cnt, VectorSet &next_call, uint sched_slot) { +Node *Block::select(PhaseCFG *cfg, Node_List &worklist, GrowableArray &ready_cnt, VectorSet &next_call, uint sched_slot) { // If only a single entry on the stack, use it uint cnt = worklist.size(); @@ -465,7 +465,7 @@ Node *Block::select(PhaseCFG *cfg, Node_List &worklist, int *ready_cnt, VectorSe // More than this instruction pending for successor to be ready, // don't choose this if other opportunities are ready - if (ready_cnt[use->_idx] > 1) + if (ready_cnt.at(use->_idx) > 1) n_choice = 1; } @@ -565,7 +565,7 @@ void Block::add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_p //------------------------------sched_call------------------------------------- -uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_List &worklist, int *ready_cnt, MachCallNode *mcall, VectorSet &next_call ) { +uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_List &worklist, GrowableArray &ready_cnt, MachCallNode *mcall, VectorSet &next_call ) { RegMask regs; // Schedule all the users of the call right now. All the users are @@ -574,8 +574,9 @@ uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_ for (DUIterator_Fast imax, i = mcall->fast_outs(imax); i < imax; i++) { Node* n = mcall->fast_out(i); assert( n->is_MachProj(), "" ); - --ready_cnt[n->_idx]; - assert( !ready_cnt[n->_idx], "" ); + int n_cnt = ready_cnt.at(n->_idx)-1; + ready_cnt.at_put(n->_idx, n_cnt); + assert( n_cnt == 0, "" ); // Schedule next to call _nodes.map(node_cnt++, n); // Collect defined registers @@ -590,7 +591,9 @@ uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_ Node* m = n->fast_out(j); // Get user if( bbs[m->_idx] != this ) continue; if( m->is_Phi() ) continue; - if( !--ready_cnt[m->_idx] ) + int m_cnt = ready_cnt.at(m->_idx)-1; + ready_cnt.at_put(m->_idx, m_cnt); + if( m_cnt == 0 ) worklist.push(m); } @@ -655,7 +658,7 @@ uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_ //------------------------------schedule_local--------------------------------- // Topological sort within a block. Someday become a real scheduler. -bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, VectorSet &next_call) { +bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray &ready_cnt, VectorSet &next_call) { // Already "sorted" are the block start Node (as the first entry), and // the block-ending Node and any trailing control projections. We leave // these alone. PhiNodes and ParmNodes are made to follow the block start @@ -695,7 +698,7 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect if( m && cfg->_bbs[m->_idx] == this && !m->is_top() ) local++; // One more block-local input } - ready_cnt[n->_idx] = local; // Count em up + ready_cnt.at_put(n->_idx, local); // Count em up #ifdef ASSERT if( UseConcMarkSweepGC || UseG1GC ) { @@ -729,7 +732,7 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect } } for(uint i2=i; i2<_nodes.size(); i2++ ) // Trailing guys get zapped count - ready_cnt[_nodes[i2]->_idx] = 0; + ready_cnt.at_put(_nodes[i2]->_idx, 0); // All the prescheduled guys do not hold back internal nodes uint i3; @@ -737,8 +740,10 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect Node *n = _nodes[i3]; // Get pre-scheduled for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { Node* m = n->fast_out(j); - if( cfg->_bbs[m->_idx] ==this ) // Local-block user - ready_cnt[m->_idx]--; // Fix ready count + if( cfg->_bbs[m->_idx] ==this ) { // Local-block user + int m_cnt = ready_cnt.at(m->_idx)-1; + ready_cnt.at_put(m->_idx, m_cnt); // Fix ready count + } } } @@ -747,7 +752,7 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect Node_List worklist; for(uint i4=i3; i4_idx] ) { // Zero ready count? + if( !ready_cnt.at(m->_idx) ) { // Zero ready count? if (m->is_iteratively_computed()) { // Push induction variable increments last to allow other uses // of the phi to be scheduled first. The select() method breaks @@ -775,14 +780,14 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect for (uint j=0; j<_nodes.size(); j++) { Node *n = _nodes[j]; int idx = n->_idx; - tty->print("# ready cnt:%3d ", ready_cnt[idx]); + tty->print("# ready cnt:%3d ", ready_cnt.at(idx)); tty->print("latency:%3d ", cfg->_node_latency->at_grow(idx)); tty->print("%4d: %s\n", idx, n->Name()); } } #endif - uint max_idx = matcher.C->unique(); + uint max_idx = (uint)ready_cnt.length(); // Pull from worklist and schedule while( worklist.size() ) { // Worklist is not ready @@ -840,11 +845,13 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect Node* m = n->fast_out(i5); // Get user if( cfg->_bbs[m->_idx] != this ) continue; if( m->is_Phi() ) continue; - if (m->_idx > max_idx) { // new node, skip it + if (m->_idx >= max_idx) { // new node, skip it assert(m->is_MachProj() && n->is_Mach() && n->as_Mach()->has_call(), "unexpected node types"); continue; } - if( !--ready_cnt[m->_idx] ) + int m_cnt = ready_cnt.at(m->_idx)-1; + ready_cnt.at_put(m->_idx, m_cnt); + if( m_cnt == 0 ) worklist.push(m); } } From fdf8f817d318109fa8880a22554627ee8f54c389 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Wed, 25 Jan 2012 21:10:08 +0400 Subject: [PATCH 78/96] 7132515: Add dcmd to manage UnlockingCommercialFeature flag Added dcmd to unlock or check status of UnlockingCommercialFeature flag Reviewed-by: fparain, rottenha --- .../share/vm/services/diagnosticCommand.cpp | 27 +++++++++++++++++ .../share/vm/services/diagnosticCommand.hpp | 1 + .../vm/services/diagnosticCommand_ext.hpp | 30 +++++++++++++++++++ .../share/vm/services/diagnosticFramework.hpp | 13 ++++++++ hotspot/src/share/vm/services/management.cpp | 17 ++--------- 5 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 hotspot/src/share/vm/services/diagnosticCommand_ext.hpp diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 39c7ce25e4b..78f4c223988 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -31,6 +31,33 @@ #include "services/heapDumper.hpp" #include "services/management.hpp" +void DCmdRegistrant::register_dcmds(){ + // Registration of the diagnostic commands + // First boolean argument specifies if the command is enabled + // Second boolean argument specifies if the command is hidden + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); +#ifndef SERVICES_KERNEL // Heap dumping not supported + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); +#endif // SERVICES_KERNEL + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + +} + +#ifndef HAVE_EXTRA_DCMD +void DCmdRegistrant::register_dcmds_ext(){ + // Do nothing here +} +#endif + + HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _all("-all", "Show help for all commands", "BOOLEAN", false, "false"), _cmd("command name", "The name of the command for which we want help", diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index 436664a9cad..c226a4ad6e9 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -34,6 +34,7 @@ #include "services/diagnosticArgument.hpp" #include "services/diagnosticCommand.hpp" #include "services/diagnosticFramework.hpp" +#include "services/diagnosticCommand_ext.hpp" class HelpDCmd : public DCmdWithParser { protected: diff --git a/hotspot/src/share/vm/services/diagnosticCommand_ext.hpp b/hotspot/src/share/vm/services/diagnosticCommand_ext.hpp new file mode 100644 index 00000000000..7b7e94f2ccc --- /dev/null +++ b/hotspot/src/share/vm/services/diagnosticCommand_ext.hpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. DO + * NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_EXT_HPP +#define SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_EXT_HPP + +#undef HAVE_EXTRA_DCMD + +#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP diff --git a/hotspot/src/share/vm/services/diagnosticFramework.hpp b/hotspot/src/share/vm/services/diagnosticFramework.hpp index e3b78bb384b..2fe4d476ddd 100644 --- a/hotspot/src/share/vm/services/diagnosticFramework.hpp +++ b/hotspot/src/share/vm/services/diagnosticFramework.hpp @@ -387,4 +387,17 @@ public: } }; +// This class provides a convenient way to register Dcmds, without a need to change +// management.cpp every time. Body of these two methods resides in +// diagnosticCommand.cpp + +class DCmdRegistrant : public AllStatic { + +private: + static void register_dcmds(); + static void register_dcmds_ext(); + + friend class Management; +}; + #endif // SHARE_VM_SERVICES_DIAGNOSTICFRAMEWORK_HPP diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp index 5decfaa9994..48a5b6a0997 100644 --- a/hotspot/src/share/vm/services/management.cpp +++ b/hotspot/src/share/vm/services/management.cpp @@ -119,21 +119,8 @@ void Management::init() { _optional_support.isThreadAllocatedMemorySupported = 1; // Registration of the diagnostic commands - // First boolean argument specifies if the command is enabled - // Second boolean argument specifies if the command is hidden - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); -#ifndef SERVICES_KERNEL // Heap dumping not supported - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); -#endif // SERVICES_KERNEL - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdRegistrant::register_dcmds(); + DCmdRegistrant::register_dcmds_ext(); } void Management::initialize(TRAPS) { From 802519ea5372ff35bf786d5861ff7a51cd00fb98 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 25 Jan 2012 12:58:23 -0500 Subject: [PATCH 79/96] 7127706: G1: re-enable survivors during the initial-mark pause Re-enable survivors during the initial-mark pause. Afterwards, the concurrent marking threads have to scan them and mark everything reachable from them. The next GC will have to wait for the survivors to be scanned. Reviewed-by: brutisso, johnc --- .../gc_implementation/g1/concurrentMark.cpp | 145 ++++++++++++++++++ .../gc_implementation/g1/concurrentMark.hpp | 91 ++++++++++- .../g1/concurrentMark.inline.hpp | 65 +++++--- .../g1/concurrentMarkThread.cpp | 29 +++- .../gc_implementation/g1/g1CollectedHeap.cpp | 43 ++++-- .../g1/g1CollectorPolicy.cpp | 37 +++-- .../g1/g1CollectorPolicy.hpp | 11 +- .../vm/gc_implementation/g1/g1EvacFailure.hpp | 2 +- .../vm/gc_implementation/g1/g1OopClosures.hpp | 16 ++ .../g1/g1OopClosures.inline.hpp | 29 +++- .../g1/heapRegion.inline.hpp | 28 ++-- hotspot/src/share/vm/runtime/mutexLocker.cpp | 6 +- hotspot/src/share/vm/runtime/mutexLocker.hpp | 5 +- 13 files changed, 425 insertions(+), 82 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 94a4771719c..001f94e161e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -460,6 +460,84 @@ bool ConcurrentMark::not_yet_marked(oop obj) const { && !nextMarkBitMap()->isMarked((HeapWord*)obj))); } +CMRootRegions::CMRootRegions() : + _young_list(NULL), _cm(NULL), _scan_in_progress(false), + _should_abort(false), _next_survivor(NULL) { } + +void CMRootRegions::init(G1CollectedHeap* g1h, ConcurrentMark* cm) { + _young_list = g1h->young_list(); + _cm = cm; +} + +void CMRootRegions::prepare_for_scan() { + assert(!scan_in_progress(), "pre-condition"); + + // Currently, only survivors can be root regions. + assert(_next_survivor == NULL, "pre-condition"); + _next_survivor = _young_list->first_survivor_region(); + _scan_in_progress = (_next_survivor != NULL); + _should_abort = false; +} + +HeapRegion* CMRootRegions::claim_next() { + if (_should_abort) { + // If someone has set the should_abort flag, we return NULL to + // force the caller to bail out of their loop. + return NULL; + } + + // Currently, only survivors can be root regions. + HeapRegion* res = _next_survivor; + if (res != NULL) { + MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag); + // Read it again in case it changed while we were waiting for the lock. + res = _next_survivor; + if (res != NULL) { + if (res == _young_list->last_survivor_region()) { + // We just claimed the last survivor so store NULL to indicate + // that we're done. + _next_survivor = NULL; + } else { + _next_survivor = res->get_next_young_region(); + } + } else { + // Someone else claimed the last survivor while we were trying + // to take the lock so nothing else to do. + } + } + assert(res == NULL || res->is_survivor(), "post-condition"); + + return res; +} + +void CMRootRegions::scan_finished() { + assert(scan_in_progress(), "pre-condition"); + + // Currently, only survivors can be root regions. + if (!_should_abort) { + assert(_next_survivor == NULL, "we should have claimed all survivors"); + } + _next_survivor = NULL; + + { + MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag); + _scan_in_progress = false; + RootRegionScan_lock->notify_all(); + } +} + +bool CMRootRegions::wait_until_scan_finished() { + if (!scan_in_progress()) return false; + + { + MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag); + while (scan_in_progress()) { + RootRegionScan_lock->wait(Mutex::_no_safepoint_check_flag); + } + } + return true; +} + #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away #pragma warning( disable:4355 ) // 'this' : used in base member initializer list #endif // _MSC_VER @@ -548,6 +626,8 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set(); satb_qs.set_buffer_size(G1SATBBufferSize); + _root_regions.init(_g1h, this); + _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num); _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num); @@ -864,6 +944,8 @@ void ConcurrentMark::checkpointRootsInitialPost() { satb_mq_set.set_active_all_threads(true, /* new active value */ false /* expected_active */); + _root_regions.prepare_for_scan(); + // update_g1_committed() will be called at the end of an evac pause // when marking is on. So, it's also called at the end of the // initial-mark pause to update the heap end, if the heap expands @@ -1157,6 +1239,69 @@ uint ConcurrentMark::calc_parallel_marking_threads() { return 0; } +void ConcurrentMark::scanRootRegion(HeapRegion* hr, uint worker_id) { + // Currently, only survivors can be root regions. + assert(hr->next_top_at_mark_start() == hr->bottom(), "invariant"); + G1RootRegionScanClosure cl(_g1h, this, worker_id); + + const uintx interval = PrefetchScanIntervalInBytes; + HeapWord* curr = hr->bottom(); + const HeapWord* end = hr->top(); + while (curr < end) { + Prefetch::read(curr, interval); + oop obj = oop(curr); + int size = obj->oop_iterate(&cl); + assert(size == obj->size(), "sanity"); + curr += size; + } +} + +class CMRootRegionScanTask : public AbstractGangTask { +private: + ConcurrentMark* _cm; + +public: + CMRootRegionScanTask(ConcurrentMark* cm) : + AbstractGangTask("Root Region Scan"), _cm(cm) { } + + void work(uint worker_id) { + assert(Thread::current()->is_ConcurrentGC_thread(), + "this should only be done by a conc GC thread"); + + CMRootRegions* root_regions = _cm->root_regions(); + HeapRegion* hr = root_regions->claim_next(); + while (hr != NULL) { + _cm->scanRootRegion(hr, worker_id); + hr = root_regions->claim_next(); + } + } +}; + +void ConcurrentMark::scanRootRegions() { + // scan_in_progress() will have been set to true only if there was + // at least one root region to scan. So, if it's false, we + // should not attempt to do any further work. + if (root_regions()->scan_in_progress()) { + _parallel_marking_threads = calc_parallel_marking_threads(); + assert(parallel_marking_threads() <= max_parallel_marking_threads(), + "Maximum number of marking threads exceeded"); + uint active_workers = MAX2(1U, parallel_marking_threads()); + + CMRootRegionScanTask task(this); + if (parallel_marking_threads() > 0) { + _parallel_workers->set_active_workers((int) active_workers); + _parallel_workers->run_task(&task); + } else { + task.work(0); + } + + // It's possible that has_aborted() is true here without actually + // aborting the survivor scan earlier. This is OK as it's + // mainly used for sanity checking. + root_regions()->scan_finished(); + } +} + void ConcurrentMark::markFromRoots() { // we might be tempted to assert that: // assert(asynch == !SafepointSynchronize::is_at_safepoint(), diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index fc313869fd2..e8795d6ac39 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -349,10 +349,62 @@ typedef enum { high_verbose // per object verbose } CMVerboseLevel; +class YoungList; + +// Root Regions are regions that are not empty at the beginning of a +// marking cycle and which we might collect during an evacuation pause +// while the cycle is active. Given that, during evacuation pauses, we +// do not copy objects that are explicitly marked, what we have to do +// for the root regions is to scan them and mark all objects reachable +// from them. According to the SATB assumptions, we only need to visit +// each object once during marking. So, as long as we finish this scan +// before the next evacuation pause, we can copy the objects from the +// root regions without having to mark them or do anything else to them. +// +// Currently, we only support root region scanning once (at the start +// of the marking cycle) and the root regions are all the survivor +// regions populated during the initial-mark pause. +class CMRootRegions VALUE_OBJ_CLASS_SPEC { +private: + YoungList* _young_list; + ConcurrentMark* _cm; + + volatile bool _scan_in_progress; + volatile bool _should_abort; + HeapRegion* volatile _next_survivor; + +public: + CMRootRegions(); + // We actually do most of the initialization in this method. + void init(G1CollectedHeap* g1h, ConcurrentMark* cm); + + // Reset the claiming / scanning of the root regions. + void prepare_for_scan(); + + // Forces get_next() to return NULL so that the iteration aborts early. + void abort() { _should_abort = true; } + + // Return true if the CM thread are actively scanning root regions, + // false otherwise. + bool scan_in_progress() { return _scan_in_progress; } + + // Claim the next root region to scan atomically, or return NULL if + // all have been claimed. + HeapRegion* claim_next(); + + // Flag that we're done with root region scanning and notify anyone + // who's waiting on it. If aborted is false, assume that all regions + // have been claimed. + void scan_finished(); + + // If CM threads are still scanning root regions, wait until they + // are done. Return true if we had to wait, false otherwise. + bool wait_until_scan_finished(); +}; class ConcurrentMarkThread; -class ConcurrentMark: public CHeapObj { +class ConcurrentMark : public CHeapObj { friend class ConcurrentMarkThread; friend class CMTask; friend class CMBitMapClosure; @@ -400,6 +452,9 @@ protected: HeapWord* _heap_start; HeapWord* _heap_end; + // Root region tracking and claiming. + CMRootRegions _root_regions; + // For gray objects CMMarkStack _markStack; // Grey objects behind global finger. CMRegionStack _regionStack; // Grey regions behind global finger. @@ -553,9 +608,9 @@ protected: bool has_overflown() { return _has_overflown; } void set_has_overflown() { _has_overflown = true; } void clear_has_overflown() { _has_overflown = false; } + bool restart_for_overflow() { return _restart_for_overflow; } bool has_aborted() { return _has_aborted; } - bool restart_for_overflow() { return _restart_for_overflow; } // Methods to enter the two overflow sync barriers void enter_first_sync_barrier(int task_num); @@ -691,6 +746,8 @@ public: // Returns true if there are any aborted memory regions. bool has_aborted_regions(); + CMRootRegions* root_regions() { return &_root_regions; } + bool concurrent_marking_in_progress() { return _concurrent_marking_in_progress; } @@ -741,8 +798,17 @@ public: // G1CollectedHeap // This notifies CM that a root during initial-mark needs to be - // grayed. It is MT-safe. - inline void grayRoot(oop obj, size_t word_size, uint worker_id); + // grayed. It is MT-safe. word_size is the size of the object in + // words. It is passed explicitly as sometimes we cannot calculate + // it from the given object because it might be in an inconsistent + // state (e.g., in to-space and being copied). So the caller is + // responsible for dealing with this issue (e.g., get the size from + // the from-space image when the to-space image might be + // inconsistent) and always passing the size. hr is the region that + // contains the object and it's passed optionally from callers who + // might already have it (no point in recalculating it). + inline void grayRoot(oop obj, size_t word_size, + uint worker_id, HeapRegion* hr = NULL); // It's used during evacuation pauses to gray a region, if // necessary, and it's MT-safe. It assumes that the caller has @@ -793,6 +859,13 @@ public: void checkpointRootsInitialPre(); void checkpointRootsInitialPost(); + // Scan all the root regions and mark everything reachable from + // them. + void scanRootRegions(); + + // Scan a single root region and mark everything reachable from it. + void scanRootRegion(HeapRegion* hr, uint worker_id); + // Do concurrent phase of marking, to a tentative transitive closure. void markFromRoots(); @@ -972,6 +1045,10 @@ public: size_t* marked_bytes_array, BitMap* task_card_bm); + // Counts the given memory region in the task/worker counting + // data structures for the given worker id. + inline void count_region(MemRegion mr, HeapRegion* hr, uint worker_id); + // Counts the given memory region in the task/worker counting // data structures for the given worker id. inline void count_region(MemRegion mr, uint worker_id); @@ -992,6 +1069,12 @@ public: size_t* marked_bytes_array, BitMap* task_card_bm); + // Attempts to mark the given object and, if successful, counts + // the object in the task/worker counting structures for the + // given worker id. + inline bool par_mark_and_count(oop obj, size_t word_size, + HeapRegion* hr, uint worker_id); + // Attempts to mark the given object and, if successful, counts // the object in the task/worker counting structures for the // given worker id. diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp index 84a0af566be..27c3411051d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp @@ -81,14 +81,22 @@ inline void ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, } } +// Counts the given memory region in the task/worker counting +// data structures for the given worker id. +inline void ConcurrentMark::count_region(MemRegion mr, + HeapRegion* hr, + uint worker_id) { + size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); + BitMap* task_card_bm = count_card_bitmap_for(worker_id); + count_region(mr, hr, marked_bytes_array, task_card_bm); +} + // Counts the given memory region, which may be a single object, in the // task/worker counting data structures for the given worker id. inline void ConcurrentMark::count_region(MemRegion mr, uint worker_id) { - size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); - BitMap* task_card_bm = count_card_bitmap_for(worker_id); HeapWord* addr = mr.start(); HeapRegion* hr = _g1h->heap_region_containing_raw(addr); - count_region(mr, hr, marked_bytes_array, task_card_bm); + count_region(mr, hr, worker_id); } // Counts the given object in the given task/worker counting data structures. @@ -102,7 +110,9 @@ inline void ConcurrentMark::count_object(oop obj, // Counts the given object in the task/worker counting data // structures for the given worker id. -inline void ConcurrentMark::count_object(oop obj, HeapRegion* hr, uint worker_id) { +inline void ConcurrentMark::count_object(oop obj, + HeapRegion* hr, + uint worker_id) { size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); BitMap* task_card_bm = count_card_bitmap_for(worker_id); HeapWord* addr = (HeapWord*) obj; @@ -124,6 +134,22 @@ inline bool ConcurrentMark::par_mark_and_count(oop obj, return false; } +// Attempts to mark the given object and, if successful, counts +// the object in the task/worker counting structures for the +// given worker id. +inline bool ConcurrentMark::par_mark_and_count(oop obj, + size_t word_size, + HeapRegion* hr, + uint worker_id) { + HeapWord* addr = (HeapWord*)obj; + if (_nextMarkBitMap->parMark(addr)) { + MemRegion mr(addr, word_size); + count_region(mr, hr, worker_id); + return true; + } + return false; +} + // Attempts to mark the given object and, if successful, counts // the object in the task/worker counting structures for the // given worker id. @@ -342,20 +368,20 @@ inline void ConcurrentMark::markPrev(oop p) { ((CMBitMap*)_prevMarkBitMap)->mark((HeapWord*) p); } -inline void ConcurrentMark::grayRoot(oop obj, size_t word_size, uint worker_id) { +inline void ConcurrentMark::grayRoot(oop obj, size_t word_size, + uint worker_id, HeapRegion* hr) { + assert(obj != NULL, "pre-condition"); HeapWord* addr = (HeapWord*) obj; - - // Currently we don't do anything with word_size but we will use it - // in the very near future in the liveness calculation piggy-backing - // changes. - -#ifdef ASSERT - HeapRegion* hr = _g1h->heap_region_containing(addr); + if (hr == NULL) { + hr = _g1h->heap_region_containing_raw(addr); + } else { + assert(hr->is_in(addr), "pre-condition"); + } assert(hr != NULL, "sanity"); - assert(!hr->is_survivor(), "should not allocate survivors during IM"); - assert(addr < hr->next_top_at_mark_start(), - err_msg("addr: "PTR_FORMAT" hr: "HR_FORMAT" NTAMS: "PTR_FORMAT, - addr, HR_FORMAT_PARAMS(hr), hr->next_top_at_mark_start())); + // Given that we're looking for a region that contains an object + // header it's impossible to get back a HC region. + assert(!hr->continuesHumongous(), "sanity"); + // We cannot assert that word_size == obj->size() given that obj // might not be in a consistent state (another thread might be in // the process of copying it). So the best thing we can do is to @@ -365,10 +391,11 @@ inline void ConcurrentMark::grayRoot(oop obj, size_t word_size, uint worker_id) err_msg("size: "SIZE_FORMAT" capacity: "SIZE_FORMAT" "HR_FORMAT, word_size * HeapWordSize, hr->capacity(), HR_FORMAT_PARAMS(hr))); -#endif // ASSERT - if (!_nextMarkBitMap->isMarked(addr)) { - par_mark_and_count(obj, word_size, worker_id); + if (addr < hr->next_top_at_mark_start()) { + if (!_nextMarkBitMap->isMarked(addr)) { + par_mark_and_count(obj, word_size, hr, worker_id); + } } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp index bf1cd89e85e..4dce3689175 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp @@ -92,9 +92,36 @@ void ConcurrentMarkThread::run() { ResourceMark rm; HandleMark hm; double cycle_start = os::elapsedVTime(); - double mark_start_sec = os::elapsedTime(); char verbose_str[128]; + // We have to ensure that we finish scanning the root regions + // before the next GC takes place. To ensure this we have to + // make sure that we do not join the STS until the root regions + // have been scanned. If we did then it's possible that a + // subsequent GC could block us from joining the STS and proceed + // without the root regions have been scanned which would be a + // correctness issue. + + double scan_start = os::elapsedTime(); + if (!cm()->has_aborted()) { + if (PrintGC) { + gclog_or_tty->date_stamp(PrintGCDateStamps); + gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]"); + } + + _cm->scanRootRegions(); + + double scan_end = os::elapsedTime(); + if (PrintGC) { + gclog_or_tty->date_stamp(PrintGCDateStamps); + gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf]", + scan_end - scan_start); + } + } + + double mark_start_sec = os::elapsedTime(); if (PrintGC) { gclog_or_tty->date_stamp(PrintGCDateStamps); gclog_or_tty->stamp(PrintGCTimeStamps); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index dfda7ab2ed5..35470ea85d1 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -174,13 +174,10 @@ public: } }; -YoungList::YoungList(G1CollectedHeap* g1h) - : _g1h(g1h), _head(NULL), - _length(0), - _last_sampled_rs_lengths(0), - _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) -{ - guarantee( check_list_empty(false), "just making sure..." ); +YoungList::YoungList(G1CollectedHeap* g1h) : + _g1h(g1h), _head(NULL), _length(0), _last_sampled_rs_lengths(0), + _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) { + guarantee(check_list_empty(false), "just making sure..."); } void YoungList::push_region(HeapRegion *hr) { @@ -1270,7 +1267,18 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, double start = os::elapsedTime(); g1_policy()->record_full_collection_start(); + // Note: When we have a more flexible GC logging framework that + // allows us to add optional attributes to a GC log record we + // could consider timing and reporting how long we wait in the + // following two methods. wait_while_free_regions_coming(); + // If we start the compaction before the CM threads finish + // scanning the root regions we might trip them over as we'll + // be moving objects / updating references. So let's wait until + // they are done. By telling them to abort, they should complete + // early. + _cm->root_regions()->abort(); + _cm->root_regions()->wait_until_scan_finished(); append_secondary_free_list_if_not_empty_with_lock(); gc_prologue(true); @@ -1299,7 +1307,8 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, ref_processor_cm()->verify_no_references_recorded(); // Abandon current iterations of concurrent marking and concurrent - // refinement, if any are in progress. + // refinement, if any are in progress. We have to do this before + // wait_until_scan_finished() below. concurrent_mark()->abort(); // Make sure we'll choose a new allocation region afterwards. @@ -3675,6 +3684,18 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { g1_policy()->record_collection_pause_start(start_time_sec, start_used_bytes); + double scan_wait_start = os::elapsedTime(); + // We have to wait until the CM threads finish scanning the + // root regions as it's the only way to ensure that all the + // objects on them have been correctly scanned before we start + // moving them during the GC. + bool waited = _cm->root_regions()->wait_until_scan_finished(); + if (waited) { + double scan_wait_end = os::elapsedTime(); + double wait_time_ms = (scan_wait_end - scan_wait_start) * 1000.0; + g1_policy()->record_root_region_scan_wait_time(wait_time_ms); + } + #if YOUNG_LIST_VERBOSE gclog_or_tty->print_cr("\nAfter recording pause start.\nYoung_list:"); _young_list->print(); @@ -3784,6 +3805,9 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { } if (g1_policy()->during_initial_mark_pause()) { + // We have to do this before we notify the CM threads that + // they can start working to make sure that all the + // appropriate initialization is done on the CM object. concurrent_mark()->checkpointRootsInitialPost(); set_marking_started(); // Note that we don't actually trigger the CM thread at @@ -5773,8 +5797,9 @@ void G1CollectedHeap::set_free_regions_coming() { } void G1CollectedHeap::reset_free_regions_coming() { + assert(free_regions_coming(), "pre-condition"); + { - assert(free_regions_coming(), "pre-condition"); MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); _free_regions_coming = false; SecondaryFreeList_lock->notify_all(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 89fa51be308..ffbf25c221c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -141,6 +141,7 @@ G1CollectorPolicy::G1CollectorPolicy() : _cur_clear_ct_time_ms(0.0), _mark_closure_time_ms(0.0), + _root_region_scan_wait_time_ms(0.0), _cur_ref_proc_time_ms(0.0), _cur_ref_enq_time_ms(0.0), @@ -903,19 +904,10 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, gclog_or_tty->print(" (%s)", gcs_are_young() ? "young" : "mixed"); } - if (!during_initial_mark_pause()) { - // We only need to do this here as the policy will only be applied - // to the GC we're about to start. so, no point is calculating this - // every time we calculate / recalculate the target young length. - update_survivors_policy(); - } else { - // The marking phase has a "we only copy implicitly live - // objects during marking" invariant. The easiest way to ensure it - // holds is not to allocate any survivor regions and tenure all - // objects. In the future we might change this and handle survivor - // regions specially during marking. - tenure_all_objects(); - } + // We only need to do this here as the policy will only be applied + // to the GC we're about to start. so, no point is calculating this + // every time we calculate / recalculate the target young length. + update_survivors_policy(); assert(_g1->used() == _g1->recalculate_used(), err_msg("sanity, used: "SIZE_FORMAT" recalculate_used: "SIZE_FORMAT, @@ -967,6 +959,9 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, // This is initialized to zero here and is set during // the evacuation pause if marking is in progress. _cur_satb_drain_time_ms = 0.0; + // This is initialized to zero here and is set during the evacuation + // pause if we actually waited for the root region scanning to finish. + _root_region_scan_wait_time_ms = 0.0; _last_gc_was_young = false; @@ -1271,6 +1266,10 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { // is in progress. other_time_ms -= _cur_satb_drain_time_ms; + // Subtract the root region scanning wait time. It's initialized to + // zero at the start of the pause. + other_time_ms -= _root_region_scan_wait_time_ms; + if (parallel) { other_time_ms -= _cur_collection_par_time_ms; } else { @@ -1303,6 +1302,8 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { // each other. Therefore we unconditionally record the SATB drain // time - even if it's zero. body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms); + body_summary->record_root_region_scan_wait_time_ms( + _root_region_scan_wait_time_ms); body_summary->record_ext_root_scan_time_ms(ext_root_scan_time); body_summary->record_satb_filtering_time_ms(satb_filtering_time); @@ -1399,6 +1400,9 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { (last_pause_included_initial_mark) ? " (initial-mark)" : "", elapsed_ms / 1000.0); + if (_root_region_scan_wait_time_ms > 0.0) { + print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms); + } if (parallel) { print_stats(1, "Parallel Time", _cur_collection_par_time_ms); print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms); @@ -2002,6 +2006,7 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const { if (summary->get_total_seq()->num() > 0) { print_summary_sd(0, "Evacuation Pauses", summary->get_total_seq()); if (body_summary != NULL) { + print_summary(1, "Root Region Scan Wait", body_summary->get_root_region_scan_wait_seq()); if (parallel) { print_summary(1, "Parallel Time", body_summary->get_parallel_seq()); print_summary(2, "Ext Root Scanning", body_summary->get_ext_root_scan_seq()); @@ -2043,15 +2048,17 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const { // parallel NumberSeq* other_parts[] = { body_summary->get_satb_drain_seq(), + body_summary->get_root_region_scan_wait_seq(), body_summary->get_parallel_seq(), body_summary->get_clear_ct_seq() }; calc_other_times_ms = NumberSeq(summary->get_total_seq(), - 3, other_parts); + 4, other_parts); } else { // serial NumberSeq* other_parts[] = { body_summary->get_satb_drain_seq(), + body_summary->get_root_region_scan_wait_seq(), body_summary->get_update_rs_seq(), body_summary->get_ext_root_scan_seq(), body_summary->get_satb_filtering_seq(), @@ -2059,7 +2066,7 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const { body_summary->get_obj_copy_seq() }; calc_other_times_ms = NumberSeq(summary->get_total_seq(), - 6, other_parts); + 7, other_parts); } check_other_times(1, summary->get_other_seq(), &calc_other_times_ms); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index a7f521bf9a5..ba18a4a6ef5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -65,6 +65,7 @@ public: class MainBodySummary: public CHeapObj { define_num_seq(satb_drain) // optional + define_num_seq(root_region_scan_wait) define_num_seq(parallel) // parallel only define_num_seq(ext_root_scan) define_num_seq(satb_filtering) @@ -715,6 +716,7 @@ private: double _mark_remark_start_sec; double _mark_cleanup_start_sec; double _mark_closure_time_ms; + double _root_region_scan_wait_time_ms; // Update the young list target length either by setting it to the // desired fixed value or by calculating it using G1's pause @@ -817,6 +819,10 @@ public: _mark_closure_time_ms = mark_closure_time_ms; } + void record_root_region_scan_wait_time(double time_ms) { + _root_region_scan_wait_time_ms = time_ms; + } + void record_concurrent_mark_remark_start(); void record_concurrent_mark_remark_end(); @@ -1147,11 +1153,6 @@ public: _survivor_surv_rate_group->stop_adding_regions(); } - void tenure_all_objects() { - _max_survivor_regions = 0; - _tenuring_threshold = 0; - } - void record_survivor_regions(size_t regions, HeapRegion* head, HeapRegion* tail) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp index 1dd8cc765f5..84d998265a9 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp @@ -127,7 +127,7 @@ public: // explicitly and all objects in the CSet are considered // (implicitly) live. So, we won't mark them explicitly and // we'll leave them over NTAMS. - _cm->grayRoot(obj, obj_size, _worker_id); + _cm->grayRoot(obj, obj_size, _worker_id, _hr); } _marked_bytes += (obj_size * HeapWordSize); obj->set_mark(markOopDesc::prototype()); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index 0930d2d4dd8..f7ccb79cf3e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -220,6 +220,7 @@ public: // Closure for iterating over object fields during concurrent marking class G1CMOopClosure : public OopClosure { +private: G1CollectedHeap* _g1h; ConcurrentMark* _cm; CMTask* _task; @@ -230,4 +231,19 @@ public: virtual void do_oop(narrowOop* p) { do_oop_nv(p); } }; +// Closure to scan the root regions during concurrent marking +class G1RootRegionScanClosure : public OopClosure { +private: + G1CollectedHeap* _g1h; + ConcurrentMark* _cm; + uint _worker_id; +public: + G1RootRegionScanClosure(G1CollectedHeap* g1h, ConcurrentMark* cm, + uint worker_id) : + _g1h(g1h), _cm(cm), _worker_id(worker_id) { } + template void do_oop_nv(T* p); + virtual void do_oop( oop* p) { do_oop_nv(p); } + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } +}; + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp index 26b951d961f..5db2340bc07 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,8 @@ // perf-critical inner loop. #define FILTERINTOCSCLOSURE_DOHISTOGRAMCOUNT 0 -template inline void FilterIntoCSClosure::do_oop_nv(T* p) { +template +inline void FilterIntoCSClosure::do_oop_nv(T* p) { T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop) && _g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop))) { @@ -53,7 +54,8 @@ template inline void FilterIntoCSClosure::do_oop_nv(T* p) { #define FILTEROUTOFREGIONCLOSURE_DOHISTOGRAMCOUNT 0 -template inline void FilterOutOfRegionClosure::do_oop_nv(T* p) { +template +inline void FilterOutOfRegionClosure::do_oop_nv(T* p) { T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop)) { HeapWord* obj_hw = (HeapWord*)oopDesc::decode_heap_oop_not_null(heap_oop); @@ -67,7 +69,8 @@ template inline void FilterOutOfRegionClosure::do_oop_nv(T* p) { } // This closure is applied to the fields of the objects that have just been copied. -template inline void G1ParScanClosure::do_oop_nv(T* p) { +template +inline void G1ParScanClosure::do_oop_nv(T* p) { T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop)) { @@ -96,7 +99,8 @@ template inline void G1ParScanClosure::do_oop_nv(T* p) { } } -template inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) { +template +inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) { T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop)) { @@ -111,7 +115,8 @@ template inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) { } } -template inline void G1CMOopClosure::do_oop_nv(T* p) { +template +inline void G1CMOopClosure::do_oop_nv(T* p) { assert(_g1h->is_in_g1_reserved((HeapWord*) p), "invariant"); assert(!_g1h->is_on_master_free_list( _g1h->heap_region_containing((HeapWord*) p)), "invariant"); @@ -125,4 +130,16 @@ template inline void G1CMOopClosure::do_oop_nv(T* p) { _task->deal_with_reference(obj); } +template +inline void G1RootRegionScanClosure::do_oop_nv(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + HeapRegion* hr = _g1h->heap_region_containing((HeapWord*) obj); + if (hr != NULL) { + _cm->grayRoot(obj, obj->size(), _worker_id, hr); + } + } +} + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp index 55d05d998fe..1498b94a4e9 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp @@ -72,10 +72,11 @@ inline void HeapRegion::note_end_of_marking() { } inline void HeapRegion::note_start_of_copying(bool during_initial_mark) { - if (during_initial_mark) { - if (is_survivor()) { - assert(false, "should not allocate survivors during IM"); - } else { + if (is_survivor()) { + // This is how we always allocate survivors. + assert(_next_top_at_mark_start == bottom(), "invariant"); + } else { + if (during_initial_mark) { // During initial-mark we'll explicitly mark any objects on old // regions that are pointed to by roots. Given that explicit // marks only make sense under NTAMS it'd be nice if we could @@ -84,11 +85,6 @@ inline void HeapRegion::note_start_of_copying(bool during_initial_mark) { // NTAMS to the end of the region so all marks will be below // NTAMS. We'll set it to the actual top when we retire this region. _next_top_at_mark_start = end(); - } - } else { - if (is_survivor()) { - // This is how we always allocate survivors. - assert(_next_top_at_mark_start == bottom(), "invariant"); } else { // We could have re-used this old region as to-space over a // couple of GCs since the start of the concurrent marking @@ -101,19 +97,15 @@ inline void HeapRegion::note_start_of_copying(bool during_initial_mark) { } inline void HeapRegion::note_end_of_copying(bool during_initial_mark) { - if (during_initial_mark) { - if (is_survivor()) { - assert(false, "should not allocate survivors during IM"); - } else { + if (is_survivor()) { + // This is how we always allocate survivors. + assert(_next_top_at_mark_start == bottom(), "invariant"); + } else { + if (during_initial_mark) { // See the comment for note_start_of_copying() for the details // on this. assert(_next_top_at_mark_start == end(), "pre-condition"); _next_top_at_mark_start = top(); - } - } else { - if (is_survivor()) { - // This is how we always allocate survivors. - assert(_next_top_at_mark_start == bottom(), "invariant"); } else { // See the comment for note_start_of_copying() for the details // on this. diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp index 7653b5bef84..dae98f08dcb 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,13 +126,14 @@ Mutex* OopMapCacheAlloc_lock = NULL; Mutex* FreeList_lock = NULL; Monitor* SecondaryFreeList_lock = NULL; Mutex* OldSets_lock = NULL; +Monitor* RootRegionScan_lock = NULL; Mutex* MMUTracker_lock = NULL; Mutex* HotCardCache_lock = NULL; Monitor* GCTaskManager_lock = NULL; Mutex* Management_lock = NULL; -Monitor* Service_lock = NULL; +Monitor* Service_lock = NULL; #define MAX_NUM_MUTEX 128 static Monitor * _mutex_array[MAX_NUM_MUTEX]; @@ -193,6 +194,7 @@ void mutex_init() { def(FreeList_lock , Mutex, leaf , true ); def(SecondaryFreeList_lock , Monitor, leaf , true ); def(OldSets_lock , Mutex , leaf , true ); + def(RootRegionScan_lock , Monitor, leaf , true ); def(MMUTracker_lock , Mutex , leaf , true ); def(HotCardCache_lock , Mutex , special , true ); def(EvacFailureStack_lock , Mutex , nonleaf , true ); diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp index 37a3d3132b4..884640595c5 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,7 +115,7 @@ extern Mutex* OsrList_lock; // a lock used to serialize acc #ifndef PRODUCT extern Mutex* FullGCALot_lock; // a lock to make FullGCALot MT safe -#endif +#endif // PRODUCT extern Mutex* Debug1_lock; // A bunch of pre-allocated locks that can be used for tracing extern Mutex* Debug2_lock; // down synchronization related bugs! extern Mutex* Debug3_lock; @@ -129,6 +129,7 @@ extern Mutex* OopMapCacheAlloc_lock; // protects allocation of oop_m extern Mutex* FreeList_lock; // protects the free region list during safepoints extern Monitor* SecondaryFreeList_lock; // protects the secondary free region list extern Mutex* OldSets_lock; // protects the old region sets +extern Monitor* RootRegionScan_lock; // used to notify that the CM threads have finished scanning the IM snapshot regions extern Mutex* MMUTracker_lock; // protects the MMU // tracker data structures extern Mutex* HotCardCache_lock; // protects the hot card cache From 6fd2cebd8537a048c1fc080a16fde3e047889e9f Mon Sep 17 00:00:00 2001 From: Frederic Parain Date: Wed, 25 Jan 2012 10:32:29 -0800 Subject: [PATCH 80/96] 7131346: Parsing of boolean arguments to diagnostic commands is broken Reviewed-by: dholmes, dcubed --- hotspot/src/share/vm/services/diagnosticArgument.cpp | 7 ++++--- .../src/share/vm/utilities/globalDefinitions_visCPP.hpp | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/services/diagnosticArgument.cpp b/hotspot/src/share/vm/services/diagnosticArgument.cpp index 0821c9ac238..33563fbdc74 100644 --- a/hotspot/src/share/vm/services/diagnosticArgument.cpp +++ b/hotspot/src/share/vm/services/diagnosticArgument.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,12 +59,13 @@ template <> void DCmdArgument::destroy_value() { } template <> void DCmdArgument::parse_value(const char* str, size_t len, TRAPS) { + // len is the length of the current token starting at str if (len == 0) { set_value(true); } else { - if (strcasecmp(str, "true") == 0) { + if (len == strlen("true") && strncasecmp(str, "true", len) == 0) { set_value(true); - } else if (strcasecmp(str, "false") == 0) { + } else if (len == strlen("false") && strncasecmp(str, "false", len) == 0) { set_value(false); } else { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp index ba54d229097..60ebb118ee9 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp @@ -130,6 +130,9 @@ inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } //---------------------------------------------------------------------------------------------------- // Non-standard stdlib-like stuff: inline int strcasecmp(const char *s1, const char *s2) { return _stricmp(s1,s2); } +inline int strncasecmp(const char *s1, const char *s2, size_t n) { + return _strnicmp(s1,s2,n); +} //---------------------------------------------------------------------------------------------------- From 3eb017ee50e3d237b627f9040fb717c0f9d16447 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Wed, 25 Jan 2012 21:14:11 -0800 Subject: [PATCH 81/96] 7112413: JVM Crash, possibly GC-related Disable UseAdaptiveSizePolicy with the CMS and ParNew Reviewed-by: johnc, brutisso --- hotspot/src/share/vm/runtime/arguments.cpp | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index ed777ce2b64..bbd359a9172 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1040,6 +1040,16 @@ void Arguments::set_tiered_flags() { } #ifndef KERNEL +static void disable_adaptive_size_policy(const char* collector_name) { + if (UseAdaptiveSizePolicy) { + if (FLAG_IS_CMDLINE(UseAdaptiveSizePolicy)) { + warning("disabling UseAdaptiveSizePolicy; it is incompatible with %s.", + collector_name); + } + FLAG_SET_DEFAULT(UseAdaptiveSizePolicy, false); + } +} + // If the user has chosen ParallelGCThreads > 0, we set UseParNewGC // if it's not explictly set or unset. If the user has chosen // UseParNewGC and not explicitly set ParallelGCThreads we @@ -1049,11 +1059,8 @@ void Arguments::set_parnew_gc_flags() { "control point invariant"); assert(UseParNewGC, "Error"); - // Turn off AdaptiveSizePolicy by default for parnew until it is - // complete. - if (FLAG_IS_DEFAULT(UseAdaptiveSizePolicy)) { - FLAG_SET_DEFAULT(UseAdaptiveSizePolicy, false); - } + // Turn off AdaptiveSizePolicy for parnew until it is complete. + disable_adaptive_size_policy("UseParNewGC"); if (ParallelGCThreads == 0) { FLAG_SET_DEFAULT(ParallelGCThreads, @@ -1110,11 +1117,8 @@ void Arguments::set_cms_and_parnew_gc_flags() { FLAG_SET_ERGO(bool, UseParNewGC, true); } - // Turn off AdaptiveSizePolicy by default for cms until it is - // complete. - if (FLAG_IS_DEFAULT(UseAdaptiveSizePolicy)) { - FLAG_SET_DEFAULT(UseAdaptiveSizePolicy, false); - } + // Turn off AdaptiveSizePolicy for CMS until it is complete. + disable_adaptive_size_policy("UseConcMarkSweepGC"); // In either case, adjust ParallelGCThreads and/or UseParNewGC // as needed. From de3ed511b19913f24fda98a87766f4189dd8db74 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Thu, 26 Jan 2012 09:38:28 +0100 Subject: [PATCH 82/96] 7123910: Some CTW tests crash VM: is_loaded() && that->is_loaded() Handle not loaded array klass in Parse::do_checkcast(). Reviewed-by: kvn, never --- hotspot/src/share/vm/opto/parseHelper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/opto/parseHelper.cpp b/hotspot/src/share/vm/opto/parseHelper.cpp index 9ebc716b548..26a146f5e88 100644 --- a/hotspot/src/share/vm/opto/parseHelper.cpp +++ b/hotspot/src/share/vm/opto/parseHelper.cpp @@ -71,14 +71,14 @@ void Parse::do_checkcast() { // Throw uncommon trap if class is not loaded or the value we are casting // _from_ is not loaded, and value is not null. If the value _is_ NULL, // then the checkcast does nothing. - const TypeInstPtr *tp = _gvn.type(obj)->isa_instptr(); - if (!will_link || (tp && !tp->is_loaded())) { + const TypeOopPtr *tp = _gvn.type(obj)->isa_oopptr(); + if (!will_link || (tp && tp->klass() && !tp->klass()->is_loaded())) { if (C->log() != NULL) { if (!will_link) { C->log()->elem("assert_null reason='checkcast' klass='%d'", C->log()->identify(klass)); } - if (tp && !tp->is_loaded()) { + if (tp && tp->klass() && !tp->klass()->is_loaded()) { // %%% Cannot happen? C->log()->elem("assert_null reason='checkcast source' klass='%d'", C->log()->identify(tp->klass())); From 070f9108ffb0c0b52194215b4f3766104cc023fc Mon Sep 17 00:00:00 2001 From: Bertrand Delsart Date: Thu, 26 Jan 2012 16:49:22 +0100 Subject: [PATCH 83/96] 7120468: SPARC/x86: use frame::describe to enhance trace_method_handle Improvements of TraceMethodHandles for JSR292 Reviewed-by: never, twisti --- hotspot/src/cpu/sparc/vm/frame_sparc.cpp | 2 +- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 113 ++++++++++++++++-- .../src/cpu/sparc/vm/methodHandles_sparc.hpp | 2 +- hotspot/src/cpu/x86/vm/frame_x86.cpp | 2 +- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 113 +++++++++++++++--- hotspot/src/cpu/x86/vm/methodHandles_x86.hpp | 2 +- hotspot/src/cpu/zero/vm/frame_zero.cpp | 2 +- hotspot/src/share/vm/runtime/frame.cpp | 11 +- hotspot/src/share/vm/runtime/frame.hpp | 4 +- 9 files changed, 213 insertions(+), 38 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp index fdcfffef804..f7bccc84a0d 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp @@ -810,7 +810,7 @@ intptr_t* frame::interpreter_frame_tos_at(jint offset) const { } -#ifdef ASSERT +#ifndef PRODUCT #define DESCRIBE_FP_OFFSET(name) \ values.describe(frame_no, fp() + frame::name##_offset, #name) diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index 96b8ff8594d..9adb9d93b90 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -177,7 +177,7 @@ void MethodHandles::RicochetFrame::generate_ricochet_blob(MacroAssembler* _masm, BLOCK_COMMENT("ricochet_blob.bounce"); if (VerifyMethodHandles) RicochetFrame::verify_clean(_masm); - trace_method_handle(_masm, "ricochet_blob.bounce"); + trace_method_handle(_masm, "return/ricochet_blob.bounce"); __ JMP(L1_continuation, 0); __ delayed()->nop(); @@ -268,14 +268,16 @@ void MethodHandles::RicochetFrame::leave_ricochet_frame(MacroAssembler* _masm, } // Emit code to verify that FP is pointing at a valid ricochet frame. -#ifdef ASSERT +#ifndef PRODUCT enum { ARG_LIMIT = 255, SLOP = 45, // use this parameter for checking for garbage stack movements: UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP) // the slop defends against false alarms due to fencepost errors }; +#endif +#ifdef ASSERT void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) { // The stack should look like this: // ... keep1 | dest=42 | keep2 | magic | handler | magic | recursive args | [RF] @@ -1000,7 +1002,7 @@ void MethodHandles::move_return_value(MacroAssembler* _masm, BasicType type, BLOCK_COMMENT("} move_return_value"); } -#ifdef ASSERT +#ifndef PRODUCT void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) { RicochetFrame* rf = new RicochetFrame(*fr); @@ -1022,28 +1024,121 @@ void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values extern "C" void print_method_handle(oop mh); void trace_method_handle_stub(const char* adaptername, oopDesc* mh, - intptr_t* saved_sp) { + intptr_t* saved_sp, + intptr_t* args, + intptr_t* tracing_fp) { bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have mh - tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp); - if (has_mh) + + tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT " args=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp, args); + + if (Verbose) { + // dumping last frame with frame::describe + + JavaThread* p = JavaThread::active(); + + ResourceMark rm; + PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here + FrameValues values; + + // Note: We want to allow trace_method_handle from any call site. + // While trace_method_handle creates a frame, it may be entered + // without a valid return PC in O7 (e.g. not just after a call). + // Walking that frame could lead to failures due to that invalid PC. + // => carefully detect that frame when doing the stack walking + + // walk up to the right frame using the "tracing_fp" argument + intptr_t* cur_sp = StubRoutines::Sparc::flush_callers_register_windows_func()(); + frame cur_frame(cur_sp, frame::unpatchable, NULL); + + while (cur_frame.fp() != (intptr_t *)(STACK_BIAS+(uintptr_t)tracing_fp)) { + cur_frame = os::get_sender_for_C_frame(&cur_frame); + } + + // safely create a frame and call frame::describe + intptr_t *dump_sp = cur_frame.sender_sp(); + intptr_t *dump_fp = cur_frame.link(); + + bool walkable = has_mh; // whether the traced frame shoud be walkable + + // the sender for cur_frame is the caller of trace_method_handle + if (walkable) { + // The previous definition of walkable may have to be refined + // if new call sites cause the next frame constructor to start + // failing. Alternatively, frame constructors could be + // modified to support the current or future non walkable + // frames (but this is more intrusive and is not considered as + // part of this RFE, which will instead use a simpler output). + frame dump_frame = frame(dump_sp, + cur_frame.sp(), // younger_sp + false); // no adaptation + dump_frame.describe(values, 1); + } else { + // Robust dump for frames which cannot be constructed from sp/younger_sp + // Add descriptions without building a Java frame to avoid issues + values.describe(-1, dump_fp, "fp for #1 "); + values.describe(-1, dump_sp, "sp"); + } + + bool has_args = has_mh; // whether Gargs is meaningful + + // mark args, if seems valid (may not be valid for some adapters) + if (has_args) { + if ((args >= dump_sp) && (args < dump_fp)) { + values.describe(-1, args, "*G4_args"); + } + } + + // mark saved_sp, if seems valid (may not be valid for some adapters) + intptr_t *unbiased_sp = (intptr_t *)(STACK_BIAS+(uintptr_t)saved_sp); + if ((unbiased_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (unbiased_sp < dump_fp)) { + values.describe(-1, unbiased_sp, "*saved_sp+STACK_BIAS"); + } + + // Note: the unextended_sp may not be correct + tty->print_cr(" stack layout:"); + values.print(p); + } + + if (has_mh) { print_method_handle(mh); + } } + void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { if (!TraceMethodHandles) return; BLOCK_COMMENT("trace_method_handle {"); // save: Gargs, O5_savedSP - __ save_frame(16); + __ save_frame(16); // need space for saving required FPU state + __ set((intptr_t) adaptername, O0); __ mov(G3_method_handle, O1); __ mov(I5_savedSP, O2); + __ mov(Gargs, O3); + __ mov(I6, O4); // frame identifier for safe stack walking + + // Save scratched registers that might be needed. Robustness is more + // important than optimizing the saves for this debug only code. + + // save FP result, valid at some call sites (adapter_opt_return_float, ...) + Address d_save(FP, -sizeof(jdouble) + STACK_BIAS); + __ stf(FloatRegisterImpl::D, Ftos_d, d_save); + // Safely save all globals but G2 (handled by call_VM_leaf) and G7 + // (OS reserved). __ mov(G3_method_handle, L3); __ mov(Gargs, L4); __ mov(G5_method_type, L5); - __ call_VM_leaf(L7, CAST_FROM_FN_PTR(address, trace_method_handle_stub)); + __ mov(G6, L6); + __ mov(G1, L1); + + __ call_VM_leaf(L2 /* for G2 */, CAST_FROM_FN_PTR(address, trace_method_handle_stub)); __ mov(L3, G3_method_handle); __ mov(L4, Gargs); __ mov(L5, G5_method_type); + __ mov(L6, G6); + __ mov(L1, G1); + __ ldf(FloatRegisterImpl::D, d_save, Ftos_d); + __ restore(); BLOCK_COMMENT("} trace_method_handle"); } @@ -1268,7 +1363,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan move_typed_arg(_masm, arg_type, false, prim_value_addr, Address(O0_argslot, 0), - O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) + O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) } if (direct_to_method) { diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp index 2c3d810b813..7382b9c4ef0 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp @@ -146,7 +146,7 @@ class RicochetFrame : public ResourceObj { static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN; - static void describe(const frame* fr, FrameValues& values, int frame_no) NOT_DEBUG_RETURN; + static void describe(const frame* fr, FrameValues& values, int frame_no) PRODUCT_RETURN; }; // Additional helper methods for MethodHandles code generation: diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp index 4051cdf59ce..4255be664d2 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp @@ -651,7 +651,7 @@ intptr_t* frame::interpreter_frame_tos_at(jint offset) const { return &interpreter_frame_tos_address()[index]; } -#ifdef ASSERT +#ifndef PRODUCT #define DESCRIBE_FP_OFFSET(name) \ values.describe(frame_no, fp() + frame::name##_offset, #name) diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 38694718b7a..a6ccfb830b8 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -279,14 +279,16 @@ void MethodHandles::RicochetFrame::leave_ricochet_frame(MacroAssembler* _masm, } // Emit code to verify that RBP is pointing at a valid ricochet frame. -#ifdef ASSERT +#ifndef PRODUCT enum { ARG_LIMIT = 255, SLOP = 4, // use this parameter for checking for garbage stack movements: UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP) // the slop defends against false alarms due to fencepost errors }; +#endif +#ifdef ASSERT void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) { // The stack should look like this: // ... keep1 | dest=42 | keep2 | RF | magic | handler | magic | recursive args | @@ -990,7 +992,7 @@ void MethodHandles::move_return_value(MacroAssembler* _masm, BasicType type, BLOCK_COMMENT("} move_return_value"); } -#ifdef ASSERT +#ifndef PRODUCT #define DESCRIBE_RICOCHET_OFFSET(rf, name) \ values.describe(frame_no, (intptr_t *) (((uintptr_t)rf) + MethodHandles::RicochetFrame::name##_offset_in_bytes()), #name) @@ -1021,6 +1023,7 @@ void trace_method_handle_stub(const char* adaptername, intptr_t* saved_bp) { // called as a leaf from native code: do not block the JVM! bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have rcx_mh + intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset]; intptr_t* base_sp = last_sp; typedef MethodHandles::RicochetFrame RicochetFrame; @@ -1050,13 +1053,64 @@ void trace_method_handle_stub(const char* adaptername, tty->cr(); if (last_sp != saved_sp && last_sp != NULL) tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp); - int stack_dump_count = 16; - if (stack_dump_count < (int)(saved_bp + 2 - saved_sp)) - stack_dump_count = (int)(saved_bp + 2 - saved_sp); - if (stack_dump_count > 64) stack_dump_count = 48; - for (i = 0; i < stack_dump_count; i += 4) { - tty->print_cr(" dump at SP[%d] "PTR_FORMAT": "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT, - i, (intptr_t) &entry_sp[i+0], entry_sp[i+0], entry_sp[i+1], entry_sp[i+2], entry_sp[i+3]); + + { + // dumping last frame with frame::describe + + JavaThread* p = JavaThread::active(); + + ResourceMark rm; + PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here + FrameValues values; + + // Note: We want to allow trace_method_handle from any call site. + // While trace_method_handle creates a frame, it may be entered + // without a PC on the stack top (e.g. not just after a call). + // Walking that frame could lead to failures due to that invalid PC. + // => carefully detect that frame when doing the stack walking + + // Current C frame + frame cur_frame = os::current_frame(); + + // Robust search of trace_calling_frame (independant of inlining). + // Assumes saved_regs comes from a pusha in the trace_calling_frame. + assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?"); + frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame); + while (trace_calling_frame.fp() < saved_regs) { + trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame); + } + + // safely create a frame and call frame::describe + intptr_t *dump_sp = trace_calling_frame.sender_sp(); + intptr_t *dump_fp = trace_calling_frame.link(); + + bool walkable = has_mh; // whether the traced frame shoud be walkable + + if (walkable) { + // The previous definition of walkable may have to be refined + // if new call sites cause the next frame constructor to start + // failing. Alternatively, frame constructors could be + // modified to support the current or future non walkable + // frames (but this is more intrusive and is not considered as + // part of this RFE, which will instead use a simpler output). + frame dump_frame = frame(dump_sp, dump_fp); + dump_frame.describe(values, 1); + } else { + // Stack may not be walkable (invalid PC above FP): + // Add descriptions without building a Java frame to avoid issues + values.describe(-1, dump_fp, "fp for #1 "); + values.describe(-1, dump_sp, "sp for #1"); + } + + // mark saved_sp if seems valid + if (has_mh) { + if ((saved_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (saved_sp < dump_fp)) { + values.describe(-1, saved_sp, "*saved_sp"); + } + } + + tty->print_cr(" stack layout:"); + values.print(p); } if (has_mh) print_method_handle(mh); @@ -1086,26 +1140,49 @@ void trace_method_handle_stub_wrapper(MethodHandleStubArguments* args) { void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { if (!TraceMethodHandles) return; BLOCK_COMMENT("trace_method_handle {"); - __ push(rax); - __ lea(rax, Address(rsp, wordSize * NOT_LP64(6) LP64_ONLY(14))); // entry_sp __ pusha(); - __ pusha(); - __ mov(rbx, rsp); __ enter(); + __ andptr(rsp, -16); // align stack if needed for FPU state + __ pusha(); + __ mov(rbx, rsp); // for retreiving saved_regs + // Note: saved_regs must be in the entered frame for the + // robust stack walking implemented in trace_method_handle_stub. + + // save FP result, valid at some call sites (adapter_opt_return_float, ...) + __ increment(rsp, -2 * wordSize); + if (UseSSE >= 2) { + __ movdbl(Address(rsp, 0), xmm0); + } else if (UseSSE == 1) { + __ movflt(Address(rsp, 0), xmm0); + } else { + __ fst_d(Address(rsp, 0)); + } + // incoming state: // rcx: method handle // r13 or rsi: saved sp // To avoid calling convention issues, build a record on the stack and pass the pointer to that instead. + // Note: fix the increment below if pushing more arguments __ push(rbp); // saved_bp - __ push(rsi); // saved_sp - __ push(rax); // entry_sp + __ push(saved_last_sp_register()); // saved_sp + __ push(rbp); // entry_sp (with extra align space) __ push(rbx); // pusha saved_regs __ push(rcx); // mh - __ push(rcx); // adaptername + __ push(rcx); // slot for adaptername __ movptr(Address(rsp, 0), (intptr_t) adaptername); __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper), rsp); - __ leave(); + __ increment(rsp, 6 * wordSize); // MethodHandleStubArguments + + if (UseSSE >= 2) { + __ movdbl(xmm0, Address(rsp, 0)); + } else if (UseSSE == 1) { + __ movflt(xmm0, Address(rsp, 0)); + } else { + __ fld_d(Address(rsp, 0)); + } + __ increment(rsp, 2 * wordSize); + __ popa(); - __ pop(rax); + __ leave(); BLOCK_COMMENT("} trace_method_handle"); } #endif //PRODUCT diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp index 9f8e1a56035..75573838020 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp @@ -225,7 +225,7 @@ class RicochetFrame { static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN; - static void describe(const frame* fr, FrameValues& values, int frame_no) NOT_DEBUG_RETURN; + static void describe(const frame* fr, FrameValues& values, int frame_no) PRODUCT_RETURN; }; // Additional helper methods for MethodHandles code generation: diff --git a/hotspot/src/cpu/zero/vm/frame_zero.cpp b/hotspot/src/cpu/zero/vm/frame_zero.cpp index 35b6e52e41e..85f023049bd 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.cpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp @@ -418,7 +418,7 @@ void ZeroFrame::identify_vp_word(int frame_index, } } -#ifdef ASSERT +#ifndef PRODUCT void frame::describe_pd(FrameValues& values, int frame_no) { diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 897c7276e5d..ad6778c77fc 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -1315,7 +1315,6 @@ bool frame::verify_return_pc(address x) { } #endif - #ifdef ASSERT void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const { assert(is_interpreted_frame(), "Not an interpreted frame"); @@ -1331,8 +1330,9 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const { guarantee((current - low_mark) % monitor_size == 0 , "Misaligned bottom of BasicObjectLock*"); guarantee( current >= low_mark , "Current BasicObjectLock* below than low_mark"); } +#endif - +#ifndef PRODUCT void frame::describe(FrameValues& values, int frame_no) { // boundaries: sp and the 'real' frame pointer values.describe(-1, sp(), err_msg("sp for #%d", frame_no), 1); @@ -1436,7 +1436,7 @@ StackFrameStream::StackFrameStream(JavaThread *thread, bool update) : _reg_map(t } -#ifdef ASSERT +#ifndef PRODUCT void FrameValues::describe(int owner, intptr_t* location, const char* description, int priority) { FrameValue fv; @@ -1449,6 +1449,7 @@ void FrameValues::describe(int owner, intptr_t* location, const char* descriptio } +#ifdef ASSERT void FrameValues::validate() { _values.sort(compare); bool error = false; @@ -1474,7 +1475,7 @@ void FrameValues::validate() { } assert(!error, "invalid layout"); } - +#endif // ASSERT void FrameValues::print(JavaThread* thread) { _values.sort(compare); @@ -1523,4 +1524,4 @@ void FrameValues::print(JavaThread* thread) { } } -#endif +#endif // ndef PRODUCT diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 02e06d160a4..c55380e574d 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -494,7 +494,7 @@ class frame VALUE_OBJ_CLASS_SPEC { }; -#ifdef ASSERT +#ifndef PRODUCT // A simple class to describe a location on the stack class FrameValue VALUE_OBJ_CLASS_SPEC { public: @@ -524,7 +524,9 @@ class FrameValues { // Used by frame functions to describe locations. void describe(int owner, intptr_t* location, const char* description, int priority = 0); +#ifdef ASSERT void validate(); +#endif void print(JavaThread* thread); }; From 84dda879d048496b737ce6cf6986035057228d85 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Thu, 26 Jan 2012 12:15:24 -0800 Subject: [PATCH 84/96] 7131259: compile_method and CompilationPolicy::event shouldn't be declared TRAPS Make sure that CompilationPolicy::event() doesn't throw exceptions Reviewed-by: kvn, never --- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 3 +- .../src/share/vm/compiler/compileBroker.cpp | 12 ++--- .../src/share/vm/compiler/compileBroker.hpp | 4 +- .../vm/interpreter/interpreterRuntime.cpp | 2 + .../vm/runtime/advancedThresholdPolicy.cpp | 29 +++++------ .../vm/runtime/advancedThresholdPolicy.hpp | 8 +-- .../share/vm/runtime/compilationPolicy.cpp | 49 +++++++++---------- .../share/vm/runtime/compilationPolicy.hpp | 16 +++--- .../vm/runtime/simpleThresholdPolicy.cpp | 34 ++++++------- .../vm/runtime/simpleThresholdPolicy.hpp | 10 ++-- hotspot/src/share/vm/utilities/exceptions.hpp | 8 ++- 11 files changed, 88 insertions(+), 87 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 183be88c731..9937e9d6205 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -413,8 +413,9 @@ static nmethod* counter_overflow_helper(JavaThread* THREAD, int branch_bci, meth } bci = branch_bci + offset; } - + assert(!HAS_PENDING_EXCEPTION, "Should not have any exceptions pending"); osr_nm = CompilationPolicy::policy()->event(enclosing_method, method, branch_bci, bci, level, nm, THREAD); + assert(!HAS_PENDING_EXCEPTION, "Event handler should not throw any exceptions"); return osr_nm; } diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 4c3850936d3..58b75d7d75e 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -961,7 +961,7 @@ void CompileBroker::compile_method_base(methodHandle method, methodHandle hot_method, int hot_count, const char* comment, - TRAPS) { + Thread* thread) { // do nothing if compiler thread(s) is not available if (!_initialized ) { return; @@ -1037,7 +1037,7 @@ void CompileBroker::compile_method_base(methodHandle method, // Acquire our lock. { - MutexLocker locker(queue->lock(), THREAD); + MutexLocker locker(queue->lock(), thread); // Make sure the method has not slipped into the queues since // last we checked; note that those checks were "fast bail-outs". @@ -1119,7 +1119,7 @@ void CompileBroker::compile_method_base(methodHandle method, nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, int comp_level, methodHandle hot_method, int hot_count, - const char* comment, TRAPS) { + const char* comment, Thread* THREAD) { // make sure arguments make sense assert(method->method_holder()->klass_part()->oop_is_instance(), "not an instance method"); assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); @@ -1173,10 +1173,10 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, assert(!HAS_PENDING_EXCEPTION, "No exception should be present"); // some prerequisites that are compiler specific if (compiler(comp_level)->is_c2() || compiler(comp_level)->is_shark()) { - method->constants()->resolve_string_constants(CHECK_0); + method->constants()->resolve_string_constants(CHECK_AND_CLEAR_NULL); // Resolve all classes seen in the signature of the method // we are compiling. - methodOopDesc::load_signature_classes(method, CHECK_0); + methodOopDesc::load_signature_classes(method, CHECK_AND_CLEAR_NULL); } // If the method is native, do the lookup in the thread requesting @@ -1230,7 +1230,7 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, return NULL; } } else { - compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, CHECK_0); + compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, THREAD); } // return requested nmethod diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index 7abc37e54dd..ed559270fba 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -333,7 +333,7 @@ class CompileBroker: AllStatic { methodHandle hot_method, int hot_count, const char* comment, - TRAPS); + Thread* thread); static CompileQueue* compile_queue(int comp_level) { if (is_c2_compile(comp_level)) return _c2_method_queue; if (is_c1_compile(comp_level)) return _c1_method_queue; @@ -363,7 +363,7 @@ class CompileBroker: AllStatic { int comp_level, methodHandle hot_method, int hot_count, - const char* comment, TRAPS); + const char* comment, Thread* thread); static void compiler_thread_loop(); diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index c3eb879b9e3..e1c166587dd 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -859,7 +859,9 @@ IRT_ENTRY(nmethod*, const int branch_bci = branch_bcp != NULL ? method->bci_from(branch_bcp) : InvocationEntryBci; const int bci = branch_bcp != NULL ? method->bci_from(fr.interpreter_frame_bcp()) : InvocationEntryBci; + assert(!HAS_PENDING_EXCEPTION, "Should not have any exceptions pending"); nmethod* osr_nm = CompilationPolicy::policy()->event(method, method, branch_bci, bci, CompLevel_none, NULL, thread); + assert(!HAS_PENDING_EXCEPTION, "Event handler should not throw any exceptions"); if (osr_nm != NULL) { // We may need to do on-stack replacement which requires that no diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp index a7dab0b651b..29453b8cb1d 100644 --- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp @@ -271,13 +271,10 @@ bool AdvancedThresholdPolicy::should_not_inline(ciEnv* env, ciMethod* callee) { } // Create MDO if necessary. -void AdvancedThresholdPolicy::create_mdo(methodHandle mh, TRAPS) { +void AdvancedThresholdPolicy::create_mdo(methodHandle mh, JavaThread* THREAD) { if (mh->is_native() || mh->is_abstract() || mh->is_accessor()) return; if (mh->method_data() == NULL) { - methodOopDesc::build_interpreter_method_data(mh, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - } + methodOopDesc::build_interpreter_method_data(mh, CHECK_AND_CLEAR); } } @@ -426,22 +423,22 @@ CompLevel AdvancedThresholdPolicy::loop_event(methodOop method, CompLevel cur_le } // Update the rate and submit compile -void AdvancedThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel level, TRAPS) { +void AdvancedThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread) { int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count(); update_rate(os::javaTimeMillis(), mh()); - CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", THREAD); + CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", thread); } // Handle the invocation event. void AdvancedThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh, - CompLevel level, nmethod* nm, TRAPS) { + CompLevel level, nmethod* nm, JavaThread* thread) { if (should_create_mdo(mh(), level)) { - create_mdo(mh, THREAD); + create_mdo(mh, thread); } if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, InvocationEntryBci)) { CompLevel next_level = call_event(mh(), level); if (next_level != level) { - compile(mh, InvocationEntryBci, next_level, THREAD); + compile(mh, InvocationEntryBci, next_level, thread); } } } @@ -449,13 +446,13 @@ void AdvancedThresholdPolicy::method_invocation_event(methodHandle mh, methodHan // Handle the back branch event. Notice that we can compile the method // with a regular entry from here. void AdvancedThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh, - int bci, CompLevel level, nmethod* nm, TRAPS) { + int bci, CompLevel level, nmethod* nm, JavaThread* thread) { if (should_create_mdo(mh(), level)) { - create_mdo(mh, THREAD); + create_mdo(mh, thread); } // Check if MDO should be created for the inlined method if (should_create_mdo(imh(), level)) { - create_mdo(imh, THREAD); + create_mdo(imh, thread); } if (is_compilation_enabled()) { @@ -463,7 +460,7 @@ void AdvancedThresholdPolicy::method_back_branch_event(methodHandle mh, methodHa CompLevel max_osr_level = (CompLevel)imh->highest_osr_comp_level(); // At the very least compile the OSR version if (!CompileBroker::compilation_is_in_queue(imh, bci) && next_osr_level != level) { - compile(imh, bci, next_osr_level, THREAD); + compile(imh, bci, next_osr_level, thread); } // Use loop event as an opportunity to also check if there's been @@ -502,14 +499,14 @@ void AdvancedThresholdPolicy::method_back_branch_event(methodHandle mh, methodHa next_level = CompLevel_full_profile; } if (cur_level != next_level) { - compile(mh, InvocationEntryBci, next_level, THREAD); + compile(mh, InvocationEntryBci, next_level, thread); } } } else { cur_level = comp_level(imh()); next_level = call_event(imh(), cur_level); if (!CompileBroker::compilation_is_in_queue(imh, bci) && next_level != cur_level) { - compile(imh, InvocationEntryBci, next_level, THREAD); + compile(imh, InvocationEntryBci, next_level, thread); } } } diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp index 58be8b2dc91..71268774c3b 100644 --- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp +++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp @@ -197,7 +197,7 @@ class AdvancedThresholdPolicy : public SimpleThresholdPolicy { // determines whether we should do that. inline bool should_create_mdo(methodOop method, CompLevel cur_level); // Create MDO if necessary. - void create_mdo(methodHandle mh, TRAPS); + void create_mdo(methodHandle mh, JavaThread* thread); // Is method profiled enough? bool is_method_profiled(methodOop method); @@ -208,12 +208,12 @@ protected: jlong start_time() const { return _start_time; } // Submit a given method for compilation (and update the rate). - virtual void submit_compile(methodHandle mh, int bci, CompLevel level, TRAPS); + virtual void submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread); // event() from SimpleThresholdPolicy would call these. virtual void method_invocation_event(methodHandle method, methodHandle inlinee, - CompLevel level, nmethod* nm, TRAPS); + CompLevel level, nmethod* nm, JavaThread* thread); virtual void method_back_branch_event(methodHandle method, methodHandle inlinee, - int bci, CompLevel level, nmethod* nm, TRAPS); + int bci, CompLevel level, nmethod* nm, JavaThread* thread); public: AdvancedThresholdPolicy() : _start_time(0) { } // Select task is called by CompileBroker. We should return a task or NULL. diff --git a/hotspot/src/share/vm/runtime/compilationPolicy.cpp b/hotspot/src/share/vm/runtime/compilationPolicy.cpp index 61f113037b3..dadfb1e4801 100644 --- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp +++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp @@ -306,29 +306,27 @@ bool NonTieredCompPolicy::is_mature(methodOop method) { return (current >= initial + target); } -nmethod* NonTieredCompPolicy::event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, TRAPS) { +nmethod* NonTieredCompPolicy::event(methodHandle method, methodHandle inlinee, int branch_bci, + int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) { assert(comp_level == CompLevel_none, "This should be only called from the interpreter"); NOT_PRODUCT(trace_frequency_counter_overflow(method, branch_bci, bci)); - if (JvmtiExport::can_post_interpreter_events()) { - assert(THREAD->is_Java_thread(), "Wrong type of thread"); - if (((JavaThread*)THREAD)->is_interp_only_mode()) { - // If certain JVMTI events (e.g. frame pop event) are requested then the - // thread is forced to remain in interpreted code. This is - // implemented partly by a check in the run_compiled_code - // section of the interpreter whether we should skip running - // compiled code, and partly by skipping OSR compiles for - // interpreted-only threads. - if (bci != InvocationEntryBci) { - reset_counter_for_back_branch_event(method); - return NULL; - } + if (JvmtiExport::can_post_interpreter_events() && thread->is_interp_only_mode()) { + // If certain JVMTI events (e.g. frame pop event) are requested then the + // thread is forced to remain in interpreted code. This is + // implemented partly by a check in the run_compiled_code + // section of the interpreter whether we should skip running + // compiled code, and partly by skipping OSR compiles for + // interpreted-only threads. + if (bci != InvocationEntryBci) { + reset_counter_for_back_branch_event(method); + return NULL; } } if (bci == InvocationEntryBci) { // when code cache is full, compilation gets switched off, UseCompiler // is set to false if (!method->has_compiled_code() && UseCompiler) { - method_invocation_event(method, CHECK_NULL); + method_invocation_event(method, thread); } else { // Force counter overflow on method entry, even if no compilation // happened. (The method_invocation_event call does this also.) @@ -344,7 +342,7 @@ nmethod* NonTieredCompPolicy::event(methodHandle method, methodHandle inlinee, i NOT_PRODUCT(trace_osr_request(method, osr_nm, bci)); // when code cache is full, we should not compile any more... if (osr_nm == NULL && UseCompiler) { - method_back_branch_event(method, bci, CHECK_NULL); + method_back_branch_event(method, bci, thread); osr_nm = method->lookup_osr_nmethod_for(bci, CompLevel_highest_tier, true); } if (osr_nm == NULL) { @@ -395,7 +393,7 @@ void NonTieredCompPolicy::trace_osr_request(methodHandle method, nmethod* osr, i // SimpleCompPolicy - compile current method -void SimpleCompPolicy::method_invocation_event( methodHandle m, TRAPS) { +void SimpleCompPolicy::method_invocation_event(methodHandle m, JavaThread* thread) { int hot_count = m->invocation_count(); reset_counter_for_invocation_event(m); const char* comment = "count"; @@ -405,18 +403,18 @@ void SimpleCompPolicy::method_invocation_event( methodHandle m, TRAPS) { if (nm == NULL ) { const char* comment = "count"; CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_highest_tier, - m, hot_count, comment, CHECK); + m, hot_count, comment, thread); } } } -void SimpleCompPolicy::method_back_branch_event(methodHandle m, int bci, TRAPS) { +void SimpleCompPolicy::method_back_branch_event(methodHandle m, int bci, JavaThread* thread) { int hot_count = m->backedge_count(); const char* comment = "backedge_count"; if (is_compilation_enabled() && !m->is_not_osr_compilable() && can_be_compiled(m)) { CompileBroker::compile_method(m, bci, CompLevel_highest_tier, - m, hot_count, comment, CHECK); + m, hot_count, comment, thread); NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, CompLevel_highest_tier, true));) } } @@ -427,14 +425,13 @@ const char* StackWalkCompPolicy::_msg = NULL; // Consider m for compilation -void StackWalkCompPolicy::method_invocation_event(methodHandle m, TRAPS) { +void StackWalkCompPolicy::method_invocation_event(methodHandle m, JavaThread* thread) { int hot_count = m->invocation_count(); reset_counter_for_invocation_event(m); const char* comment = "count"; if (is_compilation_enabled() && m->code() == NULL && can_be_compiled(m)) { - ResourceMark rm(THREAD); - JavaThread *thread = (JavaThread*)THREAD; + ResourceMark rm(thread); frame fr = thread->last_frame(); assert(fr.is_interpreted_frame(), "must be interpreted"); assert(fr.interpreter_frame_method() == m(), "bad method"); @@ -461,17 +458,17 @@ void StackWalkCompPolicy::method_invocation_event(methodHandle m, TRAPS) { assert(top != NULL, "findTopInlinableFrame returned null"); if (TraceCompilationPolicy) top->print(); CompileBroker::compile_method(top->top_method(), InvocationEntryBci, CompLevel_highest_tier, - m, hot_count, comment, CHECK); + m, hot_count, comment, thread); } } } -void StackWalkCompPolicy::method_back_branch_event(methodHandle m, int bci, TRAPS) { +void StackWalkCompPolicy::method_back_branch_event(methodHandle m, int bci, JavaThread* thread) { int hot_count = m->backedge_count(); const char* comment = "backedge_count"; if (is_compilation_enabled() && !m->is_not_osr_compilable() && can_be_compiled(m)) { - CompileBroker::compile_method(m, bci, CompLevel_highest_tier, m, hot_count, comment, CHECK); + CompileBroker::compile_method(m, bci, CompLevel_highest_tier, m, hot_count, comment, thread); NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, CompLevel_highest_tier, true));) } diff --git a/hotspot/src/share/vm/runtime/compilationPolicy.hpp b/hotspot/src/share/vm/runtime/compilationPolicy.hpp index b9d70664b98..1d8427cf2fd 100644 --- a/hotspot/src/share/vm/runtime/compilationPolicy.hpp +++ b/hotspot/src/share/vm/runtime/compilationPolicy.hpp @@ -64,7 +64,7 @@ public: virtual int compiler_count(CompLevel comp_level) = 0; // main notification entry, return a pointer to an nmethod if the OSR is required, // returns NULL otherwise. - virtual nmethod* event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, TRAPS) = 0; + virtual nmethod* event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) = 0; // safepoint() is called at the end of the safepoint virtual void do_safepoint_work() = 0; // reprofile request @@ -105,15 +105,15 @@ public: virtual bool is_mature(methodOop method); virtual void initialize(); virtual CompileTask* select_task(CompileQueue* compile_queue); - virtual nmethod* event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, TRAPS); - virtual void method_invocation_event(methodHandle m, TRAPS) = 0; - virtual void method_back_branch_event(methodHandle m, int bci, TRAPS) = 0; + virtual nmethod* event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread); + virtual void method_invocation_event(methodHandle m, JavaThread* thread) = 0; + virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread) = 0; }; class SimpleCompPolicy : public NonTieredCompPolicy { public: - virtual void method_invocation_event(methodHandle m, TRAPS); - virtual void method_back_branch_event(methodHandle m, int bci, TRAPS); + virtual void method_invocation_event(methodHandle m, JavaThread* thread); + virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread); }; // StackWalkCompPolicy - existing C2 policy @@ -121,8 +121,8 @@ class SimpleCompPolicy : public NonTieredCompPolicy { #ifdef COMPILER2 class StackWalkCompPolicy : public NonTieredCompPolicy { public: - virtual void method_invocation_event(methodHandle m, TRAPS); - virtual void method_back_branch_event(methodHandle m, int bci, TRAPS); + virtual void method_invocation_event(methodHandle m, JavaThread* thread); + virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread); private: RFrame* findTopInlinableFrame(GrowableArray* stack); diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp index 232da70b077..0ebc560a58a 100644 --- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp @@ -177,13 +177,11 @@ void SimpleThresholdPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) { } nmethod* SimpleThresholdPolicy::event(methodHandle method, methodHandle inlinee, - int branch_bci, int bci, CompLevel comp_level, nmethod* nm, TRAPS) { + int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) { if (comp_level == CompLevel_none && - JvmtiExport::can_post_interpreter_events()) { - assert(THREAD->is_Java_thread(), "Should be java thread"); - if (((JavaThread*)THREAD)->is_interp_only_mode()) { - return NULL; - } + JvmtiExport::can_post_interpreter_events() && + thread->is_interp_only_mode()) { + return NULL; } nmethod *osr_nm = NULL; @@ -197,9 +195,9 @@ nmethod* SimpleThresholdPolicy::event(methodHandle method, methodHandle inlinee, } if (bci == InvocationEntryBci) { - method_invocation_event(method, inlinee, comp_level, nm, THREAD); + method_invocation_event(method, inlinee, comp_level, nm, thread); } else { - method_back_branch_event(method, inlinee, bci, comp_level, nm, THREAD); + method_back_branch_event(method, inlinee, bci, comp_level, nm, thread); // method == inlinee if the event originated in the main method int highest_level = inlinee->highest_osr_comp_level(); if (highest_level > comp_level) { @@ -210,7 +208,7 @@ nmethod* SimpleThresholdPolicy::event(methodHandle method, methodHandle inlinee, } // Check if the method can be compiled, change level if necessary -void SimpleThresholdPolicy::compile(methodHandle mh, int bci, CompLevel level, TRAPS) { +void SimpleThresholdPolicy::compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread) { assert(level <= TieredStopAtLevel, "Invalid compilation level"); if (level == CompLevel_none) { return; @@ -221,7 +219,7 @@ void SimpleThresholdPolicy::compile(methodHandle mh, int bci, CompLevel level, T // pure C1. if (!can_be_compiled(mh, level)) { if (level == CompLevel_full_optimization && can_be_compiled(mh, CompLevel_simple)) { - compile(mh, bci, CompLevel_simple, THREAD); + compile(mh, bci, CompLevel_simple, thread); } return; } @@ -232,14 +230,14 @@ void SimpleThresholdPolicy::compile(methodHandle mh, int bci, CompLevel level, T if (PrintTieredEvents) { print_event(COMPILE, mh, mh, bci, level); } - submit_compile(mh, bci, level, THREAD); + submit_compile(mh, bci, level, thread); } } // Tell the broker to compile the method -void SimpleThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel level, TRAPS) { +void SimpleThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread) { int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count(); - CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", THREAD); + CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", thread); } // Call and loop predicates determine whether a transition to a higher @@ -366,11 +364,11 @@ CompLevel SimpleThresholdPolicy::loop_event(methodOop method, CompLevel cur_leve // Handle the invocation event. void SimpleThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh, - CompLevel level, nmethod* nm, TRAPS) { + CompLevel level, nmethod* nm, JavaThread* thread) { if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, InvocationEntryBci)) { CompLevel next_level = call_event(mh(), level); if (next_level != level) { - compile(mh, InvocationEntryBci, next_level, THREAD); + compile(mh, InvocationEntryBci, next_level, thread); } } } @@ -378,7 +376,7 @@ void SimpleThresholdPolicy::method_invocation_event(methodHandle mh, methodHandl // Handle the back branch event. Notice that we can compile the method // with a regular entry from here. void SimpleThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh, - int bci, CompLevel level, nmethod* nm, TRAPS) { + int bci, CompLevel level, nmethod* nm, JavaThread* thread) { // If the method is already compiling, quickly bail out. if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh, bci)) { // Use loop event as an opportinity to also check there's been @@ -391,13 +389,13 @@ void SimpleThresholdPolicy::method_back_branch_event(methodHandle mh, methodHand next_osr_level < CompLevel_full_optimization ? next_osr_level : cur_level); bool is_compiling = false; if (next_level != cur_level) { - compile(mh, InvocationEntryBci, next_level, THREAD); + compile(mh, InvocationEntryBci, next_level, thread); is_compiling = true; } // Do the OSR version if (!is_compiling && next_osr_level != level) { - compile(mh, bci, next_osr_level, THREAD); + compile(mh, bci, next_osr_level, thread); } } } diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp index 1cff0c6cd67..e22819808f6 100644 --- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp @@ -67,9 +67,9 @@ protected: // Print policy-specific information if necessary virtual void print_specific(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level) { } // Check if the method can be compiled, change level if necessary - void compile(methodHandle mh, int bci, CompLevel level, TRAPS); + void compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread); // Submit a given method for compilation - virtual void submit_compile(methodHandle mh, int bci, CompLevel level, TRAPS); + virtual void submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread); // Simple methods are as good being compiled with C1 as C2. // This function tells if it's such a function. inline bool is_trivial(methodOop method); @@ -88,9 +88,9 @@ protected: return CompLevel_none; } virtual void method_invocation_event(methodHandle method, methodHandle inlinee, - CompLevel level, nmethod* nm, TRAPS); + CompLevel level, nmethod* nm, JavaThread* thread); virtual void method_back_branch_event(methodHandle method, methodHandle inlinee, - int bci, CompLevel level, nmethod* nm, TRAPS); + int bci, CompLevel level, nmethod* nm, JavaThread* thread); public: SimpleThresholdPolicy() : _c1_count(0), _c2_count(0) { } virtual int compiler_count(CompLevel comp_level) { @@ -104,7 +104,7 @@ public: virtual void disable_compilation(methodOop method) { } virtual void reprofile(ScopeDesc* trap_scope, bool is_osr); virtual nmethod* event(methodHandle method, methodHandle inlinee, - int branch_bci, int bci, CompLevel comp_level, nmethod* nm, TRAPS); + int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread); // Select task is called by CompileBroker. We should return a task or NULL. virtual CompileTask* select_task(CompileQueue* compile_queue); // Tell the runtime if we think a given method is adequately profiled. diff --git a/hotspot/src/share/vm/utilities/exceptions.hpp b/hotspot/src/share/vm/utilities/exceptions.hpp index f4ad5dd1c89..f7fece16fb6 100644 --- a/hotspot/src/share/vm/utilities/exceptions.hpp +++ b/hotspot/src/share/vm/utilities/exceptions.hpp @@ -189,6 +189,13 @@ class Exceptions { #define CHECK_NULL CHECK_(NULL) #define CHECK_false CHECK_(false) +#define CHECK_AND_CLEAR THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return; } (0 +#define CHECK_AND_CLEAR_(result) THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return result; } (0 +#define CHECK_AND_CLEAR_0 CHECK_AND_CLEAR_(0) +#define CHECK_AND_CLEAR_NH CHECK_AND_CLEAR_(Handle()) +#define CHECK_AND_CLEAR_NULL CHECK_AND_CLEAR_(NULL) +#define CHECK_AND_CLEAR_false CHECK_AND_CLEAR_(false) + // The THROW... macros should be used to throw an exception. They require a THREAD variable to be // visible within the scope containing the THROW. Usually this is achieved by declaring the function // with a TRAPS argument. @@ -258,7 +265,6 @@ class Exceptions { ShouldNotReachHere(); \ } (0 - // ExceptionMark is a stack-allocated helper class for local exception handling. // It is used with the EXCEPTION_MARK macro. From 179d6df8c01c3acf4614dd45efdf1ab06c555135 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Thu, 26 Jan 2012 14:14:55 -0800 Subject: [PATCH 85/96] 7133038: G1: Some small profile based optimizations Some minor profile based optimizations. Reduce the number of branches and branch mispredicts by removing some virtual calls, through closure specalization, and refactoring some conditional statements. Reviewed-by: brutisso, tonyp --- .../vm/gc_implementation/g1/g1OopClosures.hpp | 73 +++++++++++++++++ .../g1/g1OopClosures.inline.hpp | 81 +++++++++++++++++++ .../vm/gc_implementation/g1/g1RemSet.cpp | 70 +++++++--------- .../vm/gc_implementation/g1/g1RemSet.hpp | 41 +--------- .../gc_implementation/g1/g1RemSet.inline.hpp | 64 +-------------- .../g1/g1_specialized_oop_closures.hpp | 24 ++++-- .../vm/gc_implementation/g1/heapRegion.cpp | 60 ++++++++------ 7 files changed, 238 insertions(+), 175 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index f7ccb79cf3e..52a6c50665b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -246,4 +246,77 @@ public: virtual void do_oop(narrowOop* p) { do_oop_nv(p); } }; +// Closure that applies the given two closures in sequence. +// Used by the RSet refinement code (when updating RSets +// during an evacuation pause) to record cards containing +// pointers into the collection set. + +class G1Mux2Closure : public OopClosure { + OopClosure* _c1; + OopClosure* _c2; +public: + G1Mux2Closure(OopClosure *c1, OopClosure *c2); + template void do_oop_nv(T* p); + virtual void do_oop(oop* p) { do_oop_nv(p); } + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } +}; + +// A closure that returns true if it is actually applied +// to a reference + +class G1TriggerClosure : public OopClosure { + bool _triggered; +public: + G1TriggerClosure(); + bool triggered() const { return _triggered; } + template void do_oop_nv(T* p); + virtual void do_oop(oop* p) { do_oop_nv(p); } + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } +}; + +// A closure which uses a triggering closure to determine +// whether to apply an oop closure. + +class G1InvokeIfNotTriggeredClosure: public OopClosure { + G1TriggerClosure* _trigger_cl; + OopClosure* _oop_cl; +public: + G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t, OopClosure* oc); + template void do_oop_nv(T* p); + virtual void do_oop(oop* p) { do_oop_nv(p); } + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } +}; + +class G1UpdateRSOrPushRefOopClosure: public OopClosure { + G1CollectedHeap* _g1; + G1RemSet* _g1_rem_set; + HeapRegion* _from; + OopsInHeapRegionClosure* _push_ref_cl; + bool _record_refs_into_cset; + int _worker_i; + +public: + G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, + G1RemSet* rs, + OopsInHeapRegionClosure* push_ref_cl, + bool record_refs_into_cset, + int worker_i = 0); + + void set_from(HeapRegion* from) { + assert(from != NULL, "from region must be non-NULL"); + _from = from; + } + + bool self_forwarded(oop obj) { + bool result = (obj->is_forwarded() && (obj->forwardee()== obj)); + return result; + } + + bool apply_to_weak_ref_discovered_field() { return true; } + + template void do_oop_nv(T* p); + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } + virtual void do_oop(oop* p) { do_oop_nv(p); } +}; + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp index 5db2340bc07..18a9c02510c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp @@ -142,4 +142,85 @@ inline void G1RootRegionScanClosure::do_oop_nv(T* p) { } } +template +inline void G1Mux2Closure::do_oop_nv(T* p) { + // Apply first closure; then apply the second. + _c1->do_oop(p); + _c2->do_oop(p); +} + +template +inline void G1TriggerClosure::do_oop_nv(T* p) { + // Record that this closure was actually applied (triggered). + _triggered = true; +} + +template +inline void G1InvokeIfNotTriggeredClosure::do_oop_nv(T* p) { + if (!_trigger_cl->triggered()) { + _oop_cl->do_oop(p); + } +} + +template +inline void G1UpdateRSOrPushRefOopClosure::do_oop_nv(T* p) { + oop obj = oopDesc::load_decode_heap_oop(p); +#ifdef ASSERT + // can't do because of races + // assert(obj == NULL || obj->is_oop(), "expected an oop"); + + // Do the safe subset of is_oop + if (obj != NULL) { +#ifdef CHECK_UNHANDLED_OOPS + oopDesc* o = obj.obj(); +#else + oopDesc* o = obj; +#endif // CHECK_UNHANDLED_OOPS + assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned"); + assert(Universe::heap()->is_in_reserved(obj), "must be in heap"); + } +#endif // ASSERT + + assert(_from != NULL, "from region must be non-NULL"); + + HeapRegion* to = _g1->heap_region_containing(obj); + if (to != NULL && _from != to) { + // The _record_refs_into_cset flag is true during the RSet + // updating part of an evacuation pause. It is false at all + // other times: + // * rebuilding the rembered sets after a full GC + // * during concurrent refinement. + // * updating the remembered sets of regions in the collection + // set in the event of an evacuation failure (when deferred + // updates are enabled). + + if (_record_refs_into_cset && to->in_collection_set()) { + // We are recording references that point into the collection + // set and this particular reference does exactly that... + // If the referenced object has already been forwarded + // to itself, we are handling an evacuation failure and + // we have already visited/tried to copy this object + // there is no need to retry. + if (!self_forwarded(obj)) { + assert(_push_ref_cl != NULL, "should not be null"); + // Push the reference in the refs queue of the G1ParScanThreadState + // instance for this worker thread. + _push_ref_cl->do_oop(p); + } + + // Deferred updates to the CSet are either discarded (in the normal case), + // or processed (if an evacuation failure occurs) at the end + // of the collection. + // See G1RemSet::cleanup_after_oops_into_collection_set_do(). + } else { + // We either don't care about pushing references that point into the + // collection set (i.e. we're not during an evacuation pause) _or_ + // the reference doesn't point into the collection set. Either way + // we add the reference directly to the RSet of the region containing + // the referenced object. + _g1_rem_set->par_write_ref(_from, p, _worker_i); + } + } +} + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 4a98258b996..1f366c8c676 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -569,40 +569,26 @@ void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm, static IntHistogram out_of_histo(50, 50); -class TriggerClosure : public OopClosure { - bool _trigger; -public: - TriggerClosure() : _trigger(false) { } - bool value() const { return _trigger; } - template void do_oop_nv(T* p) { _trigger = true; } - virtual void do_oop(oop* p) { do_oop_nv(p); } - virtual void do_oop(narrowOop* p) { do_oop_nv(p); } -}; -class InvokeIfNotTriggeredClosure: public OopClosure { - TriggerClosure* _t; - OopClosure* _oc; -public: - InvokeIfNotTriggeredClosure(TriggerClosure* t, OopClosure* oc): - _t(t), _oc(oc) { } - template void do_oop_nv(T* p) { - if (!_t->value()) _oc->do_oop(p); - } - virtual void do_oop(oop* p) { do_oop_nv(p); } - virtual void do_oop(narrowOop* p) { do_oop_nv(p); } -}; +G1TriggerClosure::G1TriggerClosure() : + _triggered(false) { } -class Mux2Closure : public OopClosure { - OopClosure* _c1; - OopClosure* _c2; -public: - Mux2Closure(OopClosure *c1, OopClosure *c2) : _c1(c1), _c2(c2) { } - template void do_oop_nv(T* p) { - _c1->do_oop(p); _c2->do_oop(p); - } - virtual void do_oop(oop* p) { do_oop_nv(p); } - virtual void do_oop(narrowOop* p) { do_oop_nv(p); } -}; +G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl, + OopClosure* oop_cl) : + _trigger_cl(t_cl), _oop_cl(oop_cl) { } + +G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) : + _c1(c1), _c2(c2) { } + +G1UpdateRSOrPushRefOopClosure:: +G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, + G1RemSet* rs, + OopsInHeapRegionClosure* push_ref_cl, + bool record_refs_into_cset, + int worker_i) : + _g1(g1h), _g1_rem_set(rs), _from(NULL), + _record_refs_into_cset(record_refs_into_cset), + _push_ref_cl(push_ref_cl), _worker_i(worker_i) { } bool G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i, bool check_for_refs_into_cset) { @@ -629,17 +615,17 @@ bool G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i, assert((size_t)worker_i < n_workers(), "index of worker larger than _cset_rs_update_cl[].length"); oops_in_heap_closure = _cset_rs_update_cl[worker_i]; } - UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1, - _g1->g1_rem_set(), - oops_in_heap_closure, - check_for_refs_into_cset, - worker_i); + G1UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1, + _g1->g1_rem_set(), + oops_in_heap_closure, + check_for_refs_into_cset, + worker_i); update_rs_oop_cl.set_from(r); - TriggerClosure trigger_cl; + G1TriggerClosure trigger_cl; FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl); - InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl); - Mux2Closure mux(&invoke_cl, &update_rs_oop_cl); + G1InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl); + G1Mux2Closure mux(&invoke_cl, &update_rs_oop_cl); FilterOutOfRegionClosure filter_then_update_rs_oop_cl(r, (check_for_refs_into_cset ? @@ -688,7 +674,7 @@ bool G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i, _conc_refine_cards++; } - return trigger_cl.value(); + return trigger_cl.triggered(); } bool G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i, diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp index 79d550ef27d..9c869055afd 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -191,44 +191,5 @@ public: virtual void do_oop( oop* p) { do_oop_work(p); } }; -class UpdateRSOrPushRefOopClosure: public OopClosure { - G1CollectedHeap* _g1; - G1RemSet* _g1_rem_set; - HeapRegion* _from; - OopsInHeapRegionClosure* _push_ref_cl; - bool _record_refs_into_cset; - int _worker_i; - - template void do_oop_work(T* p); - -public: - UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, - G1RemSet* rs, - OopsInHeapRegionClosure* push_ref_cl, - bool record_refs_into_cset, - int worker_i = 0) : - _g1(g1h), - _g1_rem_set(rs), - _from(NULL), - _record_refs_into_cset(record_refs_into_cset), - _push_ref_cl(push_ref_cl), - _worker_i(worker_i) { } - - void set_from(HeapRegion* from) { - assert(from != NULL, "from region must be non-NULL"); - _from = from; - } - - bool self_forwarded(oop obj) { - bool result = (obj->is_forwarded() && (obj->forwardee()== obj)); - return result; - } - - virtual void do_oop(narrowOop* p) { do_oop_work(p); } - virtual void do_oop(oop* p) { do_oop_work(p); } - - bool apply_to_weak_ref_discovered_field() { return true; } -}; - #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp index 7491e3a8509..79f4df9251a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,66 +85,4 @@ inline void UpdateRSetImmediate::do_oop_work(T* p) { } } -template -inline void UpdateRSOrPushRefOopClosure::do_oop_work(T* p) { - oop obj = oopDesc::load_decode_heap_oop(p); -#ifdef ASSERT - // can't do because of races - // assert(obj == NULL || obj->is_oop(), "expected an oop"); - - // Do the safe subset of is_oop - if (obj != NULL) { -#ifdef CHECK_UNHANDLED_OOPS - oopDesc* o = obj.obj(); -#else - oopDesc* o = obj; -#endif // CHECK_UNHANDLED_OOPS - assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned"); - assert(Universe::heap()->is_in_reserved(obj), "must be in heap"); - } -#endif // ASSERT - - assert(_from != NULL, "from region must be non-NULL"); - - HeapRegion* to = _g1->heap_region_containing(obj); - if (to != NULL && _from != to) { - // The _record_refs_into_cset flag is true during the RSet - // updating part of an evacuation pause. It is false at all - // other times: - // * rebuilding the rembered sets after a full GC - // * during concurrent refinement. - // * updating the remembered sets of regions in the collection - // set in the event of an evacuation failure (when deferred - // updates are enabled). - - if (_record_refs_into_cset && to->in_collection_set()) { - // We are recording references that point into the collection - // set and this particular reference does exactly that... - // If the referenced object has already been forwarded - // to itself, we are handling an evacuation failure and - // we have already visited/tried to copy this object - // there is no need to retry. - if (!self_forwarded(obj)) { - assert(_push_ref_cl != NULL, "should not be null"); - // Push the reference in the refs queue of the G1ParScanThreadState - // instance for this worker thread. - _push_ref_cl->do_oop(p); - } - - // Deferred updates to the CSet are either discarded (in the normal case), - // or processed (if an evacuation failure occurs) at the end - // of the collection. - // See G1RemSet::cleanup_after_oops_into_collection_set_do(). - } else { - // We either don't care about pushing references that point into the - // collection set (i.e. we're not during an evacuation pause) _or_ - // the reference doesn't point into the collection set. Either way - // we add the reference directly to the RSet of the region containing - // the referenced object. - _g1_rem_set->par_write_ref(_from, p, _worker_i); - } - } -} - - #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_INLINE_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp index fea3e076d5e..910cc6df676 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,12 +32,14 @@ // Forward declarations. enum G1Barrier { - G1BarrierNone, G1BarrierRS, G1BarrierEvac + G1BarrierNone, + G1BarrierRS, + G1BarrierEvac }; -template +template class G1ParCopyClosure; + class G1ParScanClosure; class G1ParPushHeapRSClosure; @@ -46,6 +48,13 @@ typedef G1ParCopyClosure G1ParScanHeapEvacClosure; class FilterIntoCSClosure; class FilterOutOfRegionClosure; class G1CMOopClosure; +class G1RootRegionScanClosure; + +// Specialized oop closures from g1RemSet.cpp +class G1Mux2Closure; +class G1TriggerClosure; +class G1InvokeIfNotTriggeredClosure; +class G1UpdateRSOrPushRefOopClosure; #ifdef FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES #error "FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES already defined." @@ -57,7 +66,12 @@ class G1CMOopClosure; f(G1ParPushHeapRSClosure,_nv) \ f(FilterIntoCSClosure,_nv) \ f(FilterOutOfRegionClosure,_nv) \ - f(G1CMOopClosure,_nv) + f(G1CMOopClosure,_nv) \ + f(G1RootRegionScanClosure,_nv) \ + f(G1Mux2Closure,_nv) \ + f(G1TriggerClosure,_nv) \ + f(G1InvokeIfNotTriggeredClosure,_nv) \ + f(G1UpdateRSOrPushRefOopClosure,_nv) #ifdef FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES #error "FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES already defined." diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index 336e4cab5a6..e9766559895 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -659,7 +659,7 @@ oops_on_card_seq_iterate_careful(MemRegion mr, // If we're within a stop-world GC, then we might look at a card in a // GC alloc region that extends onto a GC LAB, which may not be // parseable. Stop such at the "saved_mark" of the region. - if (G1CollectedHeap::heap()->is_gc_active()) { + if (g1h->is_gc_active()) { mr = mr.intersection(used_region_at_save_marks()); } else { mr = mr.intersection(used_region()); @@ -688,53 +688,63 @@ oops_on_card_seq_iterate_careful(MemRegion mr, OrderAccess::storeload(); } + // Cache the boundaries of the memory region in some const locals + HeapWord* const start = mr.start(); + HeapWord* const end = mr.end(); + // We used to use "block_start_careful" here. But we're actually happy // to update the BOT while we do this... - HeapWord* cur = block_start(mr.start()); - assert(cur <= mr.start(), "Postcondition"); + HeapWord* cur = block_start(start); + assert(cur <= start, "Postcondition"); - while (cur <= mr.start()) { - if (oop(cur)->klass_or_null() == NULL) { + oop obj; + + HeapWord* next = cur; + while (next <= start) { + cur = next; + obj = oop(cur); + if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. return cur; } // Otherwise... - int sz = oop(cur)->size(); - if (cur + sz > mr.start()) break; - // Otherwise, go on. - cur = cur + sz; + next = (cur + obj->size()); } - oop obj; - obj = oop(cur); - // If we finish this loop... - assert(cur <= mr.start() - && obj->klass_or_null() != NULL - && cur + obj->size() > mr.start(), + + // If we finish the above loop...We have a parseable object that + // begins on or before the start of the memory region, and ends + // inside or spans the entire region. + + assert(obj == oop(cur), "sanity"); + assert(cur <= start && + obj->klass_or_null() != NULL && + (cur + obj->size()) > start, "Loop postcondition"); + if (!g1h->is_obj_dead(obj)) { obj->oop_iterate(cl, mr); } - HeapWord* next; - while (cur < mr.end()) { + while (cur < end) { obj = oop(cur); if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. return cur; }; + // Otherwise: next = (cur + obj->size()); + if (!g1h->is_obj_dead(obj)) { - if (next < mr.end()) { + if (next < end || !obj->is_objArray()) { + // This object either does not span the MemRegion + // boundary, or if it does it's not an array. + // Apply closure to whole object. obj->oop_iterate(cl); } else { - // this obj spans the boundary. If it's an array, stop at the - // boundary. - if (obj->is_objArray()) { - obj->oop_iterate(cl, mr); - } else { - obj->oop_iterate(cl); - } + // This obj is an array that spans the boundary. + // Stop at the boundary. + obj->oop_iterate(cl, mr); } } cur = next; From 09e21afaaa3ba4bc080b4617802a7e4b769ca043 Mon Sep 17 00:00:00 2001 From: Paul Hohensee Date: Thu, 26 Jan 2012 20:06:06 -0500 Subject: [PATCH 86/96] 7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11 Add CriticalPriority == MaxPriority+1 and enable scheduling class as well as thread priority to change on Solaris. Reviewed-by: dholmes, dcubed --- hotspot/src/os/bsd/vm/os_bsd.cpp | 35 ++- hotspot/src/os/linux/vm/os_linux.cpp | 11 +- .../src/os/solaris/vm/osThread_solaris.hpp | 27 +- hotspot/src/os/solaris/vm/os_solaris.cpp | 252 ++++++++++++------ hotspot/src/os/windows/vm/os_windows.cpp | 17 +- .../src/share/vm/compiler/compileBroker.cpp | 31 +-- .../concurrentMarkSweepThread.cpp | 25 +- hotspot/src/share/vm/runtime/globals.hpp | 24 +- hotspot/src/share/vm/runtime/os.hpp | 7 +- 9 files changed, 289 insertions(+), 140 deletions(-) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index d0603bb8e71..2611e9c1401 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3589,26 +3589,28 @@ void os::loop_breaker(int attempts) { // It is only used when ThreadPriorityPolicy=1 and requires root privilege. #if defined(_ALLBSD_SOURCE) && !defined(__APPLE__) -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { 19, // 0 Entry should never be used 0, // 1 MinPriority 3, // 2 6, // 3 - 10, // 4 - 15, // 5 NormPriority - 18, // 6 + 10, // 4 + 15, // 5 NormPriority + 18, // 6 - 21, // 7 - 25, // 8 - 28, // 9 NearMaxPriority + 21, // 7 + 25, // 8 + 28, // 9 NearMaxPriority - 31 // 10 MaxPriority + 31, // 10 MaxPriority + + 31 // 11 CriticalPriority }; #elif defined(__APPLE__) /* Using Mach high-level priority assignments */ -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { 0, // 0 Entry should never be used (MINPRI_USER) 27, // 1 MinPriority @@ -3623,10 +3625,12 @@ int os::java_to_os_priority[MaxPriority + 1] = { 34, // 8 35, // 9 NearMaxPriority - 36 // 10 MaxPriority + 36, // 10 MaxPriority + + 36 // 11 CriticalPriority }; #else -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { 19, // 0 Entry should never be used 4, // 1 MinPriority @@ -3641,7 +3645,9 @@ int os::java_to_os_priority[MaxPriority + 1] = { -3, // 8 -4, // 9 NearMaxPriority - -5 // 10 MaxPriority + -5, // 10 MaxPriority + + -5 // 11 CriticalPriority }; #endif @@ -3657,6 +3663,9 @@ static int prio_init() { ThreadPriorityPolicy = 0; } } + if (UseCriticalJavaThreadPriority) { + os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority]; + } return 0; } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index f2e1988137b..72f3fd07a6c 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3383,7 +3383,7 @@ void os::loop_breaker(int attempts) { // this reason, the code should not be used as default (ThreadPriorityPolicy=0). // It is only used when ThreadPriorityPolicy=1 and requires root privilege. -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { 19, // 0 Entry should never be used 4, // 1 MinPriority @@ -3398,7 +3398,9 @@ int os::java_to_os_priority[MaxPriority + 1] = { -3, // 8 -4, // 9 NearMaxPriority - -5 // 10 MaxPriority + -5, // 10 MaxPriority + + -5 // 11 CriticalPriority }; static int prio_init() { @@ -3413,6 +3415,9 @@ static int prio_init() { ThreadPriorityPolicy = 0; } } + if (UseCriticalJavaThreadPriority) { + os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority]; + } return 0; } diff --git a/hotspot/src/os/solaris/vm/osThread_solaris.hpp b/hotspot/src/os/solaris/vm/osThread_solaris.hpp index 07742ac8e40..7fe1417e342 100644 --- a/hotspot/src/os/solaris/vm/osThread_solaris.hpp +++ b/hotspot/src/os/solaris/vm/osThread_solaris.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,17 +28,17 @@ // This is embedded via include into the class OSThread private: - - thread_t _thread_id; // Solaris thread id - unsigned int _lwp_id; // lwp ID, only used with bound threads - sigset_t _caller_sigmask; // Caller's signal mask - bool _vm_created_thread; // true if the VM create this thread - // false if primary thread or attached thread + thread_t _thread_id; // Solaris thread id + uint _lwp_id; // lwp ID, only used with bound threads + int _native_priority; // Saved native priority when starting + // a bound thread + sigset_t _caller_sigmask; // Caller's signal mask + bool _vm_created_thread; // true if the VM created this thread, + // false if primary thread or attached thread public: - - thread_t thread_id() const { return _thread_id; } - - unsigned int lwp_id() const { return _lwp_id; } + thread_t thread_id() const { return _thread_id; } + uint lwp_id() const { return _lwp_id; } + int native_priority() const { return _native_priority; } // Set and get state of _vm_created_thread flag void set_vm_created() { _vm_created_thread = true; } @@ -62,8 +62,9 @@ return true; } #endif - void set_thread_id(thread_t id) { _thread_id = id; } - void set_lwp_id(unsigned int id){ _lwp_id = id; } + void set_thread_id(thread_t id) { _thread_id = id; } + void set_lwp_id(uint id) { _lwp_id = id; } + void set_native_priority(int prio) { _native_priority = prio; } // *************************************************************** // interrupt support. interrupts (using signals) are used to get diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 939ef4229d3..832f9bc4532 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,6 +114,7 @@ # include # include # include +# include # include # include # include @@ -129,8 +130,8 @@ #ifdef _GNU_SOURCE // See bug #6514594 extern "C" int madvise(caddr_t, size_t, int); -extern "C" int memcntl(caddr_t addr, size_t len, int cmd, caddr_t arg, - int attr, int mask); +extern "C" int memcntl(caddr_t addr, size_t len, int cmd, caddr_t arg, + int attr, int mask); #endif //_GNU_SOURCE /* @@ -215,8 +216,9 @@ struct memcntl_mha { #define MaximumPriority 127 // Values for ThreadPriorityPolicy == 1 -int prio_policy1[MaxPriority+1] = { -99999, 0, 16, 32, 48, 64, - 80, 96, 112, 124, 127 }; +int prio_policy1[CriticalPriority+1] = { + -99999, 0, 16, 32, 48, 64, + 80, 96, 112, 124, 127, 127 }; // System parameters used internally static clock_t clock_tics_per_sec = 100; @@ -1048,15 +1050,22 @@ extern "C" void* java_start(void* thread_addr) { } // If the creator called set priority before we started, - // we need to call set priority now that we have an lwp. - // Get the priority from libthread and set the priority - // for the new Solaris lwp. + // we need to call set_native_priority now that we have an lwp. + // We used to get the priority from thr_getprio (we called + // thr_setprio way back in create_thread) and pass it to + // set_native_priority, but Solaris scales the priority + // in java_to_os_priority, so when we read it back here, + // we pass trash to set_native_priority instead of what's + // in java_to_os_priority. So we save the native priority + // in the osThread and recall it here. + if ( osthr->thread_id() != -1 ) { if ( UseThreadPriorities ) { - thr_getprio(osthr->thread_id(), &prio); + int prio = osthr->native_priority(); if (ThreadPriorityVerbose) { - tty->print_cr("Starting Thread " INTPTR_FORMAT ", LWP is " INTPTR_FORMAT ", setting priority: %d\n", - osthr->thread_id(), osthr->lwp_id(), prio ); + tty->print_cr("Starting Thread " INTPTR_FORMAT ", LWP is " + INTPTR_FORMAT ", setting priority: %d\n", + osthr->thread_id(), osthr->lwp_id(), prio); } os::set_native_priority(thread, prio); } @@ -1353,13 +1362,12 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { // Remember that we created this thread so we can set priority on it osthread->set_vm_created(); - // Set the default thread priority otherwise use NormalPriority - - if ( UseThreadPriorities ) { - thr_setprio(tid, (DefaultThreadPriority == -1) ? + // Set the default thread priority. If using bound threads, setting + // lwp priority will be delayed until thread start. + set_native_priority(thread, + DefaultThreadPriority == -1 ? java_to_os_priority[NormPriority] : DefaultThreadPriority); - } // Initial thread state is INITIALIZED, not SUSPENDED osthread->set_state(INITIALIZED); @@ -3728,7 +3736,7 @@ typedef struct { } SchedInfo; -static SchedInfo tsLimits, iaLimits, rtLimits; +static SchedInfo tsLimits, iaLimits, rtLimits, fxLimits; #ifdef ASSERT static int ReadBackValidate = 1; @@ -3739,6 +3747,8 @@ static int myMax = 0; static int myCur = 0; static bool priocntl_enable = false; +static const int criticalPrio = 60; // FX/60 is critical thread class/priority on T4 +static int java_MaxPriority_to_os_priority = 0; // Saved mapping // Call the version of priocntl suitable for all supported versions // of Solaris. We need to call through this wrapper so that we can @@ -3783,19 +3793,27 @@ int lwp_priocntl_init () if (os::Solaris::T2_libthread() || UseBoundThreads) { // If ThreadPriorityPolicy is 1, switch tables if (ThreadPriorityPolicy == 1) { - for (i = 0 ; i < MaxPriority+1; i++) + for (i = 0 ; i < CriticalPriority+1; i++) os::java_to_os_priority[i] = prio_policy1[i]; } + if (UseCriticalJavaThreadPriority) { + // MaxPriority always maps to the FX scheduling class and criticalPrio. + // See set_native_priority() and set_lwp_class_and_priority(). + // Save original MaxPriority mapping in case attempt to + // use critical priority fails. + java_MaxPriority_to_os_priority = os::java_to_os_priority[MaxPriority]; + // Set negative to distinguish from other priorities + os::java_to_os_priority[MaxPriority] = -criticalPrio; + } } // Not using Bound Threads, set to ThreadPolicy 1 else { - for ( i = 0 ; i < MaxPriority+1; i++ ) { + for ( i = 0 ; i < CriticalPriority+1; i++ ) { os::java_to_os_priority[i] = prio_policy1[i]; } return 0; } - // Get IDs for a set of well-known scheduling classes. // TODO-FIXME: GETCLINFO returns the current # of classes in the // the system. We should have a loop that iterates over the @@ -3828,24 +3846,33 @@ int lwp_priocntl_init () rtLimits.maxPrio = ((rtinfo_t*)ClassInfo.pc_clinfo)->rt_maxpri; rtLimits.minPrio = 0; + strcpy(ClassInfo.pc_clname, "FX"); + ClassInfo.pc_cid = -1; + rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); + if (rslt < 0) return errno; + assert(ClassInfo.pc_cid != -1, "cid for FX class is -1"); + fxLimits.schedPolicy = ClassInfo.pc_cid; + fxLimits.maxPrio = ((fxinfo_t*)ClassInfo.pc_clinfo)->fx_maxupri; + fxLimits.minPrio = 0; // Query our "current" scheduling class. - // This will normally be IA,TS or, rarely, RT. - memset (&ParmInfo, 0, sizeof(ParmInfo)); + // This will normally be IA, TS or, rarely, FX or RT. + memset(&ParmInfo, 0, sizeof(ParmInfo)); ParmInfo.pc_cid = PC_CLNULL; - rslt = (*priocntl_ptr) (PC_VERSION, P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo ); - if ( rslt < 0 ) return errno; + rslt = (*priocntl_ptr) (PC_VERSION, P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo); + if (rslt < 0) return errno; myClass = ParmInfo.pc_cid; // We now know our scheduling classId, get specific information - // the class. + // about the class. ClassInfo.pc_cid = myClass; ClassInfo.pc_clname[0] = 0; - rslt = (*priocntl_ptr) (PC_VERSION, (idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo ); - if ( rslt < 0 ) return errno; + rslt = (*priocntl_ptr) (PC_VERSION, (idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo); + if (rslt < 0) return errno; - if (ThreadPriorityVerbose) - tty->print_cr ("lwp_priocntl_init: Class=%d(%s)...", myClass, ClassInfo.pc_clname); + if (ThreadPriorityVerbose) { + tty->print_cr("lwp_priocntl_init: Class=%d(%s)...", myClass, ClassInfo.pc_clname); + } memset(&ParmInfo, 0, sizeof(pcparms_t)); ParmInfo.pc_cid = PC_CLNULL; @@ -3865,6 +3892,11 @@ int lwp_priocntl_init () myMin = tsLimits.minPrio; myMax = tsLimits.maxPrio; myMax = MIN2(myMax, (int)tsInfo->ts_uprilim); // clamp - restrict + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) { + fxparms_t *fxInfo = (fxparms_t*)ParmInfo.pc_clparms; + myMin = fxLimits.minPrio; + myMax = fxLimits.maxPrio; + myMax = MIN2(myMax, (int)fxInfo->fx_uprilim); // clamp - restrict } else { // No clue - punt if (ThreadPriorityVerbose) @@ -3872,8 +3904,9 @@ int lwp_priocntl_init () return EINVAL; // no clue, punt } - if (ThreadPriorityVerbose) - tty->print_cr ("Thread priority Range: [%d..%d]\n", myMin, myMax); + if (ThreadPriorityVerbose) { + tty->print_cr ("Thread priority Range: [%d..%d]\n", myMin, myMax); + } priocntl_enable = true; // Enable changing priorities return 0; @@ -3882,6 +3915,7 @@ int lwp_priocntl_init () #define IAPRI(x) ((iaparms_t *)((x).pc_clparms)) #define RTPRI(x) ((rtparms_t *)((x).pc_clparms)) #define TSPRI(x) ((tsparms_t *)((x).pc_clparms)) +#define FXPRI(x) ((fxparms_t *)((x).pc_clparms)) // scale_to_lwp_priority @@ -3900,13 +3934,13 @@ int scale_to_lwp_priority (int rMin, int rMax, int x) } -// set_lwp_priority +// set_lwp_class_and_priority // -// Set the priority of the lwp. This call should only be made -// when using bound threads (T2 threads are bound by default). +// Set the class and priority of the lwp. This call should only +// be made when using bound threads (T2 threads are bound by default). // -int set_lwp_priority (int ThreadID, int lwpid, int newPrio ) -{ +int set_lwp_class_and_priority(int ThreadID, int lwpid, + int newPrio, int new_class, bool scale) { int rslt; int Actual, Expected, prv; pcparms_t ParmInfo; // for GET-SET @@ -3927,19 +3961,20 @@ int set_lwp_priority (int ThreadID, int lwpid, int newPrio ) return EINVAL; } - // If lwp hasn't started yet, just return // the _start routine will call us again. if ( lwpid <= 0 ) { if (ThreadPriorityVerbose) { - tty->print_cr ("deferring the set_lwp_priority of thread " INTPTR_FORMAT " to %d, lwpid not set", + tty->print_cr ("deferring the set_lwp_class_and_priority of thread " + INTPTR_FORMAT " to %d, lwpid not set", ThreadID, newPrio); } return 0; } if (ThreadPriorityVerbose) { - tty->print_cr ("set_lwp_priority(" INTPTR_FORMAT "@" INTPTR_FORMAT " %d) ", + tty->print_cr ("set_lwp_class_and_priority(" + INTPTR_FORMAT "@" INTPTR_FORMAT " %d) ", ThreadID, lwpid, newPrio); } @@ -3948,40 +3983,70 @@ int set_lwp_priority (int ThreadID, int lwpid, int newPrio ) rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ParmInfo); if (rslt < 0) return errno; - if (ParmInfo.pc_cid == rtLimits.schedPolicy) { + int cur_class = ParmInfo.pc_cid; + ParmInfo.pc_cid = (id_t)new_class; + + if (new_class == rtLimits.schedPolicy) { rtparms_t *rtInfo = (rtparms_t*)ParmInfo.pc_clparms; - rtInfo->rt_pri = scale_to_lwp_priority (rtLimits.minPrio, rtLimits.maxPrio, newPrio); + rtInfo->rt_pri = scale ? scale_to_lwp_priority(rtLimits.minPrio, + rtLimits.maxPrio, newPrio) + : newPrio; rtInfo->rt_tqsecs = RT_NOCHANGE; rtInfo->rt_tqnsecs = RT_NOCHANGE; if (ThreadPriorityVerbose) { tty->print_cr("RT: %d->%d\n", newPrio, rtInfo->rt_pri); } - } else if (ParmInfo.pc_cid == iaLimits.schedPolicy) { - iaparms_t *iaInfo = (iaparms_t*)ParmInfo.pc_clparms; - int maxClamped = MIN2(iaLimits.maxPrio, (int)iaInfo->ia_uprilim); - iaInfo->ia_upri = scale_to_lwp_priority(iaLimits.minPrio, maxClamped, newPrio); - iaInfo->ia_uprilim = IA_NOCHANGE; + } else if (new_class == iaLimits.schedPolicy) { + iaparms_t* iaInfo = (iaparms_t*)ParmInfo.pc_clparms; + int maxClamped = MIN2(iaLimits.maxPrio, + cur_class == new_class + ? (int)iaInfo->ia_uprilim : iaLimits.maxPrio); + iaInfo->ia_upri = scale ? scale_to_lwp_priority(iaLimits.minPrio, + maxClamped, newPrio) + : newPrio; + iaInfo->ia_uprilim = cur_class == new_class + ? IA_NOCHANGE : (pri_t)iaLimits.maxPrio; iaInfo->ia_mode = IA_NOCHANGE; + iaInfo->ia_nice = cur_class == new_class ? IA_NOCHANGE : NZERO; if (ThreadPriorityVerbose) { - tty->print_cr ("IA: [%d...%d] %d->%d\n", - iaLimits.minPrio, maxClamped, newPrio, iaInfo->ia_upri); + tty->print_cr("IA: [%d...%d] %d->%d\n", + iaLimits.minPrio, maxClamped, newPrio, iaInfo->ia_upri); } - } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) { - tsparms_t *tsInfo = (tsparms_t*)ParmInfo.pc_clparms; - int maxClamped = MIN2(tsLimits.maxPrio, (int)tsInfo->ts_uprilim); - prv = tsInfo->ts_upri; - tsInfo->ts_upri = scale_to_lwp_priority(tsLimits.minPrio, maxClamped, newPrio); - tsInfo->ts_uprilim = IA_NOCHANGE; + } else if (new_class == tsLimits.schedPolicy) { + tsparms_t* tsInfo = (tsparms_t*)ParmInfo.pc_clparms; + int maxClamped = MIN2(tsLimits.maxPrio, + cur_class == new_class + ? (int)tsInfo->ts_uprilim : tsLimits.maxPrio); + tsInfo->ts_upri = scale ? scale_to_lwp_priority(tsLimits.minPrio, + maxClamped, newPrio) + : newPrio; + tsInfo->ts_uprilim = cur_class == new_class + ? TS_NOCHANGE : (pri_t)tsLimits.maxPrio; if (ThreadPriorityVerbose) { - tty->print_cr ("TS: %d [%d...%d] %d->%d\n", - prv, tsLimits.minPrio, maxClamped, newPrio, tsInfo->ts_upri); + tty->print_cr("TS: [%d...%d] %d->%d\n", + tsLimits.minPrio, maxClamped, newPrio, tsInfo->ts_upri); + } + } else if (new_class == fxLimits.schedPolicy) { + fxparms_t* fxInfo = (fxparms_t*)ParmInfo.pc_clparms; + int maxClamped = MIN2(fxLimits.maxPrio, + cur_class == new_class + ? (int)fxInfo->fx_uprilim : fxLimits.maxPrio); + fxInfo->fx_upri = scale ? scale_to_lwp_priority(fxLimits.minPrio, + maxClamped, newPrio) + : newPrio; + fxInfo->fx_uprilim = cur_class == new_class + ? FX_NOCHANGE : (pri_t)fxLimits.maxPrio; + fxInfo->fx_tqsecs = FX_NOCHANGE; + fxInfo->fx_tqnsecs = FX_NOCHANGE; + if (ThreadPriorityVerbose) { + tty->print_cr("FX: [%d...%d] %d->%d\n", + fxLimits.minPrio, maxClamped, newPrio, fxInfo->fx_upri); } - if (prv == tsInfo->ts_upri) return 0; } else { - if ( ThreadPriorityVerbose ) { - tty->print_cr ("Unknown scheduling class\n"); + if (ThreadPriorityVerbose) { + tty->print_cr("Unknown new scheduling class %d\n", new_class); } - return EINVAL; // no clue, punt + return EINVAL; // no clue, punt } rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_SETPARMS, (caddr_t)&ParmInfo); @@ -4016,16 +4081,20 @@ int set_lwp_priority (int ThreadID, int lwpid, int newPrio ) } else if (ParmInfo.pc_cid == tsLimits.schedPolicy) { Actual = TSPRI(ReadBack)->ts_upri; Expected = TSPRI(ParmInfo)->ts_upri; + } else if (ParmInfo.pc_cid == fxLimits.schedPolicy) { + Actual = FXPRI(ReadBack)->fx_upri; + Expected = FXPRI(ParmInfo)->fx_upri; } else { - if ( ThreadPriorityVerbose ) { - tty->print_cr("set_lwp_priority: unexpected class in readback: %d\n", ParmInfo.pc_cid); + if (ThreadPriorityVerbose) { + tty->print_cr("set_lwp_class_and_priority: unexpected class in readback: %d\n", + ParmInfo.pc_cid); } } if (Actual != Expected) { - if ( ThreadPriorityVerbose ) { - tty->print_cr ("set_lwp_priority(%d %d) Class=%d: actual=%d vs expected=%d\n", - lwpid, newPrio, ReadBack.pc_cid, Actual, Expected); + if (ThreadPriorityVerbose) { + tty->print_cr ("set_lwp_class_and_priority(%d %d) Class=%d: actual=%d vs expected=%d\n", + lwpid, newPrio, ReadBack.pc_cid, Actual, Expected); } } #endif @@ -4033,8 +4102,6 @@ int set_lwp_priority (int ThreadID, int lwpid, int newPrio ) return 0; } - - // Solaris only gives access to 128 real priorities at a time, // so we expand Java's ten to fill this range. This would be better // if we dynamically adjusted relative priorities. @@ -4055,8 +4122,7 @@ int set_lwp_priority (int ThreadID, int lwpid, int newPrio ) // which do not explicitly alter their thread priorities. // - -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { -99999, // 0 Entry should never be used 0, // 1 MinPriority @@ -4071,17 +4137,51 @@ int os::java_to_os_priority[MaxPriority + 1] = { 127, // 8 127, // 9 NearMaxPriority - 127 // 10 MaxPriority + 127, // 10 MaxPriority + + -criticalPrio // 11 CriticalPriority }; - OSReturn os::set_native_priority(Thread* thread, int newpri) { + OSThread* osthread = thread->osthread(); + + // Save requested priority in case the thread hasn't been started + osthread->set_native_priority(newpri); + + // Check for critical priority request + bool fxcritical = false; + if (newpri == -criticalPrio) { + fxcritical = true; + newpri = criticalPrio; + } + assert(newpri >= MinimumPriority && newpri <= MaximumPriority, "bad priority mapping"); - if ( !UseThreadPriorities ) return OS_OK; - int status = thr_setprio(thread->osthread()->thread_id(), newpri); - if ( os::Solaris::T2_libthread() || (UseBoundThreads && thread->osthread()->is_vm_created()) ) - status |= (set_lwp_priority (thread->osthread()->thread_id(), - thread->osthread()->lwp_id(), newpri )); + if (!UseThreadPriorities) return OS_OK; + + int status = 0; + + if (!fxcritical) { + // Use thr_setprio only if we have a priority that thr_setprio understands + status = thr_setprio(thread->osthread()->thread_id(), newpri); + } + + if (os::Solaris::T2_libthread() || + (UseBoundThreads && osthread->is_vm_created())) { + int lwp_status = + set_lwp_class_and_priority(osthread->thread_id(), + osthread->lwp_id(), + newpri, + fxcritical ? fxLimits.schedPolicy : myClass, + !fxcritical); + if (lwp_status != 0 && fxcritical) { + // Try again, this time without changing the scheduling class + newpri = java_MaxPriority_to_os_priority; + lwp_status = set_lwp_class_and_priority(osthread->thread_id(), + osthread->lwp_id(), + newpri, myClass, false); + } + status |= lwp_status; + } return (status == 0) ? OS_OK : OS_ERR; } diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 56d51b6d608..798f6b350fe 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3296,7 +3296,7 @@ void os::yield_all(int attempts) { // so we compress Java's ten down to seven. It would be better // if we dynamically adjusted relative priorities. -int os::java_to_os_priority[MaxPriority + 1] = { +int os::java_to_os_priority[CriticalPriority + 1] = { THREAD_PRIORITY_IDLE, // 0 Entry should never be used THREAD_PRIORITY_LOWEST, // 1 MinPriority THREAD_PRIORITY_LOWEST, // 2 @@ -3307,10 +3307,11 @@ int os::java_to_os_priority[MaxPriority + 1] = { THREAD_PRIORITY_ABOVE_NORMAL, // 7 THREAD_PRIORITY_ABOVE_NORMAL, // 8 THREAD_PRIORITY_HIGHEST, // 9 NearMaxPriority - THREAD_PRIORITY_HIGHEST // 10 MaxPriority + THREAD_PRIORITY_HIGHEST, // 10 MaxPriority + THREAD_PRIORITY_HIGHEST // 11 CriticalPriority }; -int prio_policy1[MaxPriority + 1] = { +int prio_policy1[CriticalPriority + 1] = { THREAD_PRIORITY_IDLE, // 0 Entry should never be used THREAD_PRIORITY_LOWEST, // 1 MinPriority THREAD_PRIORITY_LOWEST, // 2 @@ -3321,17 +3322,21 @@ int prio_policy1[MaxPriority + 1] = { THREAD_PRIORITY_ABOVE_NORMAL, // 7 THREAD_PRIORITY_HIGHEST, // 8 THREAD_PRIORITY_HIGHEST, // 9 NearMaxPriority - THREAD_PRIORITY_TIME_CRITICAL // 10 MaxPriority + THREAD_PRIORITY_TIME_CRITICAL, // 10 MaxPriority + THREAD_PRIORITY_TIME_CRITICAL // 11 CriticalPriority }; static int prio_init() { // If ThreadPriorityPolicy is 1, switch tables if (ThreadPriorityPolicy == 1) { int i; - for (i = 0; i < MaxPriority + 1; i++) { + for (i = 0; i < CriticalPriority + 1; i++) { os::java_to_os_priority[i] = prio_policy1[i]; } } + if (UseCriticalJavaThreadPriority) { + os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority] ; + } return 0; } diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 4c3850936d3..daff489c057 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -855,23 +855,23 @@ CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQue // Note that this only sets the JavaThread _priority field, which by // definition is limited to Java priorities and not OS priorities. // The os-priority is set in the CompilerThread startup code itself + java_lang_Thread::set_priority(thread_oop(), NearMaxPriority); - // CLEANUP PRIORITIES: This -if- statement hids a bug whereby the compiler - // threads never have their OS priority set. The assumption here is to - // enable the Performance group to do flag tuning, figure out a suitable - // CompilerThreadPriority, and then remove this 'if' statement (and - // comment) and unconditionally set the priority. - // Compiler Threads should be at the highest Priority - if ( CompilerThreadPriority != -1 ) - os::set_native_priority( compiler_thread, CompilerThreadPriority ); - else - os::set_native_priority( compiler_thread, os::java_to_os_priority[NearMaxPriority]); + // Note that we cannot call os::set_priority because it expects Java + // priorities and we are *explicitly* using OS priorities so that it's + // possible to set the compiler thread priority higher than any Java + // thread. - // Note that I cannot call os::set_priority because it expects Java - // priorities and I am *explicitly* using OS priorities so that it's - // possible to set the compiler thread priority higher than any Java - // thread. + int native_prio = CompilerThreadPriority; + if (native_prio == -1) { + if (UseCriticalCompilerThreadPriority) { + native_prio = os::java_to_os_priority[CriticalPriority]; + } else { + native_prio = os::java_to_os_priority[NearMaxPriority]; + } + } + os::set_native_priority(compiler_thread, native_prio); java_lang_Thread::set_daemon(thread_oop()); @@ -879,6 +879,7 @@ CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQue Threads::add(compiler_thread); Thread::start(compiler_thread); } + // Let go of Threads_lock before yielding os::yield(); // make sure that the compiler thread is started early (especially helpful on SOLARIS) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp index 78ca0cb57b5..93c3df0e402 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,10 +75,25 @@ ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector) set_name("Concurrent Mark-Sweep GC Thread"); if (os::create_thread(this, os::cgc_thread)) { - // XXX: need to set this to low priority - // unless "agressive mode" set; priority - // should be just less than that of VMThread. - os::set_priority(this, NearMaxPriority); + // An old comment here said: "Priority should be just less + // than that of VMThread". Since the VMThread runs at + // NearMaxPriority, the old comment was inaccurate, but + // changing the default priority to NearMaxPriority-1 + // could change current behavior, so the default of + // NearMaxPriority stays in place. + // + // Note that there's a possibility of the VMThread + // starving if UseCriticalCMSThreadPriority is on. + // That won't happen on Solaris for various reasons, + // but may well happen on non-Solaris platforms. + int native_prio; + if (UseCriticalCMSThreadPriority) { + native_prio = os::java_to_os_priority[CriticalPriority]; + } else { + native_prio = os::java_to_os_priority[NearMaxPriority]; + } + os::set_native_priority(this, native_prio); + if (!DisableStartThread) { os::start_thread(this); } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 88e59385098..b6d4ec94e1a 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3477,16 +3477,19 @@ class CommandLineFlags { " Linux this policy requires root privilege.") \ \ product(bool, ThreadPriorityVerbose, false, \ - "print priority changes") \ + "Print priority changes") \ \ product(intx, DefaultThreadPriority, -1, \ - "what native priority threads run at if not specified elsewhere (-1 means no change)") \ + "The native priority at which threads run if not elsewhere " \ + "specified (-1 means no change)") \ \ product(intx, CompilerThreadPriority, -1, \ - "what priority should compiler threads run at (-1 means no change)") \ + "The native priority at which compiler threads should run " \ + "(-1 means no change)") \ \ product(intx, VMThreadPriority, -1, \ - "what priority should VM threads run at (-1 means no change)") \ + "The native priority at which the VM thread should run " \ + "(-1 means no change)") \ \ product(bool, CompilerThreadHintNoPreempt, true, \ "(Solaris only) Give compiler threads an extra quanta") \ @@ -3505,6 +3508,15 @@ class CommandLineFlags { product(intx, JavaPriority9_To_OSPriority, -1, "Map Java priorities to OS priorities") \ product(intx, JavaPriority10_To_OSPriority,-1, "Map Java priorities to OS priorities") \ \ + experimental(bool, UseCriticalJavaThreadPriority, false, \ + "Java thread priority 10 maps to critical scheduling priority") \ + \ + experimental(bool, UseCriticalCompilerThreadPriority, false, \ + "Compiler thread(s) run at critical scheduling priority") \ + \ + experimental(bool, UseCriticalCMSThreadPriority, false, \ + "ConcurrentMarkSweep thread runs at critical scheduling priority")\ + \ /* compiler debugging */ \ notproduct(intx, CompileTheWorldStartAt, 1, \ "First class to consider when using +CompileTheWorld") \ @@ -3871,7 +3883,7 @@ class CommandLineFlags { product(bool, UseVMInterruptibleIO, false, \ "(Unstable, Solaris-specific) Thread interrupt before or with " \ "EINTR for I/O operations results in OS_INTRPT. The default value"\ - " of this flag is true for JDK 6 and earliers") + " of this flag is true for JDK 6 and earlier") /* * Macros for factoring of globals diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 85a85a3776a..e77f3ce919a 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,8 +73,9 @@ enum ThreadPriority { // JLS 20.20.1-3 MinPriority = 1, // Minimum priority NormPriority = 5, // Normal (non-daemon) priority NearMaxPriority = 9, // High priority, used for VMThread - MaxPriority = 10 // Highest priority, used for WatcherThread + MaxPriority = 10, // Highest priority, used for WatcherThread // ensures that VMThread doesn't starve profiler + CriticalPriority = 11 // Critical thread priority }; // Typedef for structured exception handling support @@ -733,7 +734,7 @@ class os: AllStatic { // Thread priority helpers (implemented in OS-specific part) static OSReturn set_native_priority(Thread* thread, int native_prio); static OSReturn get_native_priority(const Thread* const thread, int* priority_ptr); - static int java_to_os_priority[MaxPriority + 1]; + static int java_to_os_priority[CriticalPriority + 1]; // Hint to the underlying OS that a task switch would not be good. // Void return because it's a hint and can fail. static void hint_no_preempt(); From 47bf575dfa7e43d74a5e3536850b4ef0db8f86e1 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 26 Jan 2012 18:23:09 -0800 Subject: [PATCH 87/96] Added tag jdk8-b23 for changeset c62b7a0288a4 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index bb12895c257..3453ea78ed0 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -144,3 +144,4 @@ a4f28069d44a379cda99dd1d921d19f819726d22 jdk8-b15 5a5eaf6374bcbe23530899579fed17a05b7705f3 jdk8-b20 cc771d92284f71765eca14d6d08703c4af254c04 jdk8-b21 7ad075c809952e355d25030605da6af30456ed74 jdk8-b22 +60d6f64a86b1e511169d264727f6d51415978df0 jdk8-b23 From fbc7f2bbafd2b8abba0a96f9b00354644d80fcb0 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 26 Jan 2012 18:23:14 -0800 Subject: [PATCH 88/96] Added tag jdk8-b23 for changeset 751387b26353 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index afe42c25fa3..6042eb3a9c7 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -144,3 +144,4 @@ e1366c5d84ef984095a332bcee70b3938232d07d jdk8-b19 51d8b6cb18c0978ecfa4f33e1537d35ee01b69fa jdk8-b20 f157fc2a71a38ce44007a6f18d5b011824dce705 jdk8-b21 a11d0062c445d5f36651c78650ab88aa594bcbff jdk8-b22 +5218eb256658442b62b05295aafa5b5f35252972 jdk8-b23 From 5e494c370aa4fffce5c3b0d2ecc54daea19abf97 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 26 Jan 2012 18:23:17 -0800 Subject: [PATCH 89/96] Added tag jdk8-b23 for changeset af005838b2f8 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 383edfe958d..4e47d3250fc 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -213,3 +213,4 @@ fe2c8764998112b7fefcd7d41599714813ae4327 jdk8-b20 513351373923f74a7c91755748b95c9771e59f96 hs23-b10 24727fb37561779077fdfa5a33342246f20e5c0f jdk8-b22 dcc292399a39113957eebbd3e487b7e05e2c79fc hs23-b11 +e850d8e7ea54b91c7aa656e297f0f9f38dd4c296 jdk8-b23 From c4b15b06e6e58c941465d9bd4eed432a484a8194 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 26 Jan 2012 18:23:24 -0800 Subject: [PATCH 90/96] Added tag jdk8-b23 for changeset 939aca1c5dac --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 462530760e6..bc6e6734c1a 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -144,3 +144,4 @@ dffeb62b1a7fc8b316bf58fe5479323f3661894e jdk8-b19 f052abb8f37444ba77858913887d0d92795dd6b8 jdk8-b20 d41eeadf5c1344b88c5051a997aec9e1ad7ce1db jdk8-b21 cf9d6ec44f891236ad18451021d6dcd57dc82f7b jdk8-b22 +95102fd334183d15dc98a95dd0d749527b6c7300 jdk8-b23 From 34ff11cc2f9fa9da447d093354f92dc9be343380 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 26 Jan 2012 18:23:25 -0800 Subject: [PATCH 91/96] Added tag jdk8-b23 for changeset 11fa98675c2a --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 639ceef74ca..a22c184b4b9 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -144,3 +144,4 @@ b73b733214aa43648d69a2da51e6b48fda902a2d jdk8-b19 2b2818e3386f4510c390f6aea90d77e1c6a5bf9e jdk8-b20 c266cab0e3fff05f2048c23046c14d60f7102175 jdk8-b21 8d3df89b0f2d3c603b2edb0f5e24af1245397cc6 jdk8-b22 +25ce7a0004874273f6aeda14e7c3538cba34bdf1 jdk8-b23 From 1b98d6343f8efb959b7a58bca26f62176d8c1dbc Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 26 Jan 2012 18:23:28 -0800 Subject: [PATCH 92/96] Added tag jdk8-b23 for changeset 412e931c07b9 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index da0c9215a8f..d8826fdc86c 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -144,3 +144,4 @@ b71d1acfae5240d8c1359443cd02b5ddb587231c jdk8-b17 39e938cd1b82ec3aab0a9aa66fd8a0457cd0c9c2 jdk8-b20 664fa4fb0ee411ef048903c479f8b962fcdb2f4b jdk8-b21 dda27c73d8db4a9c7a23872b6f0c5106edcb2021 jdk8-b22 +54202e0148ec7d4570cab5bc9b00d216a7677569 jdk8-b23 From 3d631d7389c0e999f2ba0663a856218bf4894eab Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 26 Jan 2012 18:23:36 -0800 Subject: [PATCH 93/96] Added tag jdk8-b23 for changeset 6662fc41e1c3 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index d4c24a7c411..7b277d7822c 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -144,3 +144,4 @@ ab1b1cc7857716914f2bb20b3128e5a8978290f7 jdk8-b18 ffd294128a48cbb90ce8f0569f82b61f1f164a18 jdk8-b20 bcb21abf1c4177baf4574f99709513dcd4474727 jdk8-b21 390a7828ae18324030c0546b6452d51093ffa451 jdk8-b22 +601ffcc6551d5414ef871be306c3a26396cf16a7 jdk8-b23 From b67bc26c4d72e22f5f40a129b1b2938a9ab41f95 Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 27 Jan 2012 14:44:20 -0800 Subject: [PATCH 94/96] Added tag hs23-b12 for changeset 68d6477cc31f --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 4e47d3250fc..c7006b1f249 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -214,3 +214,4 @@ fe2c8764998112b7fefcd7d41599714813ae4327 jdk8-b20 24727fb37561779077fdfa5a33342246f20e5c0f jdk8-b22 dcc292399a39113957eebbd3e487b7e05e2c79fc hs23-b11 e850d8e7ea54b91c7aa656e297f0f9f38dd4c296 jdk8-b23 +9e177d44b10fe92ecffa965fef9c5ac5433c1b46 hs23-b12 From 44e95b7411df22a2bab2e2622c3453552bc8c7a1 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:00:12 +0200 Subject: [PATCH 95/96] Added tag jdk8-b22 for changeset e8f03541af27 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 2bbafd699b6..613c0a5d913 100644 --- a/.hgtags +++ b/.hgtags @@ -143,3 +143,4 @@ f0eccb2946986fb9626efde7d8ed9c8192623f5c jdk8-b17 0ff7113a0882ec82d642cb9f0297b4e497807ced jdk8-b19 6561530ea757c3f3a6fb171c9cc7b3885cdeca85 jdk8-b20 b3a426170188f52981cf4573a2f14d487fddab0d jdk8-b21 +e8f03541af27e38aafb619b96863e17f65ffe53b jdk8-b22 From 1cbd6b266b4017fe60f65062f8d80e627aa4500f Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:00:53 +0200 Subject: [PATCH 96/96] Added tag jdk8-b23 for changeset 498124337041 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 613c0a5d913..ee4f0ef5c89 100644 --- a/.hgtags +++ b/.hgtags @@ -144,3 +144,4 @@ f0eccb2946986fb9626efde7d8ed9c8192623f5c jdk8-b17 6561530ea757c3f3a6fb171c9cc7b3885cdeca85 jdk8-b20 b3a426170188f52981cf4573a2f14d487fddab0d jdk8-b21 e8f03541af27e38aafb619b96863e17f65ffe53b jdk8-b22 +498124337041ad53cbaa7eb110f3d7acd6d4eac4 jdk8-b23