From 69a6be0305772fbcba9bf0798e0f61445bf42083 Mon Sep 17 00:00:00 2001 From: Anthony Petrov Date: Fri, 12 Oct 2012 15:51:44 +0400 Subject: [PATCH 001/102] 7173145: Improve in-memory representation of splashscreens Reviewed-by: bae, mschoene --- jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c index fcd7de01639..b1a59098955 100644 --- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c +++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c @@ -133,6 +133,10 @@ SplashDecodeJpeg(Splash * splash, struct jpeg_decompress_struct *cinfo) ImageFormat srcFormat; jpeg_read_header(cinfo, TRUE); + + // SplashScreen jpeg converter expects data in RGB format only + cinfo->out_color_space = JCS_RGB; + jpeg_start_decompress(cinfo); SplashCleanup(splash); From f36ef09388cc33f69d56573d6a51ccea6333b632 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Mon, 15 Oct 2012 07:42:18 -0700 Subject: [PATCH 002/102] 7192393: Better Checking of order of TLS Messages Also reviewed by Andrew Gross Reviewed-by: weijun --- .../sun/security/ssl/ClientHandshaker.java | 5 ++--- .../sun/security/ssl/ServerHandshaker.java | 16 +++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java index 9ebeb75c5aa..63d48ad376d 100644 --- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java @@ -128,9 +128,8 @@ final class ClientHandshaker extends Handshaker { * in the constructor. */ void processMessage(byte type, int messageLen) throws IOException { - if (state > type - && (type != HandshakeMessage.ht_hello_request - && state != HandshakeMessage.ht_client_hello)) { + if (state >= type + && (type != HandshakeMessage.ht_hello_request)) { throw new SSLProtocolException( "Handshake message sequence violation, " + type); } diff --git a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java index 8b10f8a9499..a8d256f76d6 100644 --- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java @@ -150,7 +150,7 @@ final class ServerHandshaker extends Handshaker { // In SSLv3 and TLS, messages follow strictly increasing // numerical order _except_ for one annoying special case. // - if ((state > type) + if ((state >= type) && (state != HandshakeMessage.ht_client_key_exchange && type != HandshakeMessage.ht_certificate_verify)) { throw new SSLProtocolException( @@ -250,13 +250,15 @@ final class ServerHandshaker extends Handshaker { } // - // Move the state machine forward except for that annoying - // special case. This means that clients could send extra - // cert verify messages; not a problem so long as all of - // them actually check out. + // Move state machine forward if the message handling + // code didn't already do so // - if (state < type && type != HandshakeMessage.ht_certificate_verify) { - state = type; + if (state < type) { + if(type == HandshakeMessage.ht_certificate_verify) { + state = type + 2; // an annoying special case + } else { + state = type; + } } } From c4f31fd22e9905fb38ad0919154d9fcd6c7c3183 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 15 Oct 2012 19:00:13 +0400 Subject: [PATCH 003/102] 7200493: Improve cache handling Reviewed-by: art, ahgross --- .../share/classes/com/sun/beans/finder/MethodFinder.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java index fa7cc5612ab..98c52bc929a 100644 --- a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java +++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java @@ -66,11 +66,14 @@ public final class MethodFinder extends AbstractFinder { Signature signature = new Signature(type, name, args); Method method = CACHE.get(signature); - if (method != null) { + boolean cached = method != null; + if (cached && isPackageAccessible(method.getDeclaringClass())) { return method; } method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods())); - CACHE.put(signature, method); + if (!cached) { + CACHE.put(signature, method); + } return method; } From e2a34e4d9e5975da831124dd4d49e389fabcfcf5 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Tue, 16 Oct 2012 14:13:39 +0400 Subject: [PATCH 004/102] 7186948: Improve Swing data validation Reviewed-by: art, ahgross --- jdk/src/share/classes/javax/swing/UIDefaults.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/src/share/classes/javax/swing/UIDefaults.java b/jdk/src/share/classes/javax/swing/UIDefaults.java index 9f22122d7b2..9f304e742c7 100644 --- a/jdk/src/share/classes/javax/swing/UIDefaults.java +++ b/jdk/src/share/classes/javax/swing/UIDefaults.java @@ -677,6 +677,8 @@ public class UIDefaults extends Hashtable try { String className = (String)get(uiClassID); if (className != null) { + ReflectUtil.checkPackageAccess(className); + Class cls = (Class)get(className); if (cls == null) { if (uiClassLoader == null) { From 1ee5b4509e4ee5008bdcf19b54b14de7f6e1b443 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Tue, 16 Oct 2012 12:29:10 -0700 Subject: [PATCH 005/102] 7186945: Unpack200 improvement Reviewed-by: jrose, jjh, mschoene --- .../share/native/com/sun/java/util/jar/pack/jni.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp index bedecda5391..50b5d114b39 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp @@ -127,8 +127,10 @@ static jlong read_input_via_jni(unpacker* self, JNIEXPORT void JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) { +#ifndef PRODUCT dbg = getenv("DEBUG_ATTACH"); while( dbg != null) { sleep(10); } +#endif NIclazz = (jclass) env->NewGlobalRef(clazz); unpackerPtrFID = env->GetFieldID(clazz, "unpackerPtr", "J"); currentInstMID = env->GetStaticMethodID(clazz, "currentInstance", @@ -230,11 +232,14 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject // We have fetched all the files. // Now swallow up any remaining input. - if (uPtr->input_remaining() == 0) + if (uPtr->input_remaining() == 0) { return null; - else - return env->NewDirectByteBuffer(uPtr->input_scan(), - uPtr->input_remaining()); + } else { + bytes remaining_bytes; + remaining_bytes.malloc(uPtr->input_remaining()); + remaining_bytes.copyFrom(uPtr->input_scan(), uPtr->input_remaining()); + return env->NewDirectByteBuffer(remaining_bytes.ptr, remaining_bytes.len); + } } JNIEXPORT jlong JNICALL From 0c4da1ece18f318e7f8387f595dbfbc64c2573ef Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Tue, 16 Oct 2012 12:35:22 -0700 Subject: [PATCH 006/102] 7186957: Improve Pack200 data validation Reviewed-by: jrose, jjh, mschoene --- .../sun/java/util/jar/pack/BandStructure.java | 3 +- .../sun/java/util/jar/pack/ConstantPool.java | 2 ++ .../com/sun/java/util/jar/pack/bands.cpp | 4 +++ .../native/com/sun/java/util/jar/pack/bands.h | 4 +-- .../com/sun/java/util/jar/pack/unpack.cpp | 30 ++++++++++++++++--- 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java index f3d5cec8e48..b53e082b802 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java @@ -1000,7 +1000,6 @@ class BandStructure { /** Write a constant pool reference. */ public void putRef(Entry e) { - assert(index != null); addValue(encodeRefOrNull(e, index)); } public void putRef(Entry e, Index index) { @@ -1052,6 +1051,8 @@ class BandStructure { int encodeRef(Entry e, Index ix) { + if (ix == null) + throw new RuntimeException("null index for " + e.stringValue()); int coding = ix.indexOf(e); if (verbose > 2) Utils.log.fine("putRef "+coding+" => "+e); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java index be4da54d247..4c5e5ba050d 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java @@ -1381,6 +1381,8 @@ class ConstantPool { /** Index of all CP entries of a given tag and class. */ public Index getMemberIndex(byte tag, ClassEntry classRef) { + if (classRef == null) + throw new RuntimeException("missing class reference for " + tagName(tag)); if (indexByTagAndClass == null) indexByTagAndClass = new Index[CONSTANT_Limit][]; Index allClasses = getIndexByTag(CONSTANT_Class); diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp index 08cdc8d3e76..6db0f31bc32 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp @@ -187,6 +187,10 @@ void band::setIndexByTag(byte tag) { entry* band::getRefCommon(cpindex* ix_, bool nullOKwithCaller) { CHECK_0; + if (ix_ == NULL) { + abort("no index"); + return NULL; + } assert(ix_->ixTag == ixTag || ((ixTag == CONSTANT_All || ixTag == CONSTANT_LoadableValue || diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h index b8e322aa1db..30ce8ed49a3 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h @@ -99,8 +99,8 @@ struct band { int getByte() { assert(ix == null); return vs[0].getByte(); } int getInt() { assert(ix == null); return vs[0].getInt(); } - entry* getRefN() { assert(ix != null); return getRefCommon(ix, true); } - entry* getRef() { assert(ix != null); return getRefCommon(ix, false); } + entry* getRefN() { return getRefCommon(ix, true); } + entry* getRef() { return getRefCommon(ix, false); } entry* getRefUsing(cpindex* ix2) { assert(ix == null); return getRefCommon(ix2, true); } entry* getRefCommon(cpindex* ix, bool nullOK); diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp index d7c51978ded..bb0e10bb32b 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp @@ -281,11 +281,13 @@ int entry::typeSize() { } inline cpindex* cpool::getFieldIndex(entry* classRef) { + if (classRef == NULL) { abort("missing class reference"); return NULL; } assert(classRef->tagMatches(CONSTANT_Class)); assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]); return &member_indexes[classRef->inord*2+0]; } inline cpindex* cpool::getMethodIndex(entry* classRef) { + if (classRef == NULL) { abort("missing class reference"); return NULL; } assert(classRef->tagMatches(CONSTANT_Class)); assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]); return &member_indexes[classRef->inord*2+1]; @@ -1289,6 +1291,7 @@ void unpacker::read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, entry& e = cpMap[i]; e.refs = U_NEW(entry*, e.nrefs = 2); e.refs[0] = cp_band1.getRef(); + CHECK; e.refs[1] = cp_band2.getRef(); CHECK; } @@ -1369,6 +1372,7 @@ void unpacker::read_method_type(entry* cpMap, int len) { entry& e = cpMap[i]; e.refs = U_NEW(entry*, e.nrefs = 1); e.refs[0] = cp_MethodType.getRef(); + CHECK; } } @@ -2104,6 +2108,7 @@ void unpacker::read_attr_defs() { int attrc = ADH_BYTE_CONTEXT(header); int idx = ADH_BYTE_INDEX(header); entry* name = attr_definition_name.getRef(); + CHECK; entry* layout = attr_definition_layout.getRef(); CHECK; attr_defs[attrc].defineLayout(idx, name, layout->value.b.strval()); @@ -2208,7 +2213,9 @@ void unpacker::read_ics() { if (ics[i].name == NO_ENTRY_YET) { // Long form. ics[i].outer = ic_outer_class.getRefN(); + CHECK; ics[i].name = ic_name.getRefN(); + CHECK; } else { // Fill in outer and name based on inner. bytes& n = ics[i].inner->value.b; @@ -2724,6 +2731,7 @@ void unpacker::putlayout(band** body) { e = b.getRefUsing(cp.getKQIndex()); else e = b.getRefN(); + CHECK; switch (b.le_len) { case 0: break; case 1: putu1ref(e); break; @@ -4006,6 +4014,7 @@ void unpacker::write_bc_ops() { NOT_PRODUCT(bc_superfield.setIndex(null)); NOT_PRODUCT(bc_supermethod.setIndex(null)); } + CHECK; for (int curIP = 0; ; curIP++) { int curPC = (int)(wpoffset() - codeBase); @@ -4119,7 +4128,8 @@ void unpacker::write_bc_ops() { int coding = bc_initref.getInt(); // Find the nth overloading of in classRef. entry* ref = null; - cpindex* ix = (classRef == null)? null: cp.getMethodIndex(classRef); + cpindex* ix = cp.getMethodIndex(classRef); + CHECK; for (int j = 0, which_init = 0; ; j++) { ref = (ix == null)? null: ix->get(j); if (ref == null) break; // oops, bad input @@ -4396,6 +4406,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod): aname = cp.sym[cpool::s_EnclosingMethod]; putref(class_EnclosingMethod_RC.getRefN()); + CHECK_0; putref(class_EnclosingMethod_RDN.getRefN()); break; @@ -4414,6 +4425,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { putu2(count = method_Exceptions_N.getInt()); for (j = 0; j < count; j++) { putref(method_Exceptions_RC.getRefN()); + CHECK_0; } break; @@ -4437,16 +4449,18 @@ int unpacker::write_attrs(int attrc, julong indexBits) { // (253) [(1)(2)(2)] // (254) [(1)(2)(2)(2)] putu2(code_StackMapTable_offset.getInt()); + CHECK_0; for (int k = (tag - 251); k > 0; k--) { put_stackmap_type(); + CHECK_0; } } else { // (255) [(1)NH[(2)]NH[(2)]] putu2(code_StackMapTable_offset.getInt()); putu2(j2 = code_StackMapTable_local_N.getInt()); - while (j2-- > 0) put_stackmap_type(); + while (j2-- > 0) {put_stackmap_type(); CHECK_0;} putu2(j2 = code_StackMapTable_stack_N.getInt()); - while (j2-- > 0) put_stackmap_type(); + while (j2-- > 0) {put_stackmap_type(); CHECK_0;} } } break; @@ -4470,7 +4484,9 @@ int unpacker::write_attrs(int attrc, julong indexBits) { bii += code_LocalVariableTable_span_O.getInt(); putu2(to_bci(bii) - bci); putref(code_LocalVariableTable_name_RU.getRefN()); + CHECK_0; putref(code_LocalVariableTable_type_RS.getRefN()); + CHECK_0; putu2(code_LocalVariableTable_slot.getInt()); } break; @@ -4485,7 +4501,9 @@ int unpacker::write_attrs(int attrc, julong indexBits) { bii += code_LocalVariableTypeTable_span_O.getInt(); putu2(to_bci(bii) - bci); putref(code_LocalVariableTypeTable_name_RU.getRefN()); + CHECK_0; putref(code_LocalVariableTypeTable_type_RS.getRefN()); + CHECK_0; putu2(code_LocalVariableTypeTable_slot.getInt()); } break; @@ -4513,7 +4531,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { break; } } - + CHECK_0; if (aname == null) { // Unparse a compressor-defined attribute. layout_definition* lo = ad.getLayout(idx); @@ -4669,7 +4687,9 @@ int unpacker::write_ics(int naOffset, int na) { flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero extra_ic.flags = flags; extra_ic.outer = class_InnerClasses_outer_RCN.getRefN(); + CHECK_0; extra_ic.name = class_InnerClasses_name_RUN.getRefN(); + CHECK_0; // Detect if this is an exact copy of the global tuple. if (global_ic != null) { if (global_ic->flags != extra_ic.flags || @@ -4778,6 +4798,7 @@ void unpacker::write_classfile_tail() { julong indexMask = ad.flagIndexMask(); cur_class = class_this.getRef(); + CHECK; cur_super = class_super.getRef(); CHECK; @@ -4791,6 +4812,7 @@ void unpacker::write_classfile_tail() { putu2(num = class_interface_count.getInt()); for (i = 0; i < num; i++) { putref(class_interface.getRef()); + CHECK; } write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD); From ef7ede903e93a14a736085aa6d23a5caa95ad886 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Tue, 16 Oct 2012 12:38:29 -0700 Subject: [PATCH 007/102] 7186946: Refine unpacker resource usage Reviewed-by: jrose, jjh, mschoene --- .../sun/java/util/jar/pack/NativeUnpack.java | 6 ++- .../sun/java/util/jar/pack/PackerImpl.java | 4 +- .../sun/java/util/jar/pack/UnpackerImpl.java | 6 +-- .../native/com/sun/java/util/jar/pack/jni.cpp | 40 ++++++++++++++----- .../com/sun/java/util/jar/pack/unpack.cpp | 4 +- 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java index 7e525729034..3f2f430fb84 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.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 @@ -109,6 +109,10 @@ class NativeUnpack { return (p200 == null)? null: p200._nunp; } + private synchronized long getUnpackerPtr() { + return unpackerPtr; + } + // Callback from the unpacker engine to get more data. private long readInputFn(ByteBuffer pbuf, long minlen) throws IOException { if (in == null) return 0; // nothing is readable diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java index c7ef4ee2013..dce8811e377 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java @@ -83,7 +83,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { * @param out an OutputStream * @exception IOException if an error is encountered. */ - public void pack(JarFile in, OutputStream out) throws IOException { + public synchronized void pack(JarFile in, OutputStream out) throws IOException { assert(Utils.currentInstance.get() == null); TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null @@ -118,7 +118,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { * @param out an OutputStream * @exception IOException if an error is encountered. */ - public void pack(JarInputStream in, OutputStream out) throws IOException { + public synchronized void pack(JarInputStream in, OutputStream out) throws IOException { assert(Utils.currentInstance.get() == null); TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : TimeZone.getDefault(); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java index 5727d32986e..fd8ccfd3c71 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.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 @@ -106,7 +106,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { * @param out a JarOutputStream. * @exception IOException if an error is encountered. */ - public void unpack(InputStream in, JarOutputStream out) throws IOException { + public synchronized void unpack(InputStream in, JarOutputStream out) throws IOException { if (in == null) { throw new NullPointerException("null input"); } @@ -151,7 +151,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { * @param out a JarOutputStream. * @exception IOException if an error is encountered. */ - public void unpack(File in, JarOutputStream out) throws IOException { + public synchronized void unpack(File in, JarOutputStream out) throws IOException { if (in == null) { throw new NullPointerException("null input"); } diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp index 50b5d114b39..26c683f0ae9 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp @@ -50,6 +50,7 @@ static jfieldID unpackerPtrFID; static jmethodID currentInstMID; static jmethodID readInputMID; static jclass NIclazz; +static jmethodID getUnpackerPtrMID; static char* dbg = null; @@ -60,8 +61,8 @@ static jlong read_input_via_jni(unpacker* self, static unpacker* get_unpacker(JNIEnv *env, jobject pObj, bool noCreate=false) { unpacker* uPtr; - uPtr = (unpacker*)jlong2ptr(env->GetLongField(pObj, unpackerPtrFID)); - //fprintf(stderr, "get_unpacker(%p) uPtr=%p\n", pObj, uPtr); + jlong p = env->CallLongMethod(pObj, getUnpackerPtrMID); + uPtr = (unpacker*)jlong2ptr(p); if (uPtr == null) { if (noCreate) return null; uPtr = new unpacker(); @@ -94,11 +95,15 @@ static unpacker* get_unpacker() { if (env == null) return null; jobject pObj = env->CallStaticObjectMethod(NIclazz, currentInstMID); - //fprintf(stderr, "get_unpacker() pObj=%p\n", pObj); - if (pObj == null) - return null; - // Got pObj and env; now do it the easy way. - return get_unpacker(env, pObj); + //fprintf(stderr, "get_unpacker0() pObj=%p\n", pObj); + if (pObj != null) { + // Got pObj and env; now do it the easy way. + return get_unpacker(env, pObj); + } + // this should really not happen, if it does something is seriously + // wrong throw an exception + THROW_IOE(ERROR_INTERNAL); + return null; } static void free_unpacker(JNIEnv *env, jobject pObj, unpacker* uPtr) { @@ -137,10 +142,13 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) "()Ljava/lang/Object;"); readInputMID = env->GetMethodID(clazz, "readInputFn", "(Ljava/nio/ByteBuffer;J)J"); + getUnpackerPtrMID = env->GetMethodID(clazz, "getUnpackerPtr", "()J"); + if (unpackerPtrFID == null || currentInstMID == null || readInputMID == null || - NIclazz == null) { + NIclazz == null || + getUnpackerPtrMID == null) { THROW_IOE("cannot init class members"); } } @@ -148,8 +156,13 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) JNIEXPORT jlong JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj, jobject pBuf, jlong offset) { - unpacker* uPtr = get_unpacker(env, pObj); - + // try to get the unpacker pointer the hard way first, we do this to ensure + // valid object pointers and env is intact, if not now is good time to bail. + unpacker* uPtr = get_unpacker(); + //fprintf(stderr, "start(%p) uPtr=%p initializing\n", pObj, uPtr); + if (uPtr == null) { + return -1; + } // redirect our io to the default log file or whatever. uPtr->redirect_stdio(); @@ -165,7 +178,12 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj, else { buf = (char*)buf + (size_t)offset; buflen -= (size_t)offset; } } - + // before we start off we make sure there is no other error by the time we + // get here + if (uPtr->aborting()) { + THROW_IOE(uPtr->get_abort_message()); + return 0; + } uPtr->start(buf, buflen); if (uPtr->aborting()) { THROW_IOE(uPtr->get_abort_message()); diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp index bb0e10bb32b..9c950498252 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp @@ -3117,7 +3117,7 @@ void unpacker::read_bcs() { void unpacker::read_bands() { byte* rp0 = rp; - + CHECK; read_file_header(); CHECK; @@ -3879,10 +3879,12 @@ void unpacker::dump_options() { // packed file and len is the length of the buffer. // If null, the callback is used to fill an internal buffer. void unpacker::start(void* packptr, size_t len) { + CHECK; NOT_PRODUCT(debug_u = this); if (packptr != null && len != 0) { inbytes.set((byte*) packptr, len); } + CHECK; read_bands(); } From f9122bd3fd36e7e1c113c9c50ca46ff2e29231a8 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Tue, 16 Oct 2012 16:38:38 -0700 Subject: [PATCH 008/102] 7200499: Better data validation for options Reviewed-by: darcy, jjh, mschoene --- jdk/src/share/bin/jli_util.h | 2 +- jdk/src/windows/bin/java_md.c | 32 ++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/jdk/src/share/bin/jli_util.h b/jdk/src/share/bin/jli_util.h index 568318c95c6..dd53e936210 100644 --- a/jdk/src/share/bin/jli_util.h +++ b/jdk/src/share/bin/jli_util.h @@ -66,7 +66,7 @@ int JLI_GetStdArgc(); #include #define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2)) #define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3)) -#define JLI_Snprintf _snprintf +size_t JLI_Snprintf(char *buffer, size_t size, const char *format, ...); void JLI_CmdToArgs(char *cmdline); #define JLI_Lseek _lseeki64 #else /* NIXES */ diff --git a/jdk/src/windows/bin/java_md.c b/jdk/src/windows/bin/java_md.c index e236cab1f2e..df118717279 100644 --- a/jdk/src/windows/bin/java_md.c +++ b/jdk/src/windows/bin/java_md.c @@ -101,7 +101,6 @@ int awtPreloadD3D = -1; /* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */ #define D3D_PRELOAD_FUNC "preloadD3D" - /* Extracts value of a parameter with the specified name * from command line argument (returns pointer in the argument). * Returns NULL if the argument does not contains the parameter. @@ -276,7 +275,8 @@ LoadMSVCRT() #endif #ifdef CRT_DLL if (GetJREPath(crtpath, MAXPATHLEN)) { - if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") + JLI_StrLen(CRT_DLL) >= MAXPATHLEN) { + if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") + + JLI_StrLen(CRT_DLL) >= MAXPATHLEN) { JLI_ReportErrorMessage(JRE_ERROR11); return JNI_FALSE; } @@ -347,7 +347,8 @@ GetJVMPath(const char *jrepath, const char *jvmtype, if (JLI_StrChr(jvmtype, '/') || JLI_StrChr(jvmtype, '\\')) { JLI_Snprintf(jvmpath, jvmpathsize, "%s\\" JVM_DLL, jvmtype); } else { - JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype); + JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, + jrepath, jvmtype); } if (stat(jvmpath, &s) == 0) { return JNI_TRUE; @@ -526,6 +527,29 @@ jlong Counter2Micros(jlong counts) return (counts * 1000 * 1000)/counterFrequency.QuadPart; } +/* + * windows snprintf does not guarantee a null terminator in the buffer, + * if the computed size is equal to or greater than the buffer size, + * as well as error conditions, this function guarantees a null terminator + * under all these conditions. An unreasonable buffer size will return + * an error value. + */ +size_t +JLI_Snprintf(char* buffer, size_t size, const char* format, ...) +{ + size_t rc; + va_list vl; + if (size <= 0) + return -1; + va_start(vl, format); + rc = vsnprintf(buffer, size - 1, format, vl); + /* force a null terminator, if something is amiss */ + if (rc < 0 || rc >= size) + buffer[size - 1] = '\0'; + va_end(vl); + return rc; +} + void JLI_ReportErrorMessage(const char* fmt, ...) { va_list vl; @@ -880,7 +904,7 @@ unquote(const char *s) { */ void ExecJRE(char *jre, char **argv) { - int len; + jint len; char path[MAXPATHLEN + 1]; const char *progname = GetProgramName(); From 2414c54cc122c611c359e0e736cf43256602d75a Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Tue, 16 Oct 2012 10:56:25 -0700 Subject: [PATCH 009/102] 7200500: Launcher better input validation Reviewed-by: darcy, jjh, mschoene --- jdk/src/share/bin/parse_manifest.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/bin/parse_manifest.c b/jdk/src/share/bin/parse_manifest.c index ec3014931f2..22df69cb943 100644 --- a/jdk/src/share/bin/parse_manifest.c +++ b/jdk/src/share/bin/parse_manifest.c @@ -568,9 +568,9 @@ JLI_ParseManifest(char *jarfile, manifest_info *info) #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif - )) == -1) + )) == -1) { return (-1); - + } info->manifest_version = NULL; info->main_class = NULL; info->jre_version = NULL; @@ -617,12 +617,14 @@ JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) { zentry entry; void *data = NULL; - fd = open(jarfile, O_RDONLY + if ((fd = open(jarfile, O_RDONLY #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif - ); - if (fd != -1 && find_file(fd, &entry, filename) == 0) { + )) == -1) { + return NULL; + } + if (find_file(fd, &entry, filename) == 0) { data = inflate_file(fd, &entry, size); } close(fd); @@ -664,8 +666,9 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data) #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif - )) == -1) + )) == -1) { return (-1); + } if (rc = find_file(fd, &entry, manifest_name) != 0) { close(fd); From 1193ef2418fbb3e307eb370fe769418e5b768b8f Mon Sep 17 00:00:00 2001 From: David Holmes Date: Wed, 22 Aug 2012 21:40:19 -0400 Subject: [PATCH 010/102] 6776941: Improve thread pool shutdown Reviewed-by: dl, skoivu --- .../util/concurrent/ThreadPoolExecutor.java | 172 +++++++++++------- 1 file changed, 104 insertions(+), 68 deletions(-) diff --git a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java index db7adf0e417..b7be7274d3f 100644 --- a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -34,8 +34,10 @@ */ package java.util.concurrent; -import java.util.concurrent.locks.*; -import java.util.concurrent.atomic.*; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.atomic.AtomicInteger; import java.util.*; /** @@ -491,10 +493,15 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * policy limiting the number of threads. Even though it is not * treated as an error, failure to create threads may result in * new tasks being rejected or existing ones remaining stuck in - * the queue. On the other hand, no special precautions exist to - * handle OutOfMemoryErrors that might be thrown while trying to - * create threads, since there is generally no recourse from - * within this class. + * the queue. + * + * We go further and preserve pool invariants even in the face of + * errors such as OutOfMemoryError, that might be thrown while + * trying to create threads. Such errors are rather common due to + * the need to allocate a native stack in Thread#start, and users + * will want to perform clean pool shutdown to clean up. There + * will likely be enough memory available for the cleanup code to + * complete without encountering yet another OutOfMemoryError. */ private volatile ThreadFactory threadFactory; @@ -568,9 +575,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * task execution. This protects against interrupts that are * intended to wake up a worker thread waiting for a task from * instead interrupting a task being run. We implement a simple - * non-reentrant mutual exclusion lock rather than use ReentrantLock - * because we do not want worker tasks to be able to reacquire the - * lock when they invoke pool control methods like setCorePoolSize. + * non-reentrant mutual exclusion lock rather than use + * ReentrantLock because we do not want worker tasks to be able to + * reacquire the lock when they invoke pool control methods like + * setCorePoolSize. Additionally, to suppress interrupts until + * the thread actually starts running tasks, we initialize lock + * state to a negative value, and clear it upon start (in + * runWorker). */ private final class Worker extends AbstractQueuedSynchronizer @@ -594,6 +605,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @param firstTask the first task (null if none) */ Worker(Runnable firstTask) { + setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } @@ -609,7 +621,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { // The value 1 represents the locked state. protected boolean isHeldExclusively() { - return getState() == 1; + return getState() != 0; } protected boolean tryAcquire(int unused) { @@ -630,6 +642,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService { public boolean tryLock() { return tryAcquire(1); } public void unlock() { release(1); } public boolean isLocked() { return isHeldExclusively(); } + + void interruptIfStarted() { + Thread t; + if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { + try { + t.interrupt(); + } catch (SecurityException ignore) { + } + } + } } /* @@ -728,12 +750,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { - for (Worker w : workers) { - try { - w.thread.interrupt(); - } catch (SecurityException ignore) { - } - } + for (Worker w : workers) + w.interruptIfStarted(); } finally { mainLock.unlock(); } @@ -790,19 +808,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService { private static final boolean ONLY_ONE = true; - /** - * Ensures that unless the pool is stopping, the current thread - * does not have its interrupt set. This requires a double-check - * of state in case the interrupt was cleared concurrently with a - * shutdownNow -- if so, the interrupt is re-enabled. - */ - private void clearInterruptsForTaskRun() { - if (runStateLessThan(ctl.get(), STOP) && - Thread.interrupted() && - runStateAtLeast(ctl.get(), STOP)) - Thread.currentThread().interrupt(); - } - /* * Misc utilities, most of which are also exported to * ScheduledThreadPoolExecutor @@ -862,12 +867,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * Checks if a new worker can be added with respect to current * pool state and the given bound (either core or maximum). If so, * the worker count is adjusted accordingly, and, if possible, a - * new worker is created and started running firstTask as its + * new worker is created and started, running firstTask as its * first task. This method returns false if the pool is stopped or * eligible to shut down. It also returns false if the thread - * factory fails to create a thread when asked, which requires a - * backout of workerCount, and a recheck for termination, in case - * the existence of this worker was holding up termination. + * factory fails to create a thread when asked. If the thread + * creation fails, either due to the thread factory returning + * null, or due to an exception (typically OutOfMemoryError in + * Thread#start), we roll back cleanly. * * @param firstTask the task the new thread should run first (or * null if none). Workers are created with an initial first task @@ -910,46 +916,65 @@ public class ThreadPoolExecutor extends AbstractExecutorService { } } - Worker w = new Worker(firstTask); - Thread t = w.thread; + boolean workerStarted = false; + boolean workerAdded = false; + Worker w = null; + try { + final ReentrantLock mainLock = this.mainLock; + w = new Worker(firstTask); + final Thread t = w.thread; + if (t != null) { + mainLock.lock(); + try { + // Recheck while holding lock. + // Back out on ThreadFactory failure or if + // shut down before lock acquired. + int c = ctl.get(); + int rs = runStateOf(c); + if (rs < SHUTDOWN || + (rs == SHUTDOWN && firstTask == null)) { + if (t.isAlive()) // precheck that t is startable + throw new IllegalThreadStateException(); + workers.add(w); + int s = workers.size(); + if (s > largestPoolSize) + largestPoolSize = s; + workerAdded = true; + } + } finally { + mainLock.unlock(); + } + if (workerAdded) { + t.start(); + workerStarted = true; + } + } + } finally { + if (! workerStarted) + addWorkerFailed(w); + } + return workerStarted; + } + + /** + * Rolls back the worker thread creation. + * - removes worker from workers, if present + * - decrements worker count + * - rechecks for termination, in case the existence of this + * worker was holding up termination + */ + private void addWorkerFailed(Worker w) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { - // Recheck while holding lock. - // Back out on ThreadFactory failure or if - // shut down before lock acquired. - int c = ctl.get(); - int rs = runStateOf(c); - - if (t == null || - (rs >= SHUTDOWN && - ! (rs == SHUTDOWN && - firstTask == null))) { - decrementWorkerCount(); - tryTerminate(); - return false; - } - - workers.add(w); - - int s = workers.size(); - if (s > largestPoolSize) - largestPoolSize = s; + if (w != null) + workers.remove(w); + decrementWorkerCount(); + tryTerminate(); } finally { mainLock.unlock(); } - - t.start(); - // It is possible (but unlikely) for a thread to have been - // added to workers, but not yet started, during transition to - // STOP, which could result in a rare missed interrupt, - // because Thread.interrupt is not guaranteed to have any effect - // on a non-yet-started Thread (see Thread#interrupt). - if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted()) - t.interrupt(); - - return true; } /** @@ -1096,15 +1121,25 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @param w the worker */ final void runWorker(Worker w) { + Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; + w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { w.lock(); - clearInterruptsForTaskRun(); + // If pool is stopping, ensure thread is interrupted; + // if not, ensure thread is not interrupted. This + // requires a recheck in second case to deal with + // shutdownNow race while clearing interrupt + if ((runStateAtLeast(ctl.get(), STOP) || + (Thread.interrupted() && + runStateAtLeast(ctl.get(), STOP))) && + !wt.isInterrupted()) + wt.interrupt(); try { - beforeExecute(w.thread, task); + beforeExecute(wt, task); Throwable thrown = null; try { task.run(); @@ -2064,3 +2099,4 @@ public class ThreadPoolExecutor extends AbstractExecutorService { } } } + From c8ebc97b440104b7479b1d681967fb41a41c0052 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Mon, 22 Oct 2012 07:28:51 -0700 Subject: [PATCH 011/102] 7192392: Better validation of client keys Also reviewed by Andrew Gross Reviewed-by: vinnie --- .../sun/crypto/provider/DHKeyAgreement.java | 5 + .../sun/security/pkcs11/P11KeyAgreement.java | 9 + .../sun/security/ssl/ClientHandshaker.java | 8 +- .../sun/security/ssl/DHClientKeyExchange.java | 19 +- .../classes/sun/security/ssl/DHCrypt.java | 87 ++++++-- .../sun/security/ssl/HandshakeMessage.java | 16 +- .../security/ssl/RSAClientKeyExchange.java | 4 +- .../sun/security/ssl/ServerHandshaker.java | 2 +- .../ssl/SignatureAndHashAlgorithm.java | 4 +- .../util/DisabledAlgorithmConstraints.java | 2 +- .../classes/sun/security/util/KeyLength.java | 91 -------- .../classes/sun/security/util/KeyUtil.java | 204 ++++++++++++++++++ .../security/mscapi/ShortRSAKeyWithinTLS.java | 6 +- 13 files changed, 334 insertions(+), 123 deletions(-) delete mode 100644 jdk/src/share/classes/sun/security/util/KeyLength.java create mode 100644 jdk/src/share/classes/sun/security/util/KeyUtil.java diff --git a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java index b69875dd481..33fa49297dd 100644 --- a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java +++ b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java @@ -41,6 +41,8 @@ import javax.crypto.ShortBufferException; import javax.crypto.SecretKey; import javax.crypto.spec.*; +import sun.security.util.KeyUtil; + /** * This class implements the Diffie-Hellman key agreement protocol between * any number of parties. @@ -200,6 +202,9 @@ extends KeyAgreementSpi { throw new InvalidKeyException("Incompatible parameters"); } + // validate the Diffie-Hellman public key + KeyUtil.validate(dhPubKey); + // store the y value this.y = dhPubKey.getY(); diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java b/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java index dd7c3294649..11ce2b6126b 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java @@ -37,6 +37,7 @@ import javax.crypto.spec.*; import static sun.security.pkcs11.TemplateManager.*; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; +import sun.security.util.KeyUtil; /** * KeyAgreement implementation class. This class currently supports @@ -134,6 +135,10 @@ final class P11KeyAgreement extends KeyAgreementSpi { BigInteger p, g, y; if (key instanceof DHPublicKey) { DHPublicKey dhKey = (DHPublicKey)key; + + // validate the Diffie-Hellman public key + KeyUtil.validate(dhKey); + y = dhKey.getY(); DHParameterSpec params = dhKey.getParams(); p = params.getP(); @@ -145,6 +150,10 @@ final class P11KeyAgreement extends KeyAgreementSpi { try { DHPublicKeySpec spec = kf.engineGetKeySpec( key, DHPublicKeySpec.class); + + // validate the Diffie-Hellman public key + KeyUtil.validate(spec); + y = spec.getY(); p = spec.getP(); g = spec.getG(); diff --git a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java index 63d48ad376d..0c1022b4ce7 100644 --- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java @@ -192,8 +192,12 @@ final class ClientHandshaker extends Handshaker { } break; case K_DH_ANON: - this.serverKeyExchange(new DH_ServerKeyExchange( + try { + this.serverKeyExchange(new DH_ServerKeyExchange( input, protocolVersion)); + } catch (GeneralSecurityException e) { + throwSSLException("Server key", e); + } break; case K_DHE_DSS: case K_DHE_RSA: @@ -921,7 +925,7 @@ final class ClientHandshaker extends Handshaker { case K_DHE_RSA: case K_DHE_DSS: case K_DH_ANON: - preMasterSecret = dh.getAgreedSecret(serverDH); + preMasterSecret = dh.getAgreedSecret(serverDH, true); break; case K_ECDHE_RSA: case K_ECDHE_ECDSA: diff --git a/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java b/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java index 8838193a57b..b4500988970 100644 --- a/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java +++ b/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, 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 @@ -29,7 +29,7 @@ package sun.security.ssl; import java.io.IOException; import java.io.PrintStream; import java.math.BigInteger; - +import javax.net.ssl.SSLHandshakeException; /* * Message used by clients to send their Diffie-Hellman public @@ -50,7 +50,7 @@ final class DHClientKeyExchange extends HandshakeMessage { private byte dh_Yc[]; // 1 to 2^16 -1 bytes BigInteger getClientPublicKey() { - return new BigInteger(1, dh_Yc); + return dh_Yc == null ? null : new BigInteger(1, dh_Yc); } /* @@ -72,7 +72,14 @@ final class DHClientKeyExchange extends HandshakeMessage { * but that's what the protocol spec requires.) */ DHClientKeyExchange(HandshakeInStream input) throws IOException { - dh_Yc = input.getBytes16(); + if (input.available() >= 2) { + dh_Yc = input.getBytes16(); + } else { + // currently, we don't support cipher suites that requires + // implicit public key of client. + throw new SSLHandshakeException( + "Unsupported implicit client DiffieHellman public key"); + } } int messageLength() { @@ -84,7 +91,9 @@ final class DHClientKeyExchange extends HandshakeMessage { } void send(HandshakeOutStream s) throws IOException { - s.putBytes16(dh_Yc); + if (dh_Yc != null && dh_Yc.length != 0) { + s.putBytes16(dh_Yc); + } } void print(PrintStream s) throws IOException { diff --git a/jdk/src/share/classes/sun/security/ssl/DHCrypt.java b/jdk/src/share/classes/sun/security/ssl/DHCrypt.java index d475ae8e978..ae9118f4ba5 100644 --- a/jdk/src/share/classes/sun/security/ssl/DHCrypt.java +++ b/jdk/src/share/classes/sun/security/ssl/DHCrypt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2008, 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 @@ -28,12 +28,15 @@ package sun.security.ssl; import java.math.BigInteger; import java.security.*; - +import java.io.IOException; +import javax.net.ssl.SSLHandshakeException; import javax.crypto.SecretKey; import javax.crypto.KeyAgreement; import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.*; +import sun.security.util.KeyUtil; + /** * This class implements the Diffie-Hellman key exchange algorithm. * D-H means combining your private key with your partners public key to @@ -54,7 +57,8 @@ import javax.crypto.spec.*; * . if we are server, call DHCrypt(keyLength,random). This generates * an ephemeral keypair of the request length. * . if we are client, call DHCrypt(modulus, base, random). This - * generates an ephemeral keypair using the parameters specified by the server. + * generates an ephemeral keypair using the parameters specified by + * the server. * . send parameters and public value to remote peer * . receive peers ephemeral public key * . call getAgreedSecret() to calculate the shared secret @@ -83,6 +87,9 @@ final class DHCrypt { // public component of our key, X = (g ^ x) mod p private BigInteger publicValue; // X (aka y) + // the times to recove from failure if public key validation + private static int MAX_FAILOVER_TIMES = 2; + /** * Generate a Diffie-Hellman keypair of the specified size. */ @@ -90,9 +97,12 @@ final class DHCrypt { try { KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman"); kpg.initialize(keyLength, random); - KeyPair kp = kpg.generateKeyPair(); - privateKey = kp.getPrivate(); - DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); + + DHPublicKeySpec spec = generateDHPublicKeySpec(kpg); + if (spec == null) { + throw new RuntimeException("Could not generate DH keypair"); + } + publicValue = spec.getY(); modulus = spec.getP(); base = spec.getG(); @@ -115,20 +125,25 @@ final class DHCrypt { KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman"); DHParameterSpec params = new DHParameterSpec(modulus, base); kpg.initialize(params, random); - KeyPair kp = kpg.generateKeyPair(); - privateKey = kp.getPrivate(); - DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); + + DHPublicKeySpec spec = generateDHPublicKeySpec(kpg); + if (spec == null) { + throw new RuntimeException("Could not generate DH keypair"); + } + publicValue = spec.getY(); } catch (GeneralSecurityException e) { throw new RuntimeException("Could not generate DH keypair", e); } } + static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) { if (key instanceof DHPublicKey) { DHPublicKey dhKey = (DHPublicKey)key; DHParameterSpec params = dhKey.getParams(); - return new DHPublicKeySpec(dhKey.getY(), params.getP(), params.getG()); + return new DHPublicKeySpec(dhKey.getY(), + params.getP(), params.getG()); } try { KeyFactory factory = JsseJce.getKeyFactory("DH"); @@ -166,17 +181,32 @@ final class DHCrypt { *

It is illegal to call this member function if the private key * has not been set (or generated). * - * @param peerPublicKey the peer's public key. - * @returns the secret, which is an unsigned big-endian integer - * the same size as the Diffie-Hellman modulus. + * @param peerPublicKey the peer's public key. + * @param keyIsValidated whether the {@code peerPublicKey} has beed + * validated + * @return the secret, which is an unsigned big-endian integer + * the same size as the Diffie-Hellman modulus. */ - SecretKey getAgreedSecret(BigInteger peerPublicValue) { + SecretKey getAgreedSecret(BigInteger peerPublicValue, + boolean keyIsValidated) throws IOException { try { KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman"); DHPublicKeySpec spec = new DHPublicKeySpec(peerPublicValue, modulus, base); PublicKey publicKey = kf.generatePublic(spec); KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman"); + + // validate the Diffie-Hellman public key + if (!keyIsValidated && + !KeyUtil.isOracleJCEProvider(ka.getProvider().getName())) { + try { + KeyUtil.validate(spec); + } catch (InvalidKeyException ike) { + // prefer handshake_failure alert to internal_error alert + throw new SSLHandshakeException(ike.getMessage()); + } + } + ka.init(privateKey); ka.doPhase(publicKey, true); return ka.generateSecret("TlsPremasterSecret"); @@ -185,4 +215,33 @@ final class DHCrypt { } } + // Generate and validate DHPublicKeySpec + private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg) + throws GeneralSecurityException { + + boolean doExtraValiadtion = + (!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName())); + for (int i = 0; i <= MAX_FAILOVER_TIMES; i++) { + KeyPair kp = kpg.generateKeyPair(); + privateKey = kp.getPrivate(); + DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); + + // validate the Diffie-Hellman public key + if (doExtraValiadtion) { + try { + KeyUtil.validate(spec); + } catch (InvalidKeyException ivke) { + if (i == MAX_FAILOVER_TIMES) { + throw ivke; + } + // otherwise, ignore the exception and try the next one + continue; + } + } + + return spec; + } + + return null; + } } diff --git a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java index 4b952fe9ed8..81364e07c53 100644 --- a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java +++ b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.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 @@ -41,12 +41,14 @@ import javax.security.auth.x500.X500Principal; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; +import javax.crypto.spec.DHPublicKeySpec; import javax.net.ssl.*; import sun.security.internal.spec.TlsPrfParameterSpec; import sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.PRF.*; +import sun.security.util.KeyUtil; /** * Many data structures are involved in the handshake messages. These @@ -702,6 +704,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange this.protocolVersion = protocolVersion; this.preferableSignatureAlgorithm = null; + // The DH key has been validated in the constructor of DHCrypt. setValues(obj); signature = null; } @@ -718,6 +721,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange this.protocolVersion = protocolVersion; + // The DH key has been validated in the constructor of DHCrypt. setValues(obj); Signature sig; @@ -744,7 +748,8 @@ class DH_ServerKeyExchange extends ServerKeyExchange * DH_anon key exchange */ DH_ServerKeyExchange(HandshakeInStream input, - ProtocolVersion protocolVersion) throws IOException { + ProtocolVersion protocolVersion) + throws IOException, GeneralSecurityException { this.protocolVersion = protocolVersion; this.preferableSignatureAlgorithm = null; @@ -752,6 +757,10 @@ class DH_ServerKeyExchange extends ServerKeyExchange dh_p = input.getBytes16(); dh_g = input.getBytes16(); dh_Ys = input.getBytes16(); + KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys), + new BigInteger(1, dh_p), + new BigInteger(1, dh_g))); + signature = null; } @@ -772,6 +781,9 @@ class DH_ServerKeyExchange extends ServerKeyExchange dh_p = input.getBytes16(); dh_g = input.getBytes16(); dh_Ys = input.getBytes16(); + KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys), + new BigInteger(1, dh_p), + new BigInteger(1, dh_g))); // read the signature and hash algorithm if (protocolVersion.v >= ProtocolVersion.TLS12.v) { diff --git a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java index 36fda8c39cb..7166ecdcb24 100644 --- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java +++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java @@ -36,7 +36,7 @@ import javax.crypto.spec.*; import javax.net.ssl.*; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; -import sun.security.util.KeyLength; +import sun.security.util.KeyUtil; /** * This is the client key exchange message (CLIENT --> SERVER) used with @@ -193,7 +193,7 @@ final class RSAClientKeyExchange extends HandshakeMessage { "unable to get the plaintext of the premaster secret"); } - int keySize = KeyLength.getKeySize(secretKey); + int keySize = KeyUtil.getKeySize(secretKey); if (keySize > 0 && keySize != 384) { // 384 = 48 * 8 if (debug != null && Debug.isOn("handshake")) { System.out.println( diff --git a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java index a8d256f76d6..c651b444f49 100644 --- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java @@ -1365,7 +1365,7 @@ final class ServerHandshaker extends Handshaker { if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } - return dh.getAgreedSecret(mesg.getClientPublicKey()); + return dh.getAgreedSecret(mesg.getClientPublicKey(), false); } private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg) diff --git a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java index d1bc65393bb..043b9b156f7 100644 --- a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java +++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java @@ -38,7 +38,7 @@ import java.util.Collection; import java.util.Collections; import java.util.ArrayList; -import sun.security.util.KeyLength; +import sun.security.util.KeyUtil; /** * Signature and hash algorithm. @@ -279,7 +279,7 @@ final class SignatureAndHashAlgorithm { * If key size is less than 512, the digest length should be * less than or equal to 20 bytes. */ - int keySize = KeyLength.getKeySize(signingKey); + int keySize = KeyUtil.getKeySize(signingKey); if (keySize >= 768) { maxDigestLength = HashAlgorithm.SHA512.length; } else if ((keySize >= 512) && (keySize < 768)) { diff --git a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index ca0393a323d..17b56974ea3 100644 --- a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -440,7 +440,7 @@ public class DisabledAlgorithmConstraints implements AlgorithmConstraints { // Does this key constraint disable the specified key? public boolean disables(Key key) { - int size = KeyLength.getKeySize(key); + int size = KeyUtil.getKeySize(key); if (size == 0) { return true; // we don't allow any key of size 0. diff --git a/jdk/src/share/classes/sun/security/util/KeyLength.java b/jdk/src/share/classes/sun/security/util/KeyLength.java deleted file mode 100644 index 3ffbac3f30f..00000000000 --- a/jdk/src/share/classes/sun/security/util/KeyLength.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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/KeyUtil.java b/jdk/src/share/classes/sun/security/util/KeyUtil.java new file mode 100644 index 00000000000..6664dab38b6 --- /dev/null +++ b/jdk/src/share/classes/sun/security/util/KeyUtil.java @@ -0,0 +1,204 @@ +/* + * 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.InvalidKeyException; +import java.security.interfaces.ECKey; +import java.security.interfaces.RSAKey; +import java.security.interfaces.DSAKey; +import java.security.spec.KeySpec; +import javax.crypto.SecretKey; +import javax.crypto.interfaces.DHKey; +import javax.crypto.interfaces.DHPublicKey; +import javax.crypto.spec.DHParameterSpec; +import javax.crypto.spec.DHPublicKeySpec; +import java.math.BigInteger; + +/** + * A utility class to get key length, valiate keys, etc. + */ +public final class KeyUtil { + + /** + * 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 + */ + public static final 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; + } + + /** + * Returns whether the key is valid or not. + *

+ * Note that this method is only apply to DHPublicKey at present. + * + * @param publicKey + * the key object, cannot be null + * + * @throws NullPointerException if {@code publicKey} is null + * @throws InvalidKeyException if {@code publicKey} is invalid + */ + public static final void validate(Key key) + throws InvalidKeyException { + if (key == null) { + throw new NullPointerException( + "The key to be validated cannot be null"); + } + + if (key instanceof DHPublicKey) { + validateDHPublicKey((DHPublicKey)key); + } + } + + + /** + * Returns whether the key spec is valid or not. + *

+ * Note that this method is only apply to DHPublicKeySpec at present. + * + * @param keySpec + * the key spec object, cannot be null + * + * @throws NullPointerException if {@code keySpec} is null + * @throws InvalidKeyException if {@code keySpec} is invalid + */ + public static final void validate(KeySpec keySpec) + throws InvalidKeyException { + if (keySpec == null) { + throw new NullPointerException( + "The key spec to be validated cannot be null"); + } + + if (keySpec instanceof DHPublicKeySpec) { + validateDHPublicKey((DHPublicKeySpec)keySpec); + } + } + + /** + * Returns whether the specified provider is Oracle provider or not. + *

+ * Note that this method is only apply to SunJCE and SunPKCS11 at present. + * + * @param providerName + * the provider name + * @return true if, and only if, the provider of the specified + * {@code providerName} is Oracle provider + */ + public static final boolean isOracleJCEProvider(String providerName) { + return providerName != null && (providerName.equals("SunJCE") || + providerName.startsWith("SunPKCS11")); + } + + /** + * Returns whether the Diffie-Hellman public key is valid or not. + * + * Per RFC 2631 and NIST SP800-56A, the following algorithm is used to + * validate Diffie-Hellman public keys: + * 1. Verify that y lies within the interval [2,p-1]. If it does not, + * the key is invalid. + * 2. Compute y^q mod p. If the result == 1, the key is valid. + * Otherwise the key is invalid. + */ + private static void validateDHPublicKey(DHPublicKey publicKey) + throws InvalidKeyException { + DHParameterSpec paramSpec = publicKey.getParams(); + + BigInteger p = paramSpec.getP(); + BigInteger g = paramSpec.getG(); + BigInteger y = publicKey.getY(); + + validateDHPublicKey(p, g, y); + } + + private static void validateDHPublicKey(DHPublicKeySpec publicKeySpec) + throws InvalidKeyException { + validateDHPublicKey(publicKeySpec.getP(), + publicKeySpec.getG(), publicKeySpec.getY()); + } + + private static void validateDHPublicKey(BigInteger p, + BigInteger g, BigInteger y) throws InvalidKeyException { + + // For better interoperability, the interval is limited to [2, p-2]. + BigInteger leftOpen = BigInteger.ONE; + BigInteger rightOpen = p.subtract(BigInteger.ONE); + if (y.compareTo(leftOpen) <= 0) { + throw new InvalidKeyException( + "Diffie-Hellman public key is too small"); + } + if (y.compareTo(rightOpen) >= 0) { + throw new InvalidKeyException( + "Diffie-Hellman public key is too large"); + } + + // Don't bother to check against the y^q mod p if safe primes are used. + } +} + diff --git a/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java b/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java index e4f7eb1a773..8958718ae7a 100644 --- a/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java +++ b/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java @@ -29,7 +29,7 @@ import javax.net.*; import javax.net.ssl.*; import java.lang.reflect.*; -import sun.security.util.KeyLength; +import sun.security.util.KeyUtil; public class ShortRSAKeyWithinTLS { @@ -175,13 +175,13 @@ public class ShortRSAKeyWithinTLS { privateKey = (PrivateKey)ks.getKey(keyAlias, null); publicKey = (PublicKey)ks.getCertificate(keyAlias).getPublicKey(); - int privateKeySize = KeyLength.getKeySize(privateKey); + int privateKeySize = KeyUtil.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); + int publicKeySize = KeyUtil.getKeySize(publicKey); if (publicKeySize != keySize) { throw new Exception("Expected key size is " + keySize + ", but the public key size is " + publicKeySize); From 64bb35a5c6a514314ea81dc373a5bf62eadeba76 Mon Sep 17 00:00:00 2001 From: Kurchi Subhra Hazra Date: Mon, 22 Oct 2012 11:49:37 -0700 Subject: [PATCH 012/102] 7186954: Improve connection performance Reviewed-by: chegar, skoivu --- .../sun/net/httpserver/ChunkedInputStream.java | 14 +++++++++++--- .../sun/net/www/http/ChunkedInputStream.java | 9 +++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java b/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java index 4adab7d52ed..387ec1c8e62 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java +++ b/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java @@ -41,8 +41,12 @@ class ChunkedInputStream extends LeftOverInputStream { private boolean needToReadHeader = true; - static char CR = '\r'; - static char LF = '\n'; + final static char CR = '\r'; + final static char LF = '\n'; + /* + * Maximum chunk header size of 2KB + 2 bytes for CRLF + */ + private final static int MAX_CHUNK_HEADER_SIZE = 2050; private int numeric (char[] arr, int nchars) throws IOException { assert arr.length >= nchars; @@ -73,10 +77,14 @@ class ChunkedInputStream extends LeftOverInputStream { char[] len_arr = new char [16]; int len_size = 0; boolean end_of_len = false; + int read = 0; while ((c=in.read())!= -1) { char ch = (char) c; - if (len_size == len_arr.length -1) { + read++; + if ((len_size == len_arr.length -1) || + (read > MAX_CHUNK_HEADER_SIZE)) + { throw new IOException ("invalid chunk header"); } if (gotCR) { diff --git a/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java b/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java index 3dd445e7488..af45752206f 100644 --- a/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java +++ b/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java @@ -125,6 +125,11 @@ class ChunkedInputStream extends InputStream implements Hurryable { */ private boolean closed; + /* + * Maximum chunk header size of 2KB + 2 bytes for CRLF + */ + private final static int MAX_CHUNK_HEADER_SIZE = 2050; + /** * State to indicate that next field should be :- * chunk-size [ chunk-extension ] CRLF @@ -290,6 +295,10 @@ class ChunkedInputStream extends InputStream implements Hurryable { break; } pos++; + if ((pos - rawPos) >= MAX_CHUNK_HEADER_SIZE) { + error = true; + throw new IOException("Chunk header too long"); + } } if (pos >= rawCount) { return; From 42cf97b02fd2a64bf8ab254087cdee142c4326c9 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Wed, 19 Sep 2012 12:58:43 +0800 Subject: [PATCH 013/102] 8000210: Improve JarFile code quality Reviewed-by: ahgross, xuelei, mschoene --- .../share/classes/java/util/jar/JarFile.java | 21 ++++++++++--------- .../security/util/DerIndefLenConverter.java | 4 ++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/jdk/src/share/classes/java/util/jar/JarFile.java b/jdk/src/share/classes/java/util/jar/JarFile.java index 513d509e2f8..2dbb5206512 100644 --- a/jdk/src/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/share/classes/java/util/jar/JarFile.java @@ -34,6 +34,7 @@ import java.security.CodeSigner; import java.security.cert.Certificate; import java.security.AccessController; import java.security.CodeSource; +import sun.misc.IOUtils; import sun.security.action.GetPropertyAction; import sun.security.util.ManifestEntryVerifier; import sun.misc.SharedSecrets; @@ -329,6 +330,9 @@ class JarFile extends ZipFile { if (names != null) { for (int i = 0; i < names.length; i++) { JarEntry e = getJarEntry(names[i]); + if (e == null) { + throw new JarException("corrupted jar file"); + } if (!e.isDirectory()) { if (mev == null) { mev = new ManifestEntryVerifier @@ -348,6 +352,10 @@ class JarFile extends ZipFile { // treat the jar file as being unsigned jv = null; verify = false; + if (JarVerifier.debug != null) { + JarVerifier.debug.println("jarfile parsing error!"); + ex.printStackTrace(); + } } // if after initializing the verifier we have nothing @@ -375,11 +383,9 @@ class JarFile extends ZipFile { * META-INF files. */ private byte[] getBytes(ZipEntry ze) throws IOException { - byte[] b = new byte[(int)ze.getSize()]; - try (DataInputStream is = new DataInputStream(super.getInputStream(ze))) { - is.readFully(b, 0, b.length); + try (InputStream is = super.getInputStream(ze)) { + return IOUtils.readFully(is, (int)ze.getSize(), true); } - return b; } /** @@ -479,12 +485,7 @@ class JarFile extends ZipFile { if (!isKnownToNotHaveClassPathAttribute()) { JarEntry manEntry = getManEntry(); if (manEntry != null) { - byte[] b = new byte[(int)manEntry.getSize()]; - try (DataInputStream dis = new DataInputStream( - super.getInputStream(manEntry))) { - dis.readFully(b, 0, b.length); - } - + byte[] b = getBytes(manEntry); int last = b.length - src.length; int i = 0; next: diff --git a/jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java b/jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java index 50bb06ad7b3..78d9e302d6c 100644 --- a/jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java +++ b/jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java @@ -325,6 +325,10 @@ class DerIndefLenConverter { } } + if (unresolved != 0) { + throw new IOException("not all indef len BER resolved"); + } + newData = new byte[dataSize + numOfTotalLenBytes + unused]; dataPos=0; newDataPos=0; index=0; From cb3cb72e07d5e881ca4fc5f36e1b8dcd11c28d78 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Fri, 26 Oct 2012 15:21:05 -0400 Subject: [PATCH 014/102] 7201068: Better handling of UI elements Reviewed-by: xuelei --- jdk/src/share/lib/security/java.security | 16 ++++++++++++++-- .../share/lib/security/java.security-macosx | 18 ++++++++++++++++-- .../share/lib/security/java.security-solaris | 16 ++++++++++++++-- .../share/lib/security/java.security-windows | 16 ++++++++++++++-- 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/lib/security/java.security b/jdk/src/share/lib/security/java.security index 3bb8597654c..d0dc3c5b423 100644 --- a/jdk/src/share/lib/security/java.security +++ b/jdk/src/share/lib/security/java.security @@ -145,7 +145,13 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. +package.access=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal. # # List of comma-separated packages that start with or equal this string @@ -157,7 +163,13 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. +package.definition=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx index 689172f40d6..22c6b44c567 100644 --- a/jdk/src/share/lib/security/java.security-macosx +++ b/jdk/src/share/lib/security/java.security-macosx @@ -146,7 +146,14 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. +package.access=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + apple. # # List of comma-separated packages that start with or equal this string @@ -158,7 +165,14 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. +package.definition=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + apple. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index 1c5062c4c8b..c26b06a8de4 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -147,7 +147,13 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. +package.access=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal. # # List of comma-separated packages that start with or equal this string @@ -159,7 +165,13 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. +package.definition=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows index c98c0c95865..f9103a98718 100644 --- a/jdk/src/share/lib/security/java.security-windows +++ b/jdk/src/share/lib/security/java.security-windows @@ -146,7 +146,13 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. +package.access=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal. # # List of comma-separated packages that start with or equal this string @@ -158,7 +164,13 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. +package.definition=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal. # # Determines whether this properties file can be appended to From 526b1f405ca7a6b8646905a44d9083eea3a6c810 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 30 Oct 2012 17:05:45 +0400 Subject: [PATCH 015/102] 8000539: JMX implementation allows invocation of methods of a system class Added extra packageAccess check call Reviewed-by: ahgross, dfuchs --- .../classes/com/sun/jmx/mbeanserver/Introspector.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java index 2e259a818c8..365a004778e 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java @@ -56,6 +56,8 @@ import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import javax.management.AttributeNotFoundException; import javax.management.openmbean.CompositeData; +import sun.reflect.misc.MethodUtil; +import sun.reflect.misc.ReflectUtil; /** * This class contains the methods for performing all the tests needed to verify @@ -528,8 +530,10 @@ public class Introspector { // to locate method readMethod = SimpleIntrospector.getReadMethod(clazz, element); } - if (readMethod != null) - return readMethod.invoke(complex); + if (readMethod != null) { + ReflectUtil.checkPackageAccess(readMethod.getDeclaringClass()); + return MethodUtil.invoke(readMethod, complex, new Class[0]); + } throw new AttributeNotFoundException( "Could not find the getter method for the property " + From d3ccd20d1fc444e6ea7b314d5aaf23a718ab5054 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Fri, 2 Nov 2012 16:50:23 -0700 Subject: [PATCH 016/102] 7197546: (proxy) Reflect about creating reflective proxies Reviewed-by: alanb, jdn, jrose --- jdk/src/share/classes/java/lang/Class.java | 50 +++--- .../java/lang/invoke/MethodHandleProxies.java | 73 ++++++--- .../classes/java/lang/reflect/Proxy.java | 154 +++++++++++++++++- .../classes/sun/reflect/misc/ReflectUtil.java | 25 +++ .../loadProxyClasses/security.policy | 1 + 5 files changed, 254 insertions(+), 49 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index ec9d9725655..a22493feb6f 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -60,7 +60,9 @@ import sun.reflect.generics.repository.ConstructorRepository; import sun.reflect.generics.scope.ClassScope; import sun.security.util.SecurityConstants; import java.lang.annotation.Annotation; +import java.lang.reflect.Proxy; import sun.reflect.annotation.*; +import sun.reflect.misc.ReflectUtil; /** * Instances of the class {@code Class} represent classes and @@ -247,11 +249,11 @@ public final ClassLoader loader) throws ClassNotFoundException { - if (loader == null) { + if (sun.misc.VM.isSystemDomainLoader(loader)) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { ClassLoader ccl = ClassLoader.getCallerClassLoader(); - if (ccl != null) { + if (!sun.misc.VM.isSystemDomainLoader(ccl)) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } @@ -316,7 +318,7 @@ public final throws InstantiationException, IllegalAccessException { if (System.getSecurityManager() != null) { - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); } return newInstance0(); } @@ -1295,7 +1297,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); // Privileged so this implementation can look at DECLARED classes, // something the caller might not have privilege to do. The code here @@ -1370,7 +1372,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); return copyFields(privateGetPublicFields(null)); } @@ -1421,7 +1423,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); return copyMethods(privateGetPublicMethods()); } @@ -1470,7 +1472,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); return copyConstructors(privateGetDeclaredConstructors(true)); } @@ -1529,7 +1531,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); @@ -1614,7 +1616,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); Method method = getMethod0(name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); @@ -1668,7 +1670,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); return getConstructor0(parameterTypes, Member.PUBLIC); } @@ -1710,7 +1712,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false); return getDeclaredClasses0(); } @@ -1754,7 +1756,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); return copyFields(privateGetDeclaredFields(false)); } @@ -1802,7 +1804,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); return copyMethods(privateGetDeclaredMethods(false)); } @@ -1847,7 +1849,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); return copyConstructors(privateGetDeclaredConstructors(false)); } @@ -1891,7 +1893,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); @@ -1946,7 +1948,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); @@ -1996,7 +1998,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); return getConstructor0(parameterTypes, Member.DECLARED); } @@ -2166,18 +2168,26 @@ public final *

Default policy: allow all clients access with normal Java access * control. */ - private void checkMemberAccess(int which, ClassLoader ccl) { + private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) { SecurityManager s = System.getSecurityManager(); if (s != null) { s.checkMemberAccess(this, which); ClassLoader cl = getClassLoader0(); - if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(ccl, cl)) { + if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { String name = this.getName(); int i = name.lastIndexOf('.'); if (i != -1) { - s.checkPackageAccess(name.substring(0, i)); + // skip the package access check on a proxy class in default proxy package + String pkg = name.substring(0, i); + if (!Proxy.isProxyClass(this) || !pkg.equals(ReflectUtil.PROXY_PACKAGE)) { + s.checkPackageAccess(pkg); + } } } + // check package access on the proxy interfaces + if (checkProxyInterfaces && Proxy.isProxyClass(this)) { + ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces()); + } } } diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java index 8e068238b1f..e305ced7de4 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -26,8 +26,12 @@ package java.lang.invoke; import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; import sun.invoke.WrapperInstance; import java.util.ArrayList; +import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; /** * This class consists exclusively of static methods that help adapt @@ -137,6 +141,18 @@ public class MethodHandleProxies { T asInterfaceInstance(final Class intfc, final MethodHandle target) { if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) throw new IllegalArgumentException("not a public interface: "+intfc.getName()); + SecurityManager smgr = System.getSecurityManager(); + if (smgr != null) { + final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller + final Class caller = Reflection.getCallerClass(CALLER_FRAME); + final ClassLoader ccl = caller.getClassLoader(); + ReflectUtil.checkProxyPackageAccess(ccl, intfc); + } + ClassLoader proxyLoader = intfc.getClassLoader(); + if (proxyLoader == null) { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); // avoid use of BCP + proxyLoader = cl != null ? cl : ClassLoader.getSystemClassLoader(); + } final Method[] methods = getSingleNameMethods(intfc); if (methods == null) throw new IllegalArgumentException("not a single-method interface: "+intfc.getName()); @@ -148,27 +164,44 @@ public class MethodHandleProxies { checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class)); vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount()); } - return intfc.cast(Proxy.newProxyInstance( - intfc.getClassLoader(), - new Class[]{ intfc, WrapperInstance.class }, - new InvocationHandler() { - private Object getArg(String name) { - if ((Object)name == "getWrapperInstanceTarget") return target; - if ((Object)name == "getWrapperInstanceType") return intfc; - throw new AssertionError(); + final InvocationHandler ih = new InvocationHandler() { + private Object getArg(String name) { + if ((Object)name == "getWrapperInstanceTarget") return target; + if ((Object)name == "getWrapperInstanceType") return intfc; + throw new AssertionError(); + } + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + for (int i = 0; i < methods.length; i++) { + if (method.equals(methods[i])) + return vaTargets[i].invokeExact(args); } - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - for (int i = 0; i < methods.length; i++) { - if (method.equals(methods[i])) - return vaTargets[i].invokeExact(args); - } - if (method.getDeclaringClass() == WrapperInstance.class) - return getArg(method.getName()); - if (isObjectMethod(method)) - return callObjectMethod(proxy, method, args); - throw new InternalError("bad proxy method: "+method); - } - })); + if (method.getDeclaringClass() == WrapperInstance.class) + return getArg(method.getName()); + if (isObjectMethod(method)) + return callObjectMethod(proxy, method, args); + throw new InternalError("bad proxy method: "+method); + } + }; + + Object proxy; + if (smgr != null) { + // sun.invoke.WrapperInstance is a restricted interface not accessible + // by any non-null class loader. + final ClassLoader loader = proxyLoader; + proxy = AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return Proxy.newProxyInstance( + loader, + new Class[]{ intfc, WrapperInstance.class }, + ih); + } + }); + } else { + proxy = Proxy.newProxyInstance(proxyLoader, + new Class[]{ intfc, WrapperInstance.class }, + ih); + } + return intfc.cast(proxy); } /** diff --git a/jdk/src/share/classes/java/lang/reflect/Proxy.java b/jdk/src/share/classes/java/lang/reflect/Proxy.java index c2420915031..d7299b20dbb 100644 --- a/jdk/src/share/classes/java/lang/reflect/Proxy.java +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java @@ -27,6 +27,9 @@ package java.lang.reflect; import java.lang.ref.Reference; import java.lang.ref.WeakReference; +import java.security.AccessController; +import java.security.Permission; +import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -36,6 +39,9 @@ import java.util.Set; import java.util.List; import java.util.WeakHashMap; import sun.misc.ProxyGenerator; +import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; +import sun.security.util.SecurityConstants; /** * {@code Proxy} provides static methods for creating dynamic proxy @@ -265,9 +271,69 @@ public class Proxy implements java.io.Serializable { * @param h the invocation handler for this proxy instance */ protected Proxy(InvocationHandler h) { + doNewInstanceCheck(); this.h = h; } + private static class ProxyAccessHelper { + // The permission is implementation specific. + static final Permission PROXY_PERMISSION = + new ReflectPermission("proxyConstructorNewInstance"); + // These system properties are defined to provide a short-term + // workaround if customers need to disable the new security checks. + static final boolean allowNewInstance; + static final boolean allowNullLoader; + static { + allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance"); + allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader"); + } + + private static boolean getBooleanProperty(final String key) { + String s = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty(key); + } + }); + return Boolean.valueOf(s); + } + + static boolean needsNewInstanceCheck(Class proxyClass) { + if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) { + return false; + } + + if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) { + // all proxy interfaces are public + return false; + } + for (Class intf : proxyClass.getInterfaces()) { + if (!Modifier.isPublic(intf.getModifiers())) { + return true; + } + } + return false; + } + } + + /* + * Access check on a proxy class that implements any non-public interface. + * + * @throws SecurityException if a security manager exists, and + * the caller does not have the permission. + */ + private void doNewInstanceCheck() { + SecurityManager sm = System.getSecurityManager(); + Class proxyClass = this.getClass(); + if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) { + try { + sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION); + } catch (SecurityException e) { + throw new SecurityException("Not allowed to construct a Proxy " + + "instance that implements a non-public interface", e); + } + } + } + /** * Returns the {@code java.lang.Class} object for a proxy class * given a class loader and an array of interfaces. The proxy class @@ -346,6 +412,51 @@ public class Proxy implements java.io.Serializable { Class... interfaces) throws IllegalArgumentException { + return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor + } + + private static void checkProxyLoader(ClassLoader ccl, + ClassLoader loader) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (loader == null && ccl != null) { + if (!ProxyAccessHelper.allowNullLoader) { + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); + } + } + } + } + + /* + * Generate a proxy class (caller-sensitive). + * + * To define a proxy class, it performs the access checks as in + * Class.forName (VM will invoke ClassLoader.checkPackageAccess): + * 1. "getClassLoader" permission check if loader == null + * 2. checkPackageAccess on the interfaces it implements + * + * To get a constructor and new instance of a proxy class, it performs + * the package access check on the interfaces it implements + * as in Class.getConstructor. + * + * If an interface is non-public, the proxy class must be defined by + * the defining loader of the interface. If the caller's class loader + * is not the same as the defining loader of the interface, the VM + * will throw IllegalAccessError when the generated proxy class is + * being defined via the defineClass0 method. + */ + private static Class getProxyClass0(ClassLoader loader, + Class... interfaces) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller + final Class caller = Reflection.getCallerClass(CALLER_FRAME); + final ClassLoader ccl = caller.getClassLoader(); + checkProxyLoader(ccl, loader); + ReflectUtil.checkProxyPackageAccess(ccl, interfaces); + } + if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } @@ -497,8 +608,9 @@ public class Proxy implements java.io.Serializable { } } - if (proxyPkg == null) { // if no non-public proxy interfaces, - proxyPkg = ""; // use the unnamed package + if (proxyPkg == null) { + // if no non-public proxy interfaces, use sun.proxy package + proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } { @@ -598,22 +710,46 @@ public class Proxy implements java.io.Serializable { /* * Look up or generate the designated proxy class. */ - Class cl = getProxyClass(loader, interfaces); + Class cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor /* * Invoke its constructor with the designated invocation handler. */ try { - Constructor cons = cl.getConstructor(constructorParams); - return cons.newInstance(new Object[] { h }); - } catch (NoSuchMethodException | - IllegalAccessException | - InstantiationException | - InvocationTargetException e) { + final Constructor cons = cl.getConstructor(constructorParams); + final InvocationHandler ih = h; + SecurityManager sm = System.getSecurityManager(); + if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { + // create proxy instance with doPrivilege as the proxy class may + // implement non-public interfaces that requires a special permission + return AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return newInstance(cons, ih); + } + }); + } else { + return newInstance(cons, ih); + } + } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } } + private static Object newInstance(Constructor cons, InvocationHandler h) { + try { + return cons.newInstance(new Object[] {h} ); + } catch (IllegalAccessException | InstantiationException e) { + throw new InternalError(e.toString(), e); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else { + throw new InternalError(t.toString(), t); + } + } + } + /** * Returns true if and only if the specified class was dynamically * generated to be a proxy class using the {@code getProxyClass} diff --git a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java index 5a90c28db41..06956101dcc 100644 --- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java @@ -178,4 +178,29 @@ public final class ReflectUtil { return !isAncestor(from, to); } + + /** + * Access check on the interfaces that a proxy class implements and throw + * {@code SecurityException} if it accesses a restricted package. + * + * @param ccl the caller's class loader + * @param interfaces the list of interfaces that a proxy class implements + * + * @see Proxy#checkProxyAccess + */ + public static void checkProxyPackageAccess(ClassLoader ccl, + Class... interfaces) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + for (Class intf : interfaces) { + ClassLoader cl = intf.getClassLoader(); + if (needsPackageAccessCheck(ccl, cl)) { + checkPackageAccess(intf); + } + } + } + } + + public static final String PROXY_PACKAGE = "sun.proxy"; } diff --git a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy index f6e312ec696..3ba44491aca 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy +++ b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy @@ -13,6 +13,7 @@ grant { permission java.io.FilePermission ".${/}-", "read,write,delete"; permission java.lang.RuntimePermission "createClassLoader"; + permission java.lang.RuntimePermission "getClassLoader"; permission java.lang.RuntimePermission "setContextClassLoader"; // used by TestLibrary to determine test environment From ec9f5edf2ffc128e326fe56b056c6bfa45c7532e Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Tue, 6 Nov 2012 15:30:34 +0400 Subject: [PATCH 017/102] 7200491: Tighten up JTable layout code Reviewed-by: art, skoivu --- jdk/src/share/classes/javax/swing/JTable.java | 14 +++++--------- .../javax/swing/plaf/nimbus/NimbusLookAndFeel.java | 7 ++++++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/JTable.java b/jdk/src/share/classes/javax/swing/JTable.java index fbd61d9a9fc..05fc918e9eb 100644 --- a/jdk/src/share/classes/javax/swing/JTable.java +++ b/jdk/src/share/classes/javax/swing/JTable.java @@ -781,15 +781,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER); if (corner == null || corner instanceof UIResource){ corner = null; - Object componentClass = UIManager.get( - "Table.scrollPaneCornerComponent"); - if (componentClass instanceof Class){ - try { - corner = (Component) - ((Class)componentClass).newInstance(); - } catch (Exception e) { - // just ignore and don't set corner - } + try { + corner = (Component) UIManager.get( + "Table.scrollPaneCornerComponent"); + } catch (Exception e) { + // just ignore and don't set corner } scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER, corner); diff --git a/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java b/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java index b03bf653fc5..402a6885982 100644 --- a/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java +++ b/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java @@ -159,7 +159,12 @@ public class NimbusLookAndFeel extends SynthLookAndFeel { // Store Table ScrollPane Corner Component uiDefaults.put("Table.scrollPaneCornerComponent", - TableScrollPaneCorner.class); + new UIDefaults.ActiveValue() { + @Override + public Object createValue(UIDefaults table) { + return new TableScrollPaneCorner(); + } + }); // Setup the settings for ToolBarSeparator which is custom // installed for Nimbus From 90f2168fa25b2cf418cfd789161daa0ae4e38400 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 7 Nov 2012 14:26:41 +0000 Subject: [PATCH 018/102] 7201071: InetSocketAddress serialization issue Reviewed-by: alanb, michaelm, skoivu --- .../classes/java/net/InetSocketAddress.java | 272 ++++++++++++------ .../sun/nio/ch/DatagramChannelImpl.java | 18 +- .../sun/nio/ch/sctp/SctpChannelImpl.java | 14 +- .../sun/nio/ch/sctp/SctpMultiChannelImpl.java | 16 +- .../native/sun/nio/ch/DatagramChannelImpl.c | 9 +- .../native/sun/nio/ch/sctp/SctpChannelImpl.c | 27 +- .../native/sun/nio/ch/DatagramChannelImpl.c | 10 +- .../DatagramChannel/SendToUnresolved.java | 2 +- 8 files changed, 225 insertions(+), 143 deletions(-) diff --git a/jdk/src/share/classes/java/net/InetSocketAddress.java b/jdk/src/share/classes/java/net/InetSocketAddress.java index b250b18ce5a..d4322e9b427 100644 --- a/jdk/src/share/classes/java/net/InetSocketAddress.java +++ b/jdk/src/share/classes/java/net/InetSocketAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -24,9 +24,12 @@ */ package java.net; -import java.io.ObjectInputStream; import java.io.IOException; import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamException; +import java.io.ObjectStreamField; /** * @@ -46,23 +49,105 @@ import java.io.InvalidObjectException; * @see java.net.ServerSocket * @since 1.4 */ -public class InetSocketAddress extends SocketAddress { - /* The hostname of the Socket Address - * @serial - */ - private String hostname = null; - /* The IP address of the Socket Address - * @serial - */ - private InetAddress addr = null; - /* The port number of the Socket Address - * @serial - */ - private int port; +public class InetSocketAddress + extends SocketAddress +{ + // Private implementation class pointed to by all public methods. + private static class InetSocketAddressHolder { + // The hostname of the Socket Address + private String hostname; + // The IP address of the Socket Address + private InetAddress addr; + // The port number of the Socket Address + private int port; + + private InetSocketAddressHolder(String hostname, InetAddress addr, int port) { + this.hostname = hostname; + this.addr = addr; + this.port = port; + } + + private int getPort() { + return port; + } + + private InetAddress getAddress() { + return addr; + } + + private String getHostName() { + if (hostname != null) + return hostname; + if (addr != null) + return addr.getHostName(); + return null; + } + + private String getHostString() { + if (hostname != null) + return hostname; + if (addr != null) { + if (addr.hostName != null) + return addr.hostName; + else + return addr.getHostAddress(); + } + return null; + } + + private boolean isUnresolved() { + return addr == null; + } + + @Override + public String toString() { + if (isUnresolved()) { + return hostname + ":" + port; + } else { + return addr.toString() + ":" + port; + } + } + + @Override + public final boolean equals(Object obj) { + if (obj == null || !(obj instanceof InetSocketAddressHolder)) + return false; + InetSocketAddressHolder that = (InetSocketAddressHolder)obj; + boolean sameIP; + if (addr != null) + sameIP = addr.equals(that.addr); + else if (hostname != null) + sameIP = (that.addr == null) && + hostname.equalsIgnoreCase(that.hostname); + else + sameIP = (that.addr == null) && (that.hostname == null); + return sameIP && (port == that.port); + } + + @Override + public final int hashCode() { + if (addr != null) + return addr.hashCode() + port; + if (hostname != null) + return hostname.toLowerCase().hashCode() + port; + return port; + } + } + + private final transient InetSocketAddressHolder holder; private static final long serialVersionUID = 5076001401234631237L; - private InetSocketAddress() { + private static int checkPort(int port) { + if (port < 0 || port > 0xFFFF) + throw new IllegalArgumentException("port out of range:" + port); + return port; + } + + private static String checkHost(String hostname) { + if (hostname == null) + throw new IllegalArgumentException("hostname can't be null"); + return hostname; } /** @@ -97,14 +182,10 @@ public class InetSocketAddress extends SocketAddress { * range of valid port values. */ public InetSocketAddress(InetAddress addr, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - this.port = port; - if (addr == null) - this.addr = InetAddress.anyLocalAddress(); - else - this.addr = addr; + holder = new InetSocketAddressHolder( + null, + addr == null ? InetAddress.anyLocalAddress() : addr, + checkPort(port)); } /** @@ -132,19 +213,20 @@ public class InetSocketAddress extends SocketAddress { * @see #isUnresolved() */ public InetSocketAddress(String hostname, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - if (hostname == null) { - throw new IllegalArgumentException("hostname can't be null"); - } + checkHost(hostname); + InetAddress addr = null; + String host = null; try { addr = InetAddress.getByName(hostname); } catch(UnknownHostException e) { - this.hostname = hostname; - addr = null; + host = hostname; } - this.port = port; + holder = new InetSocketAddressHolder(host, addr, checkPort(port)); + } + + // private constructor for creating unresolved instances + private InetSocketAddress(int port, String hostname) { + holder = new InetSocketAddressHolder(hostname, null, port); } /** @@ -169,31 +251,67 @@ public class InetSocketAddress extends SocketAddress { * @since 1.5 */ public static InetSocketAddress createUnresolved(String host, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - if (host == null) { - throw new IllegalArgumentException("hostname can't be null"); - } - InetSocketAddress s = new InetSocketAddress(); - s.port = port; - s.hostname = host; - s.addr = null; - return s; + return new InetSocketAddress(checkPort(port), checkHost(host)); } - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject(); + /** + * @serialField hostname String + * @serialField addr InetAddress + * @serialField port int + */ + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("hostname", String.class), + new ObjectStreamField("addr", InetAddress.class), + new ObjectStreamField("port", int.class)}; + + private void writeObject(ObjectOutputStream out) + throws IOException + { + // Don't call defaultWriteObject() + ObjectOutputStream.PutField pfields = out.putFields(); + pfields.put("hostname", holder.hostname); + pfields.put("addr", holder.addr); + pfields.put("port", holder.port); + out.writeFields(); + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException + { + // Don't call defaultReadObject() + ObjectInputStream.GetField oisFields = in.readFields(); + final String oisHostname = (String)oisFields.get("hostname", null); + final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null); + final int oisPort = oisFields.get("port", -1); // Check that our invariants are satisfied - if (port < 0 || port > 0xFFFF) { - throw new InvalidObjectException("port out of range:" + port); - } - - if (hostname == null && addr == null) { + checkPort(oisPort); + if (oisHostname == null && oisAddr == null) throw new InvalidObjectException("hostname and addr " + "can't both be null"); + + InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname, + oisAddr, + oisPort); + UNSAFE.putObject(this, FIELDS_OFFSET, h); + } + + private void readObjectNoData() + throws ObjectStreamException + { + throw new InvalidObjectException("Stream data required"); + } + + private static final long FIELDS_OFFSET; + private static final sun.misc.Unsafe UNSAFE; + static { + try { + sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + FIELDS_OFFSET = unsafe.objectFieldOffset( + InetSocketAddress.class.getDeclaredField("holder")); + UNSAFE = unsafe; + } catch (ReflectiveOperationException e) { + throw new Error(e); } } @@ -203,7 +321,7 @@ public class InetSocketAddress extends SocketAddress { * @return the port number. */ public final int getPort() { - return port; + return holder.getPort(); } /** @@ -213,7 +331,7 @@ public class InetSocketAddress extends SocketAddress { * @return the InetAdress or null if it is unresolved. */ public final InetAddress getAddress() { - return addr; + return holder.getAddress(); } /** @@ -224,31 +342,19 @@ public class InetSocketAddress extends SocketAddress { * @return the hostname part of the address. */ public final String getHostName() { - if (hostname != null) - return hostname; - if (addr != null) - return addr.getHostName(); - return null; + return holder.getHostName(); } /** * Returns the hostname, or the String form of the address if it * doesn't have a hostname (it was created using a literal). - * This has the benefit of not attemptimg a reverse lookup. + * This has the benefit of not attempting a reverse lookup. * * @return the hostname, or String representation of the address. * @since 1.7 */ public final String getHostString() { - if (hostname != null) - return hostname; - if (addr != null) { - if (addr.hostName != null) - return addr.hostName; - else - return addr.getHostAddress(); - } - return null; + return holder.getHostString(); } /** @@ -258,7 +364,7 @@ public class InetSocketAddress extends SocketAddress { * an InetAddress. */ public final boolean isUnresolved() { - return addr == null; + return holder.isUnresolved(); } /** @@ -269,12 +375,9 @@ public class InetSocketAddress extends SocketAddress { * * @return a string representation of this object. */ + @Override public String toString() { - if (isUnresolved()) { - return hostname + ":" + port; - } else { - return addr.toString() + ":" + port; - } + return holder.toString(); } /** @@ -297,19 +400,11 @@ public class InetSocketAddress extends SocketAddress { * false otherwise. * @see java.net.InetAddress#equals(java.lang.Object) */ + @Override public final boolean equals(Object obj) { if (obj == null || !(obj instanceof InetSocketAddress)) return false; - InetSocketAddress sockAddr = (InetSocketAddress) obj; - boolean sameIP = false; - if (this.addr != null) - sameIP = this.addr.equals(sockAddr.addr); - else if (this.hostname != null) - sameIP = (sockAddr.addr == null) && - this.hostname.equalsIgnoreCase(sockAddr.hostname); - else - sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null); - return sameIP && (this.port == sockAddr.port); + return holder.equals(((InetSocketAddress) obj).holder); } /** @@ -317,11 +412,8 @@ public class InetSocketAddress extends SocketAddress { * * @return a hash code value for this socket address. */ + @Override public final int hashCode() { - if (addr != null) - return addr.hashCode() + port; - if (hostname != null) - return hostname.toLowerCase().hashCode() + port; - return port; + return holder.hashCode(); } } diff --git a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java index 3d60a38d74c..ff2ee589600 100644 --- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -421,7 +421,7 @@ class DatagramChannelImpl synchronized (writeLock) { ensureOpen(); - InetSocketAddress isa = (InetSocketAddress)target; + InetSocketAddress isa = Net.checkAddress(target); InetAddress ia = isa.getAddress(); if (ia == null) throw new IOException("Target address not resolved"); @@ -432,9 +432,9 @@ class DatagramChannelImpl SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (ia.isMulticastAddress()) { - sm.checkMulticast(isa.getAddress()); + sm.checkMulticast(ia); } else { - sm.checkConnect(isa.getAddress().getHostAddress(), + sm.checkConnect(ia.getHostAddress(), isa.getPort()); } } @@ -454,7 +454,7 @@ class DatagramChannelImpl return 0; writerThread = NativeThread.current(); do { - n = send(fd, src, target); + n = send(fd, src, isa); } while ((n == IOStatus.INTERRUPTED) && isOpen()); synchronized (stateLock) { @@ -471,7 +471,7 @@ class DatagramChannelImpl } } - private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target) + private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target) throws IOException { if (src instanceof DirectBuffer) @@ -502,7 +502,7 @@ class DatagramChannelImpl } private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, - SocketAddress target) + InetSocketAddress target) throws IOException { int pos = bb.position(); @@ -514,7 +514,7 @@ class DatagramChannelImpl int written; try { written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos, - rem, target); + rem, target.getAddress(), target.getPort()); } catch (PortUnreachableException pue) { if (isConnected()) throw pue; @@ -1116,8 +1116,8 @@ class DatagramChannelImpl boolean connected) throws IOException; - private native int send0(boolean preferIPv6, FileDescriptor fd, long address, int len, - SocketAddress sa) + private native int send0(boolean preferIPv6, FileDescriptor fd, long address, + int len, InetAddress addr, int port) throws IOException; static { diff --git a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java index 92f17cb3e8b..411e33c4e84 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java @@ -1026,13 +1026,21 @@ public class SctpChannelImpl extends SctpChannel boolean unordered, int ppid) throws IOException { + InetAddress addr = null; // no preferred address + int port = 0; + if (target != null) { + InetSocketAddress isa = Net.checkAddress(target); + addr = isa.getAddress(); + port = isa.getPort(); + } + int pos = bb.position(); int lim = bb.limit(); assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, - rem, target, -1 /*121*/, streamNumber, unordered, ppid); + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, -1 /*121*/, streamNumber, unordered, ppid); if (written > 0) bb.position(pos + written); return written; @@ -1091,7 +1099,7 @@ public class SctpChannelImpl extends SctpChannel long address, int length, boolean peek) throws IOException; static native int send0(int fd, long address, int length, - SocketAddress target, int assocId, int streamNumber, + InetAddress addr, int port, int assocId, int streamNumber, boolean unordered, int ppid) throws IOException; private static native int checkConnect(FileDescriptor fd, boolean block, diff --git a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java index fa44072f4dc..63dc94931da 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java @@ -889,13 +889,20 @@ public class SctpMultiChannelImpl extends SctpMultiChannel boolean unordered, int ppid) throws IOException { + InetAddress addr = null; // no preferred address + int port = 0; + if (target != null) { + InetSocketAddress isa = Net.checkAddress(target); + addr = isa.getAddress(); + port = isa.getPort(); + } int pos = bb.position(); int lim = bb.limit(); assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, - rem, target, assocId, streamNumber, unordered, ppid); + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, assocId, streamNumber, unordered, ppid); if (written > 0) bb.position(pos + written); return written; @@ -976,13 +983,14 @@ public class SctpMultiChannelImpl extends SctpMultiChannel private static int send0(int fd, long address, int length, - SocketAddress target, + InetAddress addr, + int port, int assocId, int streamNumber, boolean unordered, int ppid) throws IOException { - return SctpChannelImpl.send0(fd, address, length, target, assocId, + return SctpChannelImpl.send0(fd, address, length, addr, port, assocId, streamNumber, unordered, ppid); } diff --git a/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c index 3bccd574871..c460d61f9c4 100644 --- a/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c +++ b/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c @@ -46,8 +46,6 @@ #include "sun_nio_ch_DatagramChannelImpl.h" -static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */ -static jfieldID isa_portID; /* port in java.net.InetSocketAddress */ static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */ @@ -61,9 +59,6 @@ Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz) isa_class = (*env)->NewGlobalRef(env, clazz); isa_ctorID = (*env)->GetMethodID(env, clazz, "", "(Ljava/net/InetAddress;I)V"); - isa_addrID = (*env)->GetFieldID(env, clazz, "addr", - "Ljava/net/InetAddress;"); - isa_portID = (*env)->GetFieldID(env, clazz, "port", "I"); clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl"); dci_senderID = (*env)->GetFieldID(env, clazz, "sender", @@ -212,15 +207,13 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this, JNIEXPORT jint JNICALL Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this, jboolean preferIPv6, jobject fdo, jlong address, - jint len, jobject dest) + jint len, jobject destAddress, jint destPort) { jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); SOCKADDR sa; int sa_len = SOCKADDR_LEN; jint n = 0; - jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID); - jint destPort = (*env)->GetIntField(env, dest, isa_portID); if (len > MAX_PACKET_LEN) { len = MAX_PACKET_LEN; diff --git a/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c index 4333720c3d8..77ef9423e5c 100644 --- a/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c +++ b/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c @@ -67,8 +67,6 @@ static jclass spc_class; /* sun.nio.ch.sctp.PeerAddressChanged */ static jmethodID spc_ctrID; /* sun.nio.ch.sctp.PeerAddressChanged. */ static jclass ss_class; /* sun.nio.ch.sctp.Shutdown */ static jmethodID ss_ctrID; /* sun.nio.ch.sctp.Shutdown. */ -static jfieldID isa_addrID; /* java.net.InetSocketAddress.addr */ -static jfieldID isa_portID; /* java.net.InetSocketAddress.port */ /* defined in SctpNet.c */ jobject SockAddrToInetSocketAddress(JNIEnv* env, struct sockaddr* addr); @@ -138,13 +136,6 @@ JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_initIDs CHECK_NULL(ss_class); ss_ctrID = (*env)->GetMethodID(env, cls, "", "(I)V"); CHECK_NULL(ss_ctrID); - - /* InetSocketAddress */ - cls = (*env)->FindClass(env, "java/net/InetSocketAddress"); - CHECK_NULL(cls); - isa_addrID = (*env)->GetFieldID(env, cls, "addr", "Ljava/net/InetAddress;"); - CHECK_NULL(isa_addrID); - isa_portID = (*env)->GetFieldID(env, cls, "port", "I"); } void getControlData @@ -509,12 +500,12 @@ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_receive0 /* * Class: sun_nio_ch_sctp_SctpChannelImpl * Method: send0 - * Signature: (IJILjava/net/SocketAddress;IIZI)I + * Signature: (IJILjava/net/InetAddress;IIIZI)I */ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0 (JNIEnv *env, jclass klass, jint fd, jlong address, jint length, - jobject saTarget, jint assocId, jint streamNumber, jboolean unordered, - jint ppid) { + jobject targetAddress, jint targetPort, jint assocId, jint streamNumber, + jboolean unordered, jint ppid) { SOCKADDR sa; int sa_len = sizeof(sa); ssize_t rv = 0; @@ -526,17 +517,13 @@ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0 struct controlData cdata[1]; /* SctpChannel: - * saTarget may contain the preferred address or NULL to use primary, + * targetAddress may contain the preferred address or NULL to use primary, * assocId will always be -1 * SctpMultiChannell: - * Setup new association, saTarget will contain address, assocId = -1 - * Association already existing, assocId != -1, saTarget = preferred addr + * Setup new association, targetAddress will contain address, assocId = -1 + * Association already existing, assocId != -1, targetAddress = preferred addr */ - if (saTarget != NULL /*&& assocId <= 0*/) { - - jobject targetAddress = (*env)->GetObjectField(env, saTarget, isa_addrID); - jint targetPort = (*env)->GetIntField(env, saTarget, isa_portID); - + if (targetAddress != NULL /*&& assocId <= 0*/) { if (NET_InetAddressToSockaddr(env, targetAddress, targetPort, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) { diff --git a/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c b/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c index 555ca9fbbfb..d98032e4e0b 100644 --- a/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c +++ b/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c @@ -34,8 +34,6 @@ #include "net_util.h" #include -static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */ -static jfieldID isa_portID; /* port in java.net.InetSocketAddress */ static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */ @@ -50,9 +48,6 @@ Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz) isa_class = (*env)->NewGlobalRef(env, clazz); isa_ctorID = (*env)->GetMethodID(env, clazz, "", "(Ljava/net/InetAddress;I)V"); - isa_addrID = (*env)->GetFieldID(env, clazz, "addr", - "Ljava/net/InetAddress;"); - isa_portID = (*env)->GetFieldID(env, clazz, "port", "I"); clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl"); dci_senderID = (*env)->GetFieldID(env, clazz, "sender", @@ -214,15 +209,14 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this, JNIEXPORT jint JNICALL Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this, jboolean preferIPv6, jobject fdo, - jlong address, jint len, jobject dest) + jlong address, jint len, + jobject destAddress, jint destPort) { jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); SOCKETADDRESS sa; int sa_len; jint rv = 0; - jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID); - jint destPort = (*env)->GetIntField(env, dest, isa_portID); if (NET_InetAddressToSockaddr(env, destAddress, destPort, (struct sockaddr *)&sa, diff --git a/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java b/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java index c916b2ef8af..7b9ec6a9a36 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java +++ b/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java @@ -42,7 +42,7 @@ public class SendToUnresolved { try { dc.send(bb, sa); throw new RuntimeException("Expected exception not thrown"); - } catch (IOException e) { + } catch (IOException | UnresolvedAddressException e) { // Correct result } dc.close(); From 39edc8d2b5b7cc550453e5027181b9779ed61bf8 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Thu, 8 Nov 2012 15:41:01 -0800 Subject: [PATCH 019/102] 7201070: Serialization to conform to protocol Reviewed-by: dmocek, ahgross, skoivu --- jdk/src/share/classes/java/io/ObjectInputStream.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jdk/src/share/classes/java/io/ObjectInputStream.java b/jdk/src/share/classes/java/io/ObjectInputStream.java index 1963187eaaa..1125bb04616 100644 --- a/jdk/src/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/share/classes/java/io/ObjectInputStream.java @@ -1752,6 +1752,12 @@ public class ObjectInputStream ObjectStreamClass desc = readClassDesc(false); desc.checkDeserialize(); + Class cl = desc.forClass(); + if (cl == String.class || cl == Class.class + || cl == ObjectStreamClass.class) { + throw new InvalidClassException("invalid class descriptor"); + } + Object obj; try { obj = desc.isInstantiable() ? desc.newInstance() : null; From 695e6ab2e077b530118831cbcb4511596a73a9f9 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Fri, 9 Nov 2012 14:36:10 -0800 Subject: [PATCH 020/102] 8002091: tools/launcher/ToolsOpts.java test started to fail since 7u11 b01 on Windows Reviewed-by: darcy, jjh, mschoene --- jdk/src/share/bin/jli_util.h | 2 +- jdk/src/windows/bin/java_md.c | 39 +++++++++++++++++--------- jdk/test/tools/launcher/ToolsOpts.java | 1 + 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/jdk/src/share/bin/jli_util.h b/jdk/src/share/bin/jli_util.h index dd53e936210..388910407ff 100644 --- a/jdk/src/share/bin/jli_util.h +++ b/jdk/src/share/bin/jli_util.h @@ -66,7 +66,7 @@ int JLI_GetStdArgc(); #include #define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2)) #define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3)) -size_t JLI_Snprintf(char *buffer, size_t size, const char *format, ...); +int JLI_Snprintf(char *buffer, size_t size, const char *format, ...); void JLI_CmdToArgs(char *cmdline); #define JLI_Lseek _lseeki64 #else /* NIXES */ diff --git a/jdk/src/windows/bin/java_md.c b/jdk/src/windows/bin/java_md.c index df118717279..4078ecc754b 100644 --- a/jdk/src/windows/bin/java_md.c +++ b/jdk/src/windows/bin/java_md.c @@ -526,27 +526,35 @@ jlong Counter2Micros(jlong counts) } return (counts * 1000 * 1000)/counterFrequency.QuadPart; } - /* * windows snprintf does not guarantee a null terminator in the buffer, * if the computed size is equal to or greater than the buffer size, - * as well as error conditions, this function guarantees a null terminator - * under all these conditions. An unreasonable buffer size will return - * an error value. + * as well as error conditions. This function guarantees a null terminator + * under all these conditions. An unreasonable buffer or size will return + * an error value. Under all other conditions this function will return the + * size of the bytes actually written minus the null terminator, similar + * to ansi snprintf api. Thus when calling this function the caller must + * ensure storage for the null terminator. */ -size_t -JLI_Snprintf(char* buffer, size_t size, const char* format, ...) -{ - size_t rc; +int +JLI_Snprintf(char* buffer, size_t size, const char* format, ...) { + int rc; va_list vl; - if (size <= 0) + if (size == 0 || buffer == NULL) return -1; + buffer[0] = '\0'; va_start(vl, format); - rc = vsnprintf(buffer, size - 1, format, vl); - /* force a null terminator, if something is amiss */ - if (rc < 0 || rc >= size) - buffer[size - 1] = '\0'; + rc = vsnprintf(buffer, size, format, vl); va_end(vl); + /* force a null terminator, if something is amiss */ + if (rc < 0) { + /* apply ansi semantics */ + buffer[size - 1] = '\0'; + return size; + } else if (rc == size) { + /* force a null terminator */ + buffer[size - 1] = '\0'; + } return rc; } @@ -1441,7 +1449,10 @@ CreateApplicationArgs(JNIEnv *env, char **strv, int argc) // we add the indicator tlen = 1 + JLI_StrLen(strv[i]) + 1; nargv[i] = (char *) JLI_MemAlloc(tlen); - JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', strv[i]); + if (JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', + strv[i]) < 0) { + return NULL; + } JLI_TraceLauncher("%s\n", nargv[i]); } diff --git a/jdk/test/tools/launcher/ToolsOpts.java b/jdk/test/tools/launcher/ToolsOpts.java index 4535990dbca..f01931d5482 100644 --- a/jdk/test/tools/launcher/ToolsOpts.java +++ b/jdk/test/tools/launcher/ToolsOpts.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8002091 * @summary Test options patterns for javac,javah,javap and javadoc using * javac as a test launcher. Create a dummy javac and intercept options to check * reception of options as passed through the launcher without having to launch From 1d3d850ee0b3a31197dfff7ee3e124dfc33c5b09 Mon Sep 17 00:00:00 2001 From: Oleg Pekhovskiy Date: Thu, 15 Nov 2012 23:03:31 +0400 Subject: [PATCH 021/102] 7192977: Issue in toolkit thread Reviewed-by: skoivu, rupashka, art --- .../share/classes/java/awt/EventQueue.java | 19 +- jdk/src/share/classes/java/awt/Window.java | 2 +- .../classes/javax/swing/RepaintManager.java | 167 ++++++++++-------- .../share/classes/sun/applet/AppletPanel.java | 60 +++---- .../share/classes/sun/awt/AWTAccessor.java | 8 + .../sun/awt/windows/WComponentPeer.java | 9 +- .../sun/awt/windows/WEmbeddedFrame.java | 13 +- 7 files changed, 164 insertions(+), 114 deletions(-) diff --git a/jdk/src/share/classes/java/awt/EventQueue.java b/jdk/src/share/classes/java/awt/EventQueue.java index 5ba9756a1af..57a2ccfa3b9 100644 --- a/jdk/src/share/classes/java/awt/EventQueue.java +++ b/jdk/src/share/classes/java/awt/EventQueue.java @@ -194,7 +194,8 @@ public class EventQueue { } public void removeSourceEvents(EventQueue eventQueue, Object source, - boolean removeAllEvents) { + boolean removeAllEvents) + { eventQueue.removeSourceEvents(source, removeAllEvents); } public boolean noEvents(EventQueue eventQueue) { @@ -203,6 +204,11 @@ public class EventQueue { public void wakeup(EventQueue eventQueue, boolean isShutdown) { eventQueue.wakeup(isShutdown); } + public void invokeAndWait(Object source, Runnable r) + throws InterruptedException, InvocationTargetException + { + EventQueue.invokeAndWait(source, r); + } }); } @@ -1245,8 +1251,14 @@ public class EventQueue { * @since 1.2 */ public static void invokeAndWait(Runnable runnable) - throws InterruptedException, InvocationTargetException { + throws InterruptedException, InvocationTargetException + { + invokeAndWait(Toolkit.getDefaultToolkit(), runnable); + } + static void invokeAndWait(Object source, Runnable runnable) + throws InterruptedException, InvocationTargetException + { if (EventQueue.isDispatchThread()) { throw new Error("Cannot call invokeAndWait from the event dispatcher thread"); } @@ -1255,8 +1267,7 @@ public class EventQueue { Object lock = new AWTInvocationLock(); InvocationEvent event = - new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock, - true); + new InvocationEvent(source, runnable, lock, true); synchronized (lock) { Toolkit.getEventQueue().postEvent(event); diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index 984e287bd50..4b966273e0f 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -1206,7 +1206,7 @@ public class Window extends Container implements Accessible { } else { try { - EventQueue.invokeAndWait(action); + EventQueue.invokeAndWait(this, action); } catch (InterruptedException e) { System.err.println("Disposal was interrupted:"); diff --git a/jdk/src/share/classes/javax/swing/RepaintManager.java b/jdk/src/share/classes/javax/swing/RepaintManager.java index aa3f8bdf50c..8f2e6093393 100644 --- a/jdk/src/share/classes/javax/swing/RepaintManager.java +++ b/jdk/src/share/classes/javax/swing/RepaintManager.java @@ -27,11 +27,12 @@ package javax.swing; import java.awt.*; import java.awt.event.*; -import java.awt.peer.ComponentPeer; -import java.awt.peer.ContainerPeer; import java.awt.image.VolatileImage; +import java.security.AccessControlContext; import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.applet.*; import sun.awt.AWTAccessor; @@ -39,6 +40,8 @@ import sun.awt.AppContext; import sun.awt.DisplayChangedListener; import sun.awt.SunToolkit; import sun.java2d.SunGraphicsEnvironment; +import sun.misc.JavaSecurityAccess; +import sun.misc.SharedSecrets; import sun.security.action.GetPropertyAction; import com.sun.java.swing.SwingUtilities3; @@ -176,6 +179,9 @@ public class RepaintManager */ private final ProcessingRunnable processingRunnable; + private final static JavaSecurityAccess javaSecurityAccess = + SharedSecrets.getJavaSecurityAccess(); + static { volatileImageBufferEnabled = "true".equals(AccessController. @@ -548,13 +554,26 @@ public class RepaintManager // This is called from the toolkit thread when awt needs to run a // Runnable before we paint. // - void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c, - Runnable r) { + void nativeQueueSurfaceDataRunnable(AppContext appContext, + final Component c, final Runnable r) + { synchronized(this) { if (runnableList == null) { runnableList = new LinkedList(); } - runnableList.add(r); + runnableList.add(new Runnable() { + public void run() { + AccessControlContext stack = AccessController.getContext(); + AccessControlContext acc = + AWTAccessor.getComponentAccessor().getAccessControlContext(c); + javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { + public Void run() { + r.run(); + return null; + } + }, stack, acc); + } + }); } scheduleProcessingRunnable(appContext); } @@ -652,9 +671,9 @@ public class RepaintManager * @see #addInvalidComponent */ public void validateInvalidComponents() { - java.util.List ic; + final java.util.List ic; synchronized(this) { - if(invalidComponents == null) { + if (invalidComponents == null) { return; } ic = invalidComponents; @@ -662,7 +681,17 @@ public class RepaintManager } int n = ic.size(); for(int i = 0; i < n; i++) { - ic.get(i).validate(); + final Component c = ic.get(i); + AccessControlContext stack = AccessController.getContext(); + AccessControlContext acc = + AWTAccessor.getComponentAccessor().getAccessControlContext(c); + javaSecurityAccess.doIntersectionPrivilege( + new PrivilegedAction() { + public Void run() { + c.validate(); + return null; + } + }, stack, acc); } } @@ -740,78 +769,78 @@ public class RepaintManager paintDirtyRegions(tmpDirtyComponents); } - private void paintDirtyRegions(Map - tmpDirtyComponents){ - int i, count; - java.util.List roots; - Component dirtyComponent; - - count = tmpDirtyComponents.size(); - if (count == 0) { + private void paintDirtyRegions( + final Map tmpDirtyComponents) + { + if (tmpDirtyComponents.isEmpty()) { return; } - Rectangle rect; - int localBoundsX = 0; - int localBoundsY = 0; - int localBoundsH; - int localBoundsW; - - roots = new ArrayList(count); - + final java.util.List roots = + new ArrayList(tmpDirtyComponents.size()); for (Component dirty : tmpDirtyComponents.keySet()) { collectDirtyComponents(tmpDirtyComponents, dirty, roots); } - count = roots.size(); + final AtomicInteger count = new AtomicInteger(roots.size()); painting = true; try { - for(i=0 ; i < count ; i++) { - dirtyComponent = roots.get(i); - rect = tmpDirtyComponents.get(dirtyComponent); - // Sometimes when RepaintManager is changed during the painting - // we may get null here, see #6995769 for details - if (rect == null) { - continue; - } - localBoundsH = dirtyComponent.getHeight(); - localBoundsW = dirtyComponent.getWidth(); - - SwingUtilities.computeIntersection(localBoundsX, - localBoundsY, - localBoundsW, - localBoundsH, - rect); - if (dirtyComponent instanceof JComponent) { - ((JComponent)dirtyComponent).paintImmediately( - rect.x,rect.y,rect.width, rect.height); - } - else if (dirtyComponent.isShowing()) { - Graphics g = JComponent.safelyGetGraphics( - dirtyComponent, dirtyComponent); - // If the Graphics goes away, it means someone disposed of - // the window, don't do anything. - if (g != null) { - g.setClip(rect.x, rect.y, rect.width, rect.height); - try { - dirtyComponent.paint(g); - } finally { - g.dispose(); + for (int j=0 ; j < count.get(); j++) { + final int i = j; + final Component dirtyComponent = roots.get(j); + AccessControlContext stack = AccessController.getContext(); + AccessControlContext acc = + AWTAccessor.getComponentAccessor().getAccessControlContext(dirtyComponent); + javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { + public Void run() { + Rectangle rect = tmpDirtyComponents.get(dirtyComponent); + // Sometimes when RepaintManager is changed during the painting + // we may get null here, see #6995769 for details + if (rect == null) { + return null; } + + int localBoundsH = dirtyComponent.getHeight(); + int localBoundsW = dirtyComponent.getWidth(); + SwingUtilities.computeIntersection(0, + 0, + localBoundsW, + localBoundsH, + rect); + if (dirtyComponent instanceof JComponent) { + ((JComponent)dirtyComponent).paintImmediately( + rect.x,rect.y,rect.width, rect.height); + } + else if (dirtyComponent.isShowing()) { + Graphics g = JComponent.safelyGetGraphics( + dirtyComponent, dirtyComponent); + // If the Graphics goes away, it means someone disposed of + // the window, don't do anything. + if (g != null) { + g.setClip(rect.x, rect.y, rect.width, rect.height); + try { + dirtyComponent.paint(g); + } finally { + g.dispose(); + } + } + } + // If the repaintRoot has been set, service it now and + // remove any components that are children of repaintRoot. + if (repaintRoot != null) { + adjustRoots(repaintRoot, roots, i + 1); + count.set(roots.size()); + paintManager.isRepaintingRoot = true; + repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(), + repaintRoot.getHeight()); + paintManager.isRepaintingRoot = false; + // Only service repaintRoot once. + repaintRoot = null; + } + + return null; } - } - // If the repaintRoot has been set, service it now and - // remove any components that are children of repaintRoot. - if (repaintRoot != null) { - adjustRoots(repaintRoot, roots, i + 1); - count = roots.size(); - paintManager.isRepaintingRoot = true; - repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(), - repaintRoot.getHeight()); - paintManager.isRepaintingRoot = false; - // Only service repaintRoot once. - repaintRoot = null; - } + }, stack, acc); } } finally { painting = false; diff --git a/jdk/src/share/classes/sun/applet/AppletPanel.java b/jdk/src/share/classes/sun/applet/AppletPanel.java index e090beec417..5ca566214db 100644 --- a/jdk/src/share/classes/sun/applet/AppletPanel.java +++ b/jdk/src/share/classes/sun/applet/AppletPanel.java @@ -45,6 +45,7 @@ import java.util.*; import java.util.Collections; import java.util.Locale; import java.util.WeakHashMap; +import sun.awt.AWTAccessor; import sun.awt.AppContext; import sun.awt.EmbeddedFrame; import sun.awt.SunToolkit; @@ -448,12 +449,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { // to avoid deadlock. try { final AppletPanel p = this; - - EventQueue.invokeAndWait(new Runnable() { - public void run() { - p.validate(); - } - }); + Runnable r = new Runnable() { + public void run() { + p.validate(); + } + }; + AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); } catch(InterruptedException ie) { } @@ -478,18 +479,19 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { try { final AppletPanel p = this; final Applet a = applet; + Runnable r = new Runnable() { + public void run() { + p.validate(); + a.setVisible(true); - EventQueue.invokeAndWait(new Runnable() { - public void run() { - p.validate(); - a.setVisible(true); - - // Fix for BugTraq ID 4041703. - // Set the default focus for an applet. - if (hasInitialFocus()) - setDefaultFocus(); + // Fix for BugTraq ID 4041703. + // Set the default focus for an applet. + if (hasInitialFocus()) { + setDefaultFocus(); } - }); + } + }; + AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); } catch(InterruptedException ie) { } @@ -512,13 +514,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { // to avoid deadlock. try { final Applet a = applet; - - EventQueue.invokeAndWait(new Runnable() { - public void run() - { - a.setVisible(false); - } - }); + Runnable r = new Runnable() { + public void run() { + a.setVisible(false); + } + }; + AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); } catch(InterruptedException ie) { } @@ -570,17 +571,14 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { } status = APPLET_DISPOSE; - try - { + try { final Applet a = applet; - - EventQueue.invokeAndWait(new Runnable() - { - public void run() - { + Runnable r = new Runnable() { + public void run() { remove(a); } - }); + }; + AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); } catch(InterruptedException ie) { diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java index 21f426da2f5..633fdcb4c18 100644 --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -34,6 +34,8 @@ import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.geom.Point2D; import java.awt.peer.ComponentPeer; + +import java.lang.reflect.InvocationTargetException; import java.security.AccessControlContext; import java.io.File; @@ -476,6 +478,12 @@ public final class AWTAccessor { * appeared. */ void wakeup(EventQueue eventQueue, boolean isShutdown); + + /** + * Static in EventQueue + */ + void invokeAndWait(Object source, Runnable r) + throws InterruptedException, InvocationTargetException; } /* diff --git a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java index 6f788c2ac5d..37a257f1130 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java @@ -488,14 +488,15 @@ public abstract class WComponentPeer extends WObjectPeer try { replaceSurfaceData(); } catch (InvalidPipeException e) { - // REMIND : what do we do if our surface creation failed? + // REMIND : what do we do if our surface creation failed? } } } }; + Component c = (Component)target; // Fix 6255371. - if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing((Component)target, r)) { - postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), r)); + if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) { + postEvent(new InvocationEvent(c, r)); } } @@ -618,7 +619,7 @@ public abstract class WComponentPeer extends WObjectPeer } public void disposeLater() { - postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), new Runnable() { + postEvent(new InvocationEvent(target, new Runnable() { public void run() { dispose(); } diff --git a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java index b0f9cd3279d..3bc2c3b6b63 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java +++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java @@ -27,6 +27,7 @@ package sun.awt.windows; import sun.awt.*; import java.awt.*; +import java.awt.event.InvocationEvent; import java.awt.peer.ComponentPeer; import java.awt.image.*; import sun.awt.image.ByteInterleavedRaster; @@ -232,11 +233,13 @@ public class WEmbeddedFrame extends EmbeddedFrame { } else { // To avoid focus concurrence b/w IE and EmbeddedFrame // activation is postponed by means of posting it to EDT. - EventQueue.invokeLater(new Runnable() { - public void run() { - ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true); - } - }); + Runnable r = new Runnable() { + public void run() { + ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true); + } + }; + WToolkit.postEvent(WToolkit.targetToAppContext(this), + new InvocationEvent(this, r)); } } From 7749e896e76a27c5872c068bf24f4bd84b294abb Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Fri, 16 Nov 2012 11:05:43 +0400 Subject: [PATCH 022/102] 8001972: Improve image processing Reviewed-by: prr, ahgross --- .../sun/awt/image/ByteComponentRaster.java | 70 ++++++++++----- .../sun/awt/image/ByteInterleavedRaster.java | 29 +----- .../sun/awt/image/ShortComponentRaster.java | 69 +++++++++----- .../sun/awt/image/ShortInterleavedRaster.java | 29 +----- .../native/sun/awt/image/awt_parseImage.c | 90 +++++++++++++++++-- .../native/sun/awt/medialib/safe_alloc.h | 5 ++ 6 files changed, 191 insertions(+), 101 deletions(-) diff --git a/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java b/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java index c92f7665904..49c642e37db 100644 --- a/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java +++ b/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java @@ -198,7 +198,7 @@ public class ByteComponentRaster extends SunWritableRaster { } this.bandOffset = this.dataOffsets[0]; - verify(false); + verify(); } /** @@ -857,38 +857,68 @@ public class ByteComponentRaster extends SunWritableRaster { } /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. + * Verify that the layout parameters are consistent with the data. + * + * The method verifies whether scanline stride and pixel stride do not + * cause an integer overflow during calculation of a position of the pixel + * in data buffer. It also verifies whether the data buffer has enough data + * to correspond the raster layout attributes. + * + * @throws RasterFormatException if an integer overflow is detected, + * or if data buffer has not enough capacity. */ - private void verify (boolean strictCheck) { - // Make sure data for Raster is in a legal range - for (int i=0; i < dataOffsets.length; i++) { + protected final void verify() { + for (int i = 0; i < dataOffsets.length; i++) { if (dataOffsets[i] < 0) { - throw new RasterFormatException("Data offsets for band "+i+ - "("+dataOffsets[i]+ - ") must be >= 0"); + throw new RasterFormatException("Data offsets for band " + i + + "(" + dataOffsets[i] + + ") must be >= 0"); } } int maxSize = 0; int size; - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; + // we can be sure that width and height are greater than 0 + if (scanlineStride < 0 || + scanlineStride > (Integer.MAX_VALUE / height)) + { + // integer overflow + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } + int lastScanOffset = (height - 1) * scanlineStride; + + if (pixelStride < 0 || + pixelStride > (Integer.MAX_VALUE / width)) + { + // integer overflow + throw new RasterFormatException("Incorrect pixel stride: " + + pixelStride); + } + int lastPixelOffset = (width - 1) * pixelStride; + + if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) { + // integer overflow + throw new RasterFormatException("Incorrect raster attributes"); + } + lastPixelOffset += lastScanOffset; + + for (int i = 0; i < numDataElements; i++) { + size = lastPixelOffset + dataOffsets[i]; + if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) { + throw new RasterFormatException("Incorrect band offset: " + + dataOffsets[i]); + + } + if (size > maxSize) { maxSize = size; } } if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); + throw new RasterFormatException("Data array too small (should be " + + maxSize + " )"); } } diff --git a/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java b/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java index b721d686867..4279ce1f90a 100644 --- a/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java +++ b/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java @@ -250,7 +250,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { } } - verify(false); + verify(); } /** @@ -1292,33 +1292,6 @@ public class ByteInterleavedRaster extends ByteComponentRaster { return createCompatibleWritableRaster(width,height); } - /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. - */ - private void verify (boolean strictCheck) { - int maxSize = 0; - int size; - - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; - if (size > maxSize) { - maxSize = size; - } - } - if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); - } - } - public String toString() { return new String ("ByteInterleavedRaster: width = "+width+" height = " + height diff --git a/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java b/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java index bc39bd2f0c8..df2c0f7d663 100644 --- a/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java +++ b/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java @@ -198,7 +198,7 @@ public class ShortComponentRaster extends SunWritableRaster { } this.bandOffset = this.dataOffsets[0]; - verify(false); + verify(); } /** @@ -791,38 +791,67 @@ public class ShortComponentRaster extends SunWritableRaster { } /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. + * Verify that the layout parameters are consistent with the data. + * + * The method verifies whether scanline stride and pixel stride do not + * cause an integer overflow during calculation of a position of the pixel + * in data buffer. It also verifies whether the data buffer has enough data + * to correspond the raster layout attributes. + * + * @throws RasterFormatException if an integer overflow is detected, + * or if data buffer has not enough capacity. */ - private void verify (boolean strictCheck) { - // Make sure data for Raster is in a legal range - for (int i=0; i < dataOffsets.length; i++) { + protected final void verify() { + for (int i = 0; i < dataOffsets.length; i++) { if (dataOffsets[i] < 0) { - throw new RasterFormatException("Data offsets for band "+i+ - "("+dataOffsets[i]+ - ") must be >= 0"); + throw new RasterFormatException("Data offsets for band " + i + + "(" + dataOffsets[i] + + ") must be >= 0"); } } int maxSize = 0; int size; - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; + // we can be sure that width and height are greater than 0 + if (scanlineStride < 0 || + scanlineStride > (Integer.MAX_VALUE / height)) + { + // integer overflow + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } + int lastScanOffset = (height - 1) * scanlineStride; + + if (pixelStride < 0 || + pixelStride > (Integer.MAX_VALUE / width)) + { + // integer overflow + throw new RasterFormatException("Incorrect pixel stride: " + + pixelStride); + } + int lastPixelOffset = (width - 1) * pixelStride; + + if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) { + // integer overflow + throw new RasterFormatException("Incorrect raster attributes"); + } + lastPixelOffset += lastScanOffset; + + for (int i = 0; i < numDataElements; i++) { + size = lastPixelOffset + dataOffsets[i]; + if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) { + throw new RasterFormatException("Incorrect band offset: " + + dataOffsets[i]); + } + if (size > maxSize) { maxSize = size; } } if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); + throw new RasterFormatException("Data array too small (should be " + + maxSize + " )"); } } diff --git a/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java b/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java index ef624f978c2..c55d111d7fd 100644 --- a/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java +++ b/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java @@ -171,7 +171,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { sampleModel); } this.bandOffset = this.dataOffsets[0]; - verify(false); + verify(); } /** @@ -762,33 +762,6 @@ public class ShortInterleavedRaster extends ShortComponentRaster { return createCompatibleWritableRaster(width,height); } - /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. - */ - private void verify (boolean strictCheck) { - int maxSize = 0; - int size; - - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; - if (size > maxSize) { - maxSize = size; - } - } - if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); - } - } - public String toString() { return new String ("ShortInterleavedRaster: width = "+width +" height = " + height diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.c b/jdk/src/share/native/sun/awt/image/awt_parseImage.c index 264a02f1642..cdd22189d78 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c @@ -114,6 +114,62 @@ int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP, return status; } +/* Verifies whether the channel offsets are sane and correspond to the type of + * the raster. + * + * Return value: + * 0: Failure: channel offsets are invalid + * 1: Success + */ +static int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) { + int i, lastPixelOffset, lastScanOffset; + switch (rasterP->rasterType) { + case COMPONENT_RASTER_TYPE: + if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) { + return 0; + } + if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) { + return 0; + } + + lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride; + lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride; + + + if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) { + return 0; + } + + lastPixelOffset += lastScanOffset; + + for (i = 0; i < rasterP->numDataElements; i++) { + int off = rasterP->chanOffsets[i]; + int size = lastPixelOffset + off; + + if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) { + return 0; + } + + if (size < lastPixelOffset || size >= dataArrayLength) { + // an overflow, or insufficient buffer capacity + return 0; + } + } + return 1; + case BANDED_RASTER_TYPE: + // NB:caller does not support the banded rasters yet, + // so this branch of the code must be re-defined in + // order to provide valid criteria for the data offsets + // verification, when/if banded rasters will be supported. + // At the moment, we prohibit banded rasters as well. + return 0; + default: + // PACKED_RASTER_TYPE: does not support channel offsets + // UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error + return 0; + } +} + /* Parse the raster. All of the raster information is returned in the * rasterP structure. * @@ -125,7 +181,6 @@ int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP, int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { jobject joffs = NULL; /* int status;*/ - int isDiscrete = TRUE; if (JNU_IsNull(env, jraster)) { JNU_ThrowNullPointerException(env, "null Raster object"); @@ -155,6 +210,9 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { return -1; } + // make sure that the raster type is initialized + rasterP->rasterType = UNKNOWN_RASTER_TYPE; + if (rasterP->numBands <= 0 || rasterP->numBands > MAX_NUMBANDS) { @@ -254,7 +312,6 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { } rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID); rasterP->dataType = BYTE_DATA_TYPE; - isDiscrete = FALSE; } else { rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM; @@ -265,7 +322,19 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { return 0; } - if (isDiscrete) { + // do basic validation of the raster structure + if (rasterP->width <= 0 || rasterP->height <= 0 || + rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0) + { + // invalid raster + return -1; + } + + // channel (data) offsets + switch (rasterP->rasterType) { + case COMPONENT_RASTER_TYPE: + case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment + // get channel (data) offsets rasterP->chanOffsets = NULL; if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) { rasterP->chanOffsets = @@ -278,10 +347,21 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { } (*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements, rasterP->chanOffsets); + if (rasterP->jdata == NULL) { + // unable to verify the raster + return -1; + } + // verify whether channel offsets look sane + if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) { + return -1; + } + break; + default: + ; // PACKED_RASTER_TYPE does not use the channel offsets. } - /* additioanl check for sppsm fields validity: make sure that - * size of raster samples doesn't exceed the data type cpacity. + /* additional check for sppsm fields validity: make sure that + * size of raster samples doesn't exceed the data type capacity. */ if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */ rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */ diff --git a/jdk/src/share/native/sun/awt/medialib/safe_alloc.h b/jdk/src/share/native/sun/awt/medialib/safe_alloc.h index ce744af2c3b..579d98638dc 100644 --- a/jdk/src/share/native/sun/awt/medialib/safe_alloc.h +++ b/jdk/src/share/native/sun/awt/medialib/safe_alloc.h @@ -41,5 +41,10 @@ (((w) > 0) && ((h) > 0) && ((sz) > 0) && \ (((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz)))) +#define SAFE_TO_MULT(a, b) \ + (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b))) + +#define SAFE_TO_ADD(a, b) \ + (((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b))) #endif // __SAFE_ALLOC_H__ From 52caa8646b6b5ea2ae4a3b6883c8072f257db2ef Mon Sep 17 00:00:00 2001 From: Darryl Mocek Date: Mon, 19 Nov 2012 13:54:12 -0800 Subject: [PATCH 023/102] 6563318: RMI data sanitization Reviewed-by: ahgross, hawtin, mchung, smarks --- .../sun/rmi/transport/proxy/CGIHandler.java | 6 +-- jdk/test/java/rmi/testlibrary/JavaVM.java | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java index 918986deec9..460c9f17203 100644 --- a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java +++ b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2008, 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 @@ -153,7 +153,7 @@ public final class CGIHandler { returnServerError(e.getMessage()); } else - returnClientError("invalid command: " + command); + returnClientError("invalid command."); } catch (Exception e) { returnServerError("internal error: " + e.getMessage()); } @@ -225,7 +225,7 @@ final class CGIForwardCommand implements CGICommandHandler { try { port = Integer.parseInt(param); } catch (NumberFormatException e) { - throw new CGIClientException("invalid port number: " + param); + throw new CGIClientException("invalid port number."); } if (port <= 0 || port > 0xFFFF) throw new CGIClientException("invalid port: " + port); diff --git a/jdk/test/java/rmi/testlibrary/JavaVM.java b/jdk/test/java/rmi/testlibrary/JavaVM.java index 62be87d8279..d7b94bfe4b1 100644 --- a/jdk/test/java/rmi/testlibrary/JavaVM.java +++ b/jdk/test/java/rmi/testlibrary/JavaVM.java @@ -133,6 +133,14 @@ public class JavaVM { return TestLibrary.getExtraProperty("jcov.options",""); } + public void start(Runnable runnable) throws IOException { + if (runnable == null) { + throw new NullPointerException("Runnable cannot be null."); + } + + start(); + new JavaVMCallbackHandler(runnable).start(); + } /** * Exec the VM as specified in this object's constructor. @@ -235,4 +243,35 @@ public class JavaVM { protected Process getVM() { return vm; } + + /** + * Handles calling the callback. + */ + private class JavaVMCallbackHandler extends Thread { + Runnable runnable; + + JavaVMCallbackHandler(Runnable runnable) { + this.runnable = runnable; + } + + + /** + * Wait for the Process to terminate and notify the callback. + */ + @Override + public void run() { + if (vm != null) { + try { + vm.waitFor(); + } catch(InterruptedException ie) { + // Restore the interrupted status + Thread.currentThread().interrupt(); + } + } + + if (runnable != null) { + runnable.run(); + } + } + } } From 103aa32912bf857ca25737649db2800c4dbb8365 Mon Sep 17 00:00:00 2001 From: Darryl Mocek Date: Mon, 19 Nov 2012 15:38:56 -0800 Subject: [PATCH 024/102] 8001242: Improve RMI HTTP conformance Reviewed-by: ahgross, mchung, smarks --- .../sun/rmi/transport/proxy/CGIHandler.java | 13 ++++++++----- .../sun/rmi/transport/proxy/HttpInputStream.java | 15 +++++++++------ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java index 460c9f17203..a60b23864af 100644 --- a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java +++ b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java @@ -293,11 +293,14 @@ final class CGIForwardCommand implements CGICommandHandler { "unexpected EOF reading server response"); if (line.toLowerCase().startsWith(key)) { - // if contentLengthFound is true - // we should probably do something here - responseContentLength = - Integer.parseInt(line.substring(key.length()).trim()); - contentLengthFound = true; + if (contentLengthFound) { + throw new CGIServerException( + "Multiple Content-length entries found."); + } else { + responseContentLength = + Integer.parseInt(line.substring(key.length()).trim()); + contentLengthFound = true; + } } } while ((line.length() != 0) && (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); diff --git a/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java b/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java index 773493e48df..3a35bb02b25 100644 --- a/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java +++ b/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2001, 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 @@ -70,11 +70,14 @@ class HttpInputStream extends FilterInputStream { throw new EOFException(); if (line.toLowerCase().startsWith(key)) { - // if contentLengthFound is true - // we should probably do something here - bytesLeft = - Integer.parseInt(line.substring(key.length()).trim()); - contentLengthFound = true; + if (contentLengthFound) { + throw new IOException( + "Multiple Content-length entries found."); + } else { + bytesLeft = + Integer.parseInt(line.substring(key.length()).trim()); + contentLengthFound = true; + } } // The idea here is to go past the first blank line. From b9b59635225b5db8216c3da0024545ad279f6f53 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Tue, 20 Nov 2012 11:46:42 +0400 Subject: [PATCH 025/102] 8002325: Improve management of images Reviewed-by: prr, ahgross --- .../native/sun/awt/image/awt_parseImage.c | 20 +++++++++++++++++++ .../native/sun/awt/image/awt_parseImage.h | 1 + 2 files changed, 21 insertions(+) diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.c b/jdk/src/share/native/sun/awt/image/awt_parseImage.c index cdd22189d78..4fe4efd2916 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c @@ -223,9 +223,14 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { return 0; } + rasterP->sppsm.isUsed = 0; + if ((*env)->IsInstanceOf(env, rasterP->jsampleModel, (*env)->FindClass(env,"java/awt/image/SinglePixelPackedSampleModel"))) { jobject jmask, joffs, jnbits; + + rasterP->sppsm.isUsed = 1; + rasterP->sppsm.maxBitSize = (*env)->GetIntField(env, rasterP->jsampleModel, g_SPPSMmaxBitID); @@ -711,6 +716,21 @@ setHints(JNIEnv *env, BufImageS_t *imageP) { } else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) { int i; + + /* do some sanity check first: make sure that + * - sample model is SinglePixelPackedSampleModel + * - number of bands in the raster corresponds to the number + * of color components in the color model + */ + if (!rasterP->sppsm.isUsed || + rasterP->numBands != cmodelP->numComponents) + { + /* given raster is not compatible with the color model, + * so the operation has to be aborted. + */ + return -1; + } + if (cmodelP->maxNbits > 8) { hintP->needToExpand = TRUE; hintP->expandToNbits = cmodelP->maxNbits; diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.h b/jdk/src/share/native/sun/awt/image/awt_parseImage.h index f58adabb754..b92bb0c2833 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.h +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.h @@ -95,6 +95,7 @@ typedef struct { jint offsets[MAX_NUMBANDS]; jint nBits[MAX_NUMBANDS]; jint maxBitSize; + jint isUsed; // flag to indicate whether the raster sample model is SPPSM } SPPSampleModelS_t; /* Struct that holds information for the Raster object */ From 6ddbe35ee2793eb0ebc52b013e46b65d25c804dc Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Mon, 26 Nov 2012 20:49:54 +0400 Subject: [PATCH 026/102] 7186952: Improve clipboard access Reviewed-by: serb, ahgross --- .../share/classes/java/awt/TextComponent.java | 25 ++++++------------- .../native/sun/windows/awt_TextComponent.cpp | 22 ++++++++-------- .../native/sun/windows/awt_TextComponent.h | 3 +-- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/jdk/src/share/classes/java/awt/TextComponent.java b/jdk/src/share/classes/java/awt/TextComponent.java index c99cae403a4..838c7c9dd3c 100644 --- a/jdk/src/share/classes/java/awt/TextComponent.java +++ b/jdk/src/share/classes/java/awt/TextComponent.java @@ -109,12 +109,6 @@ public class TextComponent extends Component implements Accessible { // the background color of non-editable TextComponents. boolean backgroundSetByClientCode = false; - /** - * True if this TextComponent has access - * to the System clipboard. - */ - transient private boolean canAccessClipboard; - transient protected TextListener textListener; /* @@ -139,7 +133,6 @@ public class TextComponent extends Component implements Accessible { GraphicsEnvironment.checkHeadless(); this.text = (text != null) ? text : ""; setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); - checkSystemClipboardAccess(); } private void enableInputMethodsIfNecessary() { @@ -734,17 +727,14 @@ public class TextComponent extends Component implements Accessible { /** * Assigns a valid value to the canAccessClipboard instance variable. */ - private void checkSystemClipboardAccess() { - canAccessClipboard = true; + private boolean canAccessClipboard() { SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkSystemClipboardAccess(); - } - catch (SecurityException e) { - canAccessClipboard = false; - } - } + if (sm == null) return true; + try { + sm.checkSystemClipboardAccess(); + return true; + } catch (SecurityException e) {} + return false; } /* @@ -827,7 +817,6 @@ public class TextComponent extends Component implements Accessible { } } enableInputMethodsIfNecessary(); - checkSystemClipboardAccess(); } diff --git a/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp b/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp index f16ba6c345c..eddcbca4088 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp +++ b/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp @@ -53,14 +53,12 @@ struct EnableEditingStruct { * AwtTextComponent fields */ -/* java.awt.TextComponent fields */ -jfieldID AwtTextComponent::canAccessClipboardID; - - /************************************************************************ * AwtTextComponent methods */ +jmethodID AwtTextComponent::canAccessClipboardMID; + AwtTextComponent::AwtTextComponent() { m_synthetic = FALSE; m_lStartPos = -1; @@ -367,8 +365,7 @@ AwtTextComponent::WmPaste() } jobject target = GetTarget(env); jboolean canAccessClipboard = - env->GetBooleanField(target, - AwtTextComponent::canAccessClipboardID); + env->CallBooleanMethod (target, AwtTextComponent::canAccessClipboardMID); env->DeleteLocalRef(target); return (canAccessClipboard) ? mrDoDefault : mrConsume; } @@ -854,12 +851,13 @@ Java_sun_awt_windows_WTextComponentPeer_initIDs(JNIEnv *env, jclass cls) { TRY; - cls = env->FindClass("java/awt/TextComponent"); - if (cls != NULL) { - AwtTextComponent::canAccessClipboardID = - env->GetFieldID(cls, "canAccessClipboard", "Z"); - DASSERT(AwtTextComponent::canAccessClipboardID != NULL); - } + jclass textComponentClassID = env->FindClass("java/awt/TextComponent"); + AwtTextComponent::canAccessClipboardMID = + env->GetMethodID(textComponentClassID, + "canAccessClipboard", "()Z"); + env->DeleteLocalRef(textComponentClassID); + + DASSERT(AwtTextComponent::canAccessClipboardMID != NULL); CATCH_BAD_ALLOC; } diff --git a/jdk/src/windows/native/sun/windows/awt_TextComponent.h b/jdk/src/windows/native/sun/windows/awt_TextComponent.h index e50219cd271..cc0fc97f780 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextComponent.h +++ b/jdk/src/windows/native/sun/windows/awt_TextComponent.h @@ -42,8 +42,7 @@ class AwtTextComponent : public AwtComponent { public: - /* java.awt.TextComponent canAccessClipboard field ID */ - static jfieldID canAccessClipboardID; + static jmethodID canAccessClipboardMID; AwtTextComponent(); From 7dde39f4f5a8075a71cd57eee4c5418aaed1aa24 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Mon, 26 Nov 2012 22:49:06 -0800 Subject: [PATCH 027/102] 6664509: Add logging context 6664528: Find log level matching its name or value given at construction time Reviewed-by: alanb, ahgross, jgish, hawtin --- .../classes/java/util/logging/Level.java | 255 +++++++-- .../classes/java/util/logging/LogManager.java | 531 +++++++++++------- .../classes/java/util/logging/Logger.java | 67 ++- .../classes/java/util/logging/Logging.java | 10 +- .../java/util/logging/LoggingProxyImpl.java | 11 +- .../java/util/logging/SimpleFormatter.java | 2 +- jdk/src/share/classes/sun/awt/AppContext.java | 39 +- .../share/classes/sun/misc/JavaAWTAccess.java | 8 + jdk/src/share/lib/security/java.security | 6 + 9 files changed, 678 insertions(+), 251 deletions(-) diff --git a/jdk/src/share/classes/java/util/logging/Level.java b/jdk/src/share/classes/java/util/logging/Level.java index 286ed5e6008..6847518ce02 100644 --- a/jdk/src/share/classes/java/util/logging/Level.java +++ b/jdk/src/share/classes/java/util/logging/Level.java @@ -24,6 +24,10 @@ */ package java.util.logging; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.ResourceBundle; /** @@ -59,7 +63,6 @@ import java.util.ResourceBundle; */ public class Level implements java.io.Serializable { - private static java.util.ArrayList known = new java.util.ArrayList<>(); private static String defaultBundle = "sun.util.logging.resources.logging"; /** @@ -77,6 +80,9 @@ public class Level implements java.io.Serializable { */ private final String resourceBundleName; + // localized level name + private String localizedLevelName; + /** * OFF is a special level that can be used to turn off logging. * This level is initialized to Integer.MAX_VALUE. @@ -202,9 +208,8 @@ public class Level implements java.io.Serializable { this.name = name; this.value = value; this.resourceBundleName = resourceBundleName; - synchronized (Level.class) { - known.add(this); - } + this.localizedLevelName = resourceBundleName == null ? name : null; + KnownLevel.add(this); } /** @@ -236,12 +241,76 @@ public class Level implements java.io.Serializable { * @return localized name */ public String getLocalizedName() { + return getLocalizedLevelName(); + } + + // package-private getLevelName() is used by the implementation + // instead of getName() to avoid calling the subclass's version + final String getLevelName() { + return this.name; + } + + final synchronized String getLocalizedLevelName() { + if (localizedLevelName != null) { + return localizedLevelName; + } + try { ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName); - return rb.getString(name); + localizedLevelName = rb.getString(name); } catch (Exception ex) { - return name; + localizedLevelName = name; } + return localizedLevelName; + } + + // Returns a mirrored Level object that matches the given name as + // specified in the Level.parse method. Returns null if not found. + // + // It returns the same Level object as the one returned by Level.parse + // method if the given name is a non-localized name or integer. + // + // If the name is a localized name, findLevel and parse method may + // return a different level value if there is a custom Level subclass + // that overrides Level.getLocalizedName() to return a different string + // than what's returned by the default implementation. + // + static Level findLevel(String name) { + if (name == null) { + throw new NullPointerException(); + } + + KnownLevel level; + + // Look for a known Level with the given non-localized name. + level = KnownLevel.findByName(name); + if (level != null) { + return level.mirroredLevel; + } + + // Now, check if the given name is an integer. If so, + // first look for a Level with the given value and then + // if necessary create one. + try { + int x = Integer.parseInt(name); + level = KnownLevel.findByValue(x); + if (level == null) { + // add new Level + Level levelObject = new Level(name, x); + level = KnownLevel.findByValue(x); + } + return level.mirroredLevel; + } catch (NumberFormatException ex) { + // Not an integer. + // Drop through. + } + + level = KnownLevel.findByLocalizedLevelName(name); + if (level != null) { + return level.mirroredLevel; + } + + return null; } /** @@ -268,21 +337,15 @@ public class Level implements java.io.Serializable { // Serialization magic to prevent "doppelgangers". // This is a performance optimization. private Object readResolve() { - synchronized (Level.class) { - for (int i = 0; i < known.size(); i++) { - Level other = known.get(i); - if (this.name.equals(other.name) && this.value == other.value - && (this.resourceBundleName == other.resourceBundleName || - (this.resourceBundleName != null && - this.resourceBundleName.equals(other.resourceBundleName)))) { - return other; - } - } - // Woops. Whoever sent us this object knows - // about a new log level. Add it to our list. - known.add(this); - return this; + KnownLevel o = KnownLevel.matches(this); + if (o != null) { + return o.levelObject; } + + // Woops. Whoever sent us this object knows + // about a new log level. Add it to our list. + Level level = new Level(this.name, this.value, this.resourceBundleName); + return level; } /** @@ -296,6 +359,7 @@ public class Level implements java.io.Serializable { *
  • "SEVERE" *
  • "1000" * + * * @param name string to be parsed * @throws NullPointerException if the name is null * @throws IllegalArgumentException if the value is not valid. @@ -315,12 +379,12 @@ public class Level implements java.io.Serializable { // Check that name is not null. name.length(); + KnownLevel level; + // Look for a known Level with the given non-localized name. - for (int i = 0; i < known.size(); i++) { - Level l = known.get(i); - if (name.equals(l.name)) { - return l; - } + level = KnownLevel.findByName(name); + if (level != null) { + return level.levelObject; } // Now, check if the given name is an integer. If so, @@ -328,14 +392,13 @@ public class Level implements java.io.Serializable { // if necessary create one. try { int x = Integer.parseInt(name); - for (int i = 0; i < known.size(); i++) { - Level l = known.get(i); - if (l.value == x) { - return l; - } + level = KnownLevel.findByValue(x); + if (level == null) { + // add new Level + Level levelObject = new Level(name, x); + level = KnownLevel.findByValue(x); } - // Create a new Level. - return new Level(name, x); + return level.levelObject; } catch (NumberFormatException ex) { // Not an integer. // Drop through. @@ -344,11 +407,9 @@ public class Level implements java.io.Serializable { // Finally, look for a known level with the given localized name, // in the current default locale. // This is relatively expensive, but not excessively so. - for (int i = 0; i < known.size(); i++) { - Level l = known.get(i); - if (name.equals(l.getLocalizedName())) { - return l; - } + level = KnownLevel.findByLocalizedName(name); + if (level != null) { + return level.levelObject; } // OK, we've tried everything and failed @@ -375,4 +436,124 @@ public class Level implements java.io.Serializable { public int hashCode() { return this.value; } + + // KnownLevel class maintains the global list of all known levels. + // The API allows multiple custom Level instances of the same name/value + // be created. This class provides convenient methods to find a level + // by a given name, by a given value, or by a given localized name. + // + // KnownLevel wraps the following Level objects: + // 1. levelObject: standard Level object or custom Level object + // 2. mirroredLevel: Level object representing the level specified in the + // logging configuration. + // + // Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods + // are non-final but the name and resource bundle name are parameters to + // the Level constructor. Use the mirroredLevel object instead of the + // levelObject to prevent the logging framework to execute foreign code + // implemented by untrusted Level subclass. + // + // Implementation Notes: + // If Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods + // were final, the following KnownLevel implementation can be removed. + // Future API change should take this into consideration. + static final class KnownLevel { + private static Map> nameToLevels = new HashMap<>(); + private static Map> intToLevels = new HashMap<>(); + final Level levelObject; // instance of Level class or Level subclass + final Level mirroredLevel; // instance of Level class + KnownLevel(Level l) { + this.levelObject = l; + if (l.getClass() == Level.class) { + this.mirroredLevel = l; + } else { + this.mirroredLevel = new Level(l.name, l.value, l.resourceBundleName); + } + } + + static synchronized void add(Level l) { + // the mirroredLevel object is always added to the list + // before the custom Level instance + KnownLevel o = new KnownLevel(l); + List list = nameToLevels.get(l.name); + if (list == null) { + list = new ArrayList<>(); + nameToLevels.put(l.name, list); + } + list.add(o); + + list = intToLevels.get(l.value); + if (list == null) { + list = new ArrayList<>(); + intToLevels.put(l.value, list); + } + list.add(o); + } + + // Returns a KnownLevel with the given non-localized name. + static synchronized KnownLevel findByName(String name) { + List list = nameToLevels.get(name); + if (list != null) { + return list.get(0); + } + return null; + } + + // Returns a KnownLevel with the given value. + static synchronized KnownLevel findByValue(int value) { + List list = intToLevels.get(value); + if (list != null) { + return list.get(0); + } + return null; + } + + // Returns a KnownLevel with the given localized name matching + // by calling the Level.getLocalizedLevelName() method (i.e. found + // from the resourceBundle associated with the Level object). + // This method does not call Level.getLocalizedName() that may + // be overridden in a subclass implementation + static synchronized KnownLevel findByLocalizedLevelName(String name) { + for (List levels : nameToLevels.values()) { + for (KnownLevel l : levels) { + String lname = l.levelObject.getLocalizedLevelName(); + if (name.equals(lname)) { + return l; + } + } + } + return null; + } + + // Returns a KnownLevel with the given localized name matching + // by calling the Level.getLocalizedName() method + static synchronized KnownLevel findByLocalizedName(String name) { + for (List levels : nameToLevels.values()) { + for (KnownLevel l : levels) { + String lname = l.levelObject.getLocalizedName(); + if (name.equals(lname)) { + return l; + } + } + } + return null; + } + + static synchronized KnownLevel matches(Level l) { + List list = nameToLevels.get(l.name); + if (list != null) { + for (KnownLevel level : list) { + Level other = level.mirroredLevel; + if (l.value == other.value && + (l.resourceBundleName == other.resourceBundleName || + (l.resourceBundleName != null && + l.resourceBundleName.equals(other.resourceBundleName)))) { + return level; + } + } + } + return null; + } + } + } diff --git a/jdk/src/share/classes/java/util/logging/LogManager.java b/jdk/src/share/classes/java/util/logging/LogManager.java index bfdf83f93da..78c90acee7d 100644 --- a/jdk/src/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/share/classes/java/util/logging/LogManager.java @@ -34,6 +34,8 @@ import java.lang.ref.WeakReference; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; import java.net.URL; +import sun.misc.JavaAWTAccess; +import sun.misc.SharedSecrets; import sun.security.action.GetPropertyAction; /** @@ -157,10 +159,9 @@ public class LogManager { // count to allow for cases where the same listener is registered many times. private final Map listenerMap = new HashMap<>(); - // Table of named Loggers that maps names to Loggers. - private Hashtable namedLoggers = new Hashtable<>(); - // Tree of named Loggers - private LogNode root = new LogNode(null); + // LoggerContext for system loggers and user loggers + private final LoggerContext systemContext = new SystemLoggerContext(); + private final LoggerContext userContext = new UserLoggerContext(); private Logger rootLogger; // Have we done the primordial reading of the configuration file? @@ -198,12 +199,13 @@ public class LogManager { // Create and retain Logger for the root of the namespace. manager.rootLogger = manager.new RootLogger(); - manager.addLogger(manager.rootLogger); + manager.systemContext.addLogger(manager.rootLogger); + manager.userContext.addLogger(manager.rootLogger); // Adding the global Logger. Doing so in the Logger. // would deadlock with the LogManager.. Logger.getGlobal().setLogManager(manager); - manager.addLogger(Logger.getGlobal()); + manager.systemContext.addLogger(Logger.getGlobal()); // We don't call readConfiguration() here, as we may be running // very early in the JVM startup sequence. Instead readConfiguration @@ -281,14 +283,14 @@ public class LogManager { return; } readPrimordialConfiguration = true; + try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Void run() throws Exception { readConfiguration(); // Platform loggers begin to delegate to java.util.logging.Logger sun.util.logging.PlatformLogger.redirectPlatformLoggers(); - return null; } }); @@ -358,62 +360,290 @@ public class LogManager { } } - // Package-level method. - // Find or create a specified logger instance. If a logger has - // already been created with the given name it is returned. - // Otherwise a new logger instance is created and registered - // in the LogManager global namespace. + // Returns the LoggerContext for the user code (i.e. application or AppContext). + // Loggers are isolated from each AppContext. + LoggerContext getUserContext() { + LoggerContext context = null; - // This method will always return a non-null Logger object. - // Synchronization is not required here. All synchronization for - // adding a new Logger object is handled by addLogger(). - Logger demandLogger(String name) { - Logger result = getLogger(name); - if (result == null) { - // only allocate the new logger once - Logger newLogger = new Logger(name, null); - do { - if (addLogger(newLogger)) { - // We successfully added the new Logger that we - // created above so return it without refetching. - return newLogger; + SecurityManager sm = System.getSecurityManager(); + JavaAWTAccess javaAwtAccess = SharedSecrets.getJavaAWTAccess(); + if (sm != null && javaAwtAccess != null) { + synchronized (javaAwtAccess) { + // AppContext.getAppContext() returns the system AppContext if called + // from a system thread but Logger.getLogger might be called from + // an applet code. Instead, find the AppContext of the applet code + // from the execution stack. + Object ecx = javaAwtAccess.getExecutionContext(); + if (ecx == null) { + // fall back to AppContext.getAppContext() + ecx = javaAwtAccess.getContext(); } - - // We didn't add the new Logger that we created above - // because another thread added a Logger with the same - // name after our null check above and before our call - // to addLogger(). We have to refetch the Logger because - // addLogger() returns a boolean instead of the Logger - // reference itself. However, if the thread that created - // the other Logger is not holding a strong reference to - // the other Logger, then it is possible for the other - // Logger to be GC'ed after we saw it in addLogger() and - // before we can refetch it. If it has been GC'ed then - // we'll just loop around and try again. - result = getLogger(name); - } while (result == null); + context = (LoggerContext)javaAwtAccess.get(ecx, LoggerContext.class); + if (context == null) { + if (javaAwtAccess.isMainAppContext()) { + context = userContext; + } else { + context = new UserLoggerContext(); + context.addLogger(manager.rootLogger); + } + javaAwtAccess.put(ecx, LoggerContext.class, context); + } + } + } else { + context = userContext; } - return result; + return context; } - // If logger.getUseParentHandlers() returns 'true' and any of the logger's - // parents have levels or handlers defined, make sure they are instantiated. - private void processParentHandlers(Logger logger, String name) { - int ix = 1; - for (;;) { - int ix2 = name.indexOf(".", ix); - if (ix2 < 0) { - break; - } - String pname = name.substring(0,ix2); + LoggerContext getSystemContext() { + return systemContext; + } - if (getProperty(pname+".level") != null || - getProperty(pname+".handlers") != null) { - // This pname has a level/handlers definition. - // Make sure it exists. - demandLogger(pname); + private List contexts() { + List cxs = new ArrayList<>(); + cxs.add(systemContext); + cxs.add(getUserContext()); + return cxs; + } + + static class LoggerContext { + // Table of named Loggers that maps names to Loggers. + private final Hashtable namedLoggers = new Hashtable<>(); + // Tree of named Loggers + private final LogNode root; + + private LoggerContext() { + this.root = new LogNode(null, this); + } + + synchronized Logger findLogger(String name) { + LoggerWeakRef ref = namedLoggers.get(name); + if (ref == null) { + return null; } - ix = ix2+1; + Logger logger = ref.get(); + if (logger == null) { + // Hashtable holds stale weak reference + // to a logger which has been GC-ed. + removeLogger(name); + } + return logger; + } + + synchronized boolean addLogger(Logger logger) { + final String name = logger.getName(); + if (name == null) { + throw new NullPointerException(); + } + + // cleanup some Loggers that have been GC'ed + manager.drainLoggerRefQueueBounded(); + + LoggerWeakRef ref = namedLoggers.get(name); + if (ref != null) { + if (ref.get() == null) { + // It's possible that the Logger was GC'ed after the + // drainLoggerRefQueueBounded() call above so allow + // a new one to be registered. + removeLogger(name); + } else { + // We already have a registered logger with the given name. + return false; + } + } + + // We're adding a new logger. + // Note that we are creating a weak reference here. + ref = manager.new LoggerWeakRef(logger); + namedLoggers.put(name, ref); + + // Apply any initial level defined for the new logger. + Level level = manager.getLevelProperty(name + ".level", null); + if (level != null) { + doSetLevel(logger, level); + } + + // Do we have a per logger handler too? + // Note: this will add a 200ms penalty + manager.loadLoggerHandlers(logger, name, name + ".handlers"); + processParentHandlers(logger, name); + + // Find the new node and its parent. + LogNode node = getNode(name); + node.loggerRef = ref; + Logger parent = null; + LogNode nodep = node.parent; + while (nodep != null) { + LoggerWeakRef nodeRef = nodep.loggerRef; + if (nodeRef != null) { + parent = nodeRef.get(); + if (parent != null) { + break; + } + } + nodep = nodep.parent; + } + + if (parent != null) { + doSetParent(logger, parent); + } + // Walk over the children and tell them we are their new parent. + node.walkAndSetParent(logger); + // new LogNode is ready so tell the LoggerWeakRef about it + ref.setNode(node); + return true; + } + + void removeLogger(String name) { + namedLoggers.remove(name); + } + + synchronized Enumeration getLoggerNames() { + return namedLoggers.keys(); + } + + Logger demandLogger(String name) { + return demandLogger(name, null); + } + + // Find or create a specified logger instance. If a logger has + // already been created with the given name it is returned. + // Otherwise a new logger instance is created and registered + // in the LogManager global namespace. + + // This method will always return a non-null Logger object. + // Synchronization is not required here. All synchronization for + // adding a new Logger object is handled by addLogger(). + Logger demandLogger(String name, String resourceBundleName) { + Logger result = findLogger(name); + if (result == null) { + // only allocate the new logger once + Logger newLogger = new Logger(name, resourceBundleName); + do { + if (addLogger(newLogger)) { + // We successfully added the new Logger that we + // created above so return it without refetching. + return newLogger; + } + + // We didn't add the new Logger that we created above + // because another thread added a Logger with the same + // name after our null check above and before our call + // to addLogger(). We have to refetch the Logger because + // addLogger() returns a boolean instead of the Logger + // reference itself. However, if the thread that created + // the other Logger is not holding a strong reference to + // the other Logger, then it is possible for the other + // Logger to be GC'ed after we saw it in addLogger() and + // before we can refetch it. If it has been GC'ed then + // we'll just loop around and try again. + result = findLogger(name); + } while (result == null); + } + return result; + } + + // If logger.getUseParentHandlers() returns 'true' and any of the logger's + // parents have levels or handlers defined, make sure they are instantiated. + private void processParentHandlers(Logger logger, String name) { + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + + if (manager.getProperty(pname + ".level") != null || + manager.getProperty(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + demandLogger(pname); + } + ix = ix2+1; + } + } + + // Gets a node in our tree of logger nodes. + // If necessary, create it. + LogNode getNode(String name) { + if (name == null || name.equals("")) { + return root; + } + LogNode node = root; + while (name.length() > 0) { + int ix = name.indexOf("."); + String head; + if (ix > 0) { + head = name.substring(0, ix); + name = name.substring(ix + 1); + } else { + head = name; + name = ""; + } + if (node.children == null) { + node.children = new HashMap<>(); + } + LogNode child = node.children.get(head); + if (child == null) { + child = new LogNode(node, this); + node.children.put(head, child); + } + node = child; + } + return node; + } + } + + static class SystemLoggerContext extends LoggerContext { + // Default resource bundle for all system loggers + Logger demandLogger(String name) { + // default to use the system logger's resource bundle + return super.demandLogger(name, Logger.SYSTEM_LOGGER_RB_NAME); + } + } + + static class UserLoggerContext extends LoggerContext { + /** + * Returns a Logger of the given name if there is one registered + * in this context. Otherwise, it will return the one registered + * in the system context if there is one. The returned Logger + * instance may be initialized with a different resourceBundleName. + * If no such logger exists, a new Logger instance will be created + * and registered in this context. + */ + Logger demandLogger(String name, String resourceBundleName) { + Logger result = findLogger(name); + if (result == null) { + // use the system logger if exists; or allocate a new logger. + // The system logger is added to the app logger context so that + // any child logger created in the app logger context can have + // a system logger as its parent if already exist. + Logger logger = manager.systemContext.findLogger(name); + Logger newLogger = + logger != null ? logger : new Logger(name, resourceBundleName); + do { + if (addLogger(newLogger)) { + // We successfully added the new Logger that we + // created above so return it without refetching. + return newLogger; + } + + // We didn't add the new Logger that we created above + // because another thread added a Logger with the same + // name after our null check above and before our call + // to addLogger(). We have to refetch the Logger because + // addLogger() returns a boolean instead of the Logger + // reference itself. However, if the thread that created + // the other Logger is not holding a strong reference to + // the other Logger, then it is possible for the other + // Logger to be GC'ed after we saw it in addLogger() and + // before we can refetch it. If it has been GC'ed then + // we'll just loop around and try again. + result = findLogger(name); + } while (result == null); + } + return result; } } @@ -438,16 +668,17 @@ public class LogManager { try { Class clz = ClassLoader.getSystemClassLoader().loadClass(word); Handler hdl = (Handler) clz.newInstance(); - try { - // Check if there is a property defining the - // this handler's level. - String levs = getProperty(word + ".level"); - if (levs != null) { - hdl.setLevel(Level.parse(levs)); + // Check if there is a property defining the + // this handler's level. + String levs = getProperty(word + ".level"); + if (levs != null) { + Level l = Level.findLevel(levs); + if (l != null) { + hdl.setLevel(l); + } else { + // Probably a bad level. Drop through. + System.err.println("Can't set level for " + word); } - } catch (Exception ex) { - System.err.println("Can't set level for " + word); - // Probably a bad level. Drop through. } // Add this Handler to the logger logger.addHandler(hdl); @@ -503,7 +734,7 @@ public class LogManager { if (node != null) { // if we have a LogNode, then we were a named Logger // so clear namedLoggers weak ref to us - manager.namedLoggers.remove(name); + node.context.removeLogger(name); name = null; // clear our ref to the Logger's name node.loggerRef = null; // clear LogNode's weak ref to us @@ -592,70 +823,15 @@ public class LogManager { * false if a logger of that name already exists. * @exception NullPointerException if the logger name is null. */ - public synchronized boolean addLogger(Logger logger) { + public boolean addLogger(Logger logger) { final String name = logger.getName(); if (name == null) { throw new NullPointerException(); } - - // cleanup some Loggers that have been GC'ed - drainLoggerRefQueueBounded(); - - LoggerWeakRef ref = namedLoggers.get(name); - if (ref != null) { - if (ref.get() == null) { - // It's possible that the Logger was GC'ed after the - // drainLoggerRefQueueBounded() call above so allow - // a new one to be registered. - namedLoggers.remove(name); - } else { - // We already have a registered logger with the given name. - return false; - } + if (systemContext.findLogger(name) != null) { + return false; } - - // We're adding a new logger. - // Note that we are creating a weak reference here. - ref = new LoggerWeakRef(logger); - namedLoggers.put(name, ref); - - // Apply any initial level defined for the new logger. - Level level = getLevelProperty(name+".level", null); - if (level != null) { - doSetLevel(logger, level); - } - - // Do we have a per logger handler too? - // Note: this will add a 200ms penalty - loadLoggerHandlers(logger, name, name+".handlers"); - processParentHandlers(logger, name); - - // Find the new node and its parent. - LogNode node = findNode(name); - node.loggerRef = ref; - Logger parent = null; - LogNode nodep = node.parent; - while (nodep != null) { - LoggerWeakRef nodeRef = nodep.loggerRef; - if (nodeRef != null) { - parent = nodeRef.get(); - if (parent != null) { - break; - } - } - nodep = nodep.parent; - } - - if (parent != null) { - doSetParent(logger, parent); - } - // Walk over the children and tell them we are their new parent. - node.walkAndSetParent(logger); - - // new LogNode is ready so tell the LoggerWeakRef about it - ref.setNode(node); - - return true; + return getUserContext().addLogger(logger); } @@ -697,36 +873,6 @@ public class LogManager { }}); } - // Find a node in our tree of logger nodes. - // If necessary, create it. - private LogNode findNode(String name) { - if (name == null || name.equals("")) { - return root; - } - LogNode node = root; - while (name.length() > 0) { - int ix = name.indexOf("."); - String head; - if (ix > 0) { - head = name.substring(0,ix); - name = name.substring(ix+1); - } else { - head = name; - name = ""; - } - if (node.children == null) { - node.children = new HashMap<>(); - } - LogNode child = node.children.get(head); - if (child == null) { - child = new LogNode(node); - node.children.put(head, child); - } - node = child; - } - return node; - } - /** * Method to find a named logger. *

    @@ -742,18 +888,16 @@ public class LogManager { * @param name name of the logger * @return matching logger or null if none is found */ - public synchronized Logger getLogger(String name) { - LoggerWeakRef ref = namedLoggers.get(name); - if (ref == null) { - return null; - } - Logger logger = ref.get(); - if (logger == null) { - // Hashtable holds stale weak reference - // to a logger which has been GC-ed. - namedLoggers.remove(name); - } - return logger; + public Logger getLogger(String name) { + // return the first logger added + // + // once a system logger is added in the system context, no one can + // adds a logger with the same name in the global context + // (see LogManager.addLogger). So if there is a logger in the global + // context with the same name as one in the system context, it must be + // added before the system logger was created. + Logger logger = getUserContext().findLogger(name); + return logger != null ? logger : systemContext.findLogger(name); } /** @@ -772,8 +916,11 @@ public class LogManager { *

    * @return enumeration of logger name strings */ - public synchronized Enumeration getLoggerNames() { - return namedLoggers.keys(); + public Enumeration getLoggerNames() { + // only return unique names + Set names = new HashSet<>(Collections.list(systemContext.getLoggerNames())); + names.addAll(Collections.list(getUserContext().getLoggerNames())); + return Collections.enumeration(names); } /** @@ -858,20 +1005,20 @@ public class LogManager { // the global handlers, if they haven't been initialized yet. initializedGlobalHandlers = true; } - Enumeration enum_ = getLoggerNames(); - while (enum_.hasMoreElements()) { - String name = enum_.nextElement(); - resetLogger(name); + for (LoggerContext cx : contexts()) { + Enumeration enum_ = cx.getLoggerNames(); + while (enum_.hasMoreElements()) { + String name = enum_.nextElement(); + Logger logger = cx.findLogger(name); + if (logger != null) { + resetLogger(logger); + } + } } } - // Private method to reset an individual target logger. - private void resetLogger(String name) { - Logger logger = getLogger(name); - if (logger == null) { - return; - } + private void resetLogger(Logger logger) { // Close all the Logger's handlers. Handler[] targets = logger.getHandlers(); for (int i = 0; i < targets.length; i++) { @@ -883,6 +1030,7 @@ public class LogManager { // Problems closing a handler? Keep going... } } + String name = logger.getName(); if (name != null && name.equals("")) { // This is the root logger. logger.setLevel(defaultLevel); @@ -1046,11 +1194,8 @@ public class LogManager { if (val == null) { return defaultValue; } - try { - return Level.parse(val.trim()); - } catch (Exception ex) { - return defaultValue; - } + Level l = Level.findLevel(val.trim()); + return l != null ? l : defaultValue; } // Package private method to get a filter property. @@ -1140,9 +1285,11 @@ public class LogManager { HashMap children; LoggerWeakRef loggerRef; LogNode parent; + final LoggerContext context; - LogNode(LogNode parent) { + LogNode(LogNode parent, LoggerContext context) { this.parent = parent; + this.context = context; } // Recursive method to walk the tree below a node and set @@ -1215,11 +1362,13 @@ public class LogManager { System.err.println("Bad level value for property: " + key); continue; } - Logger l = getLogger(name); - if (l == null) { - continue; + for (LoggerContext cx : contexts()) { + Logger l = cx.findLogger(name); + if (l == null) { + continue; + } + l.setLevel(level); } - l.setLevel(level); } } diff --git a/jdk/src/share/classes/java/util/logging/Logger.java b/jdk/src/share/classes/java/util/logging/Logger.java index f1d6f729b91..fec3d5c9a64 100644 --- a/jdk/src/share/classes/java/util/logging/Logger.java +++ b/jdk/src/share/classes/java/util/logging/Logger.java @@ -30,6 +30,7 @@ import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.security.*; import java.lang.ref.WeakReference; +import java.util.logging.LogManager.LoggerContext; /** * A Logger object is used to log messages for a specific @@ -286,6 +287,26 @@ public class Logger { } } + // Until all JDK code converted to call sun.util.logging.PlatformLogger + // (see 7054233), we need to determine if Logger.getLogger is to add + // a system logger or user logger. + // + // As an interim solution, if the immediate caller whose caller loader is + // null, we assume it's a system logger and add it to the system context. + private static LoggerContext getLoggerContext() { + LogManager manager = LogManager.getLogManager(); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // 0: Reflection 1: Logger.getLoggerContext 2: Logger.getLogger 3: caller + final int SKIP_FRAMES = 3; + Class caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES); + if (caller.getClassLoader() == null) { + return manager.getSystemContext(); + } + } + return manager.getUserContext(); + } + /** * Find or create a logger for a named subsystem. If a logger has * already been created with the given name it is returned. Otherwise @@ -327,8 +348,8 @@ public class Logger { // would throw an IllegalArgumentException in the second call // because the wrapper would result in an attempt to replace // the existing "resourceBundleForFoo" with null. - LogManager manager = LogManager.getLogManager(); - return manager.demandLogger(name); + LoggerContext context = getLoggerContext(); + return context.demandLogger(name); } /** @@ -375,8 +396,8 @@ public class Logger { // Synchronization is not required here. All synchronization for // adding a new Logger object is handled by LogManager.addLogger(). public static Logger getLogger(String name, String resourceBundleName) { - LogManager manager = LogManager.getLogManager(); - Logger result = manager.demandLogger(name); + LoggerContext context = getLoggerContext(); + Logger result = context.demandLogger(name, resourceBundleName); // MissingResourceException or IllegalArgumentException can be // thrown by setupResourceInfo(). @@ -384,6 +405,18 @@ public class Logger { return result; } + // package-private + // Add a platform logger to the system context. + // i.e. caller of sun.util.logging.PlatformLogger.getLogger + static Logger getPlatformLogger(String name) { + LogManager manager = LogManager.getLogManager(); + LoggerContext context = manager.getSystemContext(); + + // all loggers in the system context will default to + // the system logger's resource bundle + Logger result = context.demandLogger(name); + return result; + } /** * Create an anonymous Logger. The newly created Logger is not @@ -536,7 +569,7 @@ public class Logger { private void doLog(LogRecord lr) { lr.setLoggerName(name); String ebname = getEffectiveResourceBundleName(); - if (ebname != null) { + if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) { lr.setResourceBundleName(ebname); lr.setResourceBundle(findResourceBundle(ebname)); } @@ -1285,6 +1318,22 @@ public class Logger { // May also return null if we can't find the resource bundle and // there is no suitable previous cached value. + static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging"; + + private static ResourceBundle findSystemResourceBundle(final Locale locale) { + // the resource bundle is in a restricted package + return AccessController.doPrivileged(new PrivilegedAction() { + public ResourceBundle run() { + try { + return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME, + locale); + } catch (MissingResourceException e) { + throw new InternalError(e.toString()); + } + } + }); + } + private synchronized ResourceBundle findResourceBundle(String name) { // Return a null bundle for a null name. if (name == null) { @@ -1299,6 +1348,13 @@ public class Logger { return catalog; } + if (name.equals(SYSTEM_LOGGER_RB_NAME)) { + catalog = findSystemResourceBundle(currentLocale); + catalogName = name; + catalogLocale = currentLocale; + return catalog; + } + // Use the thread's context ClassLoader. If there isn't one, // use the SystemClassloader. ClassLoader cl = Thread.currentThread().getContextClassLoader(); @@ -1315,7 +1371,6 @@ public class Logger { // ClassLoader. Drop through. } - // Fall back to searching up the call stack and trying each // calling ClassLoader. for (int ix = 0; ; ix++) { diff --git a/jdk/src/share/classes/java/util/logging/Logging.java b/jdk/src/share/classes/java/util/logging/Logging.java index 2492349188e..bf34046826d 100644 --- a/jdk/src/share/classes/java/util/logging/Logging.java +++ b/jdk/src/share/classes/java/util/logging/Logging.java @@ -34,7 +34,7 @@ import java.util.ArrayList; * * The LoggingMXBean interface provides a standard * method for management access to the individual - * java.util.Logger objects available at runtime. + * {@code Logger} objects available at runtime. * * @author Ron Mann * @author Mandy Chung @@ -75,7 +75,7 @@ class Logging implements LoggingMXBean { if (level == null) { return EMPTY_STRING; } else { - return level.getName(); + return level.getLevelName(); } } @@ -85,7 +85,6 @@ class Logging implements LoggingMXBean { } Logger logger = logManager.getLogger(loggerName); - if (logger == null) { throw new IllegalArgumentException("Logger " + loggerName + "does not exist"); @@ -94,7 +93,10 @@ class Logging implements LoggingMXBean { Level level = null; if (levelName != null) { // parse will throw IAE if logLevel is invalid - level = Level.parse(levelName); + level = Level.findLevel(levelName); + if (level == null) { + throw new IllegalArgumentException("Unknown level \"" + levelName + "\""); + } } logger.setLevel(level); diff --git a/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java b/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java index 8e027d66a47..dbb62a144e3 100644 --- a/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java +++ b/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java @@ -37,7 +37,8 @@ class LoggingProxyImpl implements LoggingProxy { @Override public Object getLogger(String name) { - return Logger.getLogger(name); + // always create a platform logger with the resource bundle name + return Logger.getPlatformLogger(name); } @Override @@ -92,12 +93,16 @@ class LoggingProxyImpl implements LoggingProxy { @Override public Object parseLevel(String levelName) { - return Level.parse(levelName); + Level level = Level.findLevel(levelName); + if (level == null) { + throw new IllegalArgumentException("Unknown level \"" + levelName + "\""); + } + return level; } @Override public String getLevelName(Object level) { - return ((Level) level).getName(); + return ((Level) level).getLevelName(); } @Override diff --git a/jdk/src/share/classes/java/util/logging/SimpleFormatter.java b/jdk/src/share/classes/java/util/logging/SimpleFormatter.java index 87f2c7eeba6..af2b1dcb5f2 100644 --- a/jdk/src/share/classes/java/util/logging/SimpleFormatter.java +++ b/jdk/src/share/classes/java/util/logging/SimpleFormatter.java @@ -162,7 +162,7 @@ public class SimpleFormatter extends Formatter { dat, source, record.getLoggerName(), - record.getLevel().getLocalizedName(), + record.getLevel().getLocalizedLevelName(), message, throwable); } diff --git a/jdk/src/share/classes/sun/awt/AppContext.java b/jdk/src/share/classes/sun/awt/AppContext.java index 0756b6c82bd..47f472737ea 100644 --- a/jdk/src/share/classes/sun/awt/AppContext.java +++ b/jdk/src/share/classes/sun/awt/AppContext.java @@ -327,21 +327,27 @@ public final class AppContext { // Before we return the main "system" AppContext, check to // see if there's an AWTSecurityManager installed. If so, // allow it to choose the AppContext to return. - SecurityManager securityManager = System.getSecurityManager(); - if ((securityManager != null) && - (securityManager instanceof AWTSecurityManager)) - { - AWTSecurityManager awtSecMgr = (AWTSecurityManager)securityManager; - AppContext secAppContext = awtSecMgr.getAppContext(); - if (secAppContext != null) { - appContext = secAppContext; // Return what we're told - } + AppContext secAppContext = getExecutionAppContext(); + if (secAppContext != null) { + appContext = secAppContext; // Return what we're told } } return appContext; } + private final static AppContext getExecutionAppContext() { + SecurityManager securityManager = System.getSecurityManager(); + if ((securityManager != null) && + (securityManager instanceof AWTSecurityManager)) + { + AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager; + AppContext secAppContext = awtSecMgr.getAppContext(); + return secAppContext; // Return what we're told + } + return null; + } + /** * Returns the main ("system") AppContext. * @@ -806,6 +812,21 @@ public final class AppContext { public boolean isMainAppContext() { return (numAppContexts.get() == 1); } + public Object getContext() { + return getAppContext(); + } + public Object getExecutionContext() { + return getExecutionAppContext(); + } + public Object get(Object context, Object key) { + return ((AppContext)context).get(key); + } + public void put(Object context, Object key, Object value) { + ((AppContext)context).put(key, value); + } + public void remove(Object context, Object key) { + ((AppContext)context).remove(key); + } }); } } diff --git a/jdk/src/share/classes/sun/misc/JavaAWTAccess.java b/jdk/src/share/classes/sun/misc/JavaAWTAccess.java index 6e3712592ce..e64a38b22c9 100644 --- a/jdk/src/share/classes/sun/misc/JavaAWTAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaAWTAccess.java @@ -26,6 +26,14 @@ package sun.misc; public interface JavaAWTAccess { + public Object getContext(); + public Object getExecutionContext(); + + public Object get(Object context, Object key); + public void put(Object context, Object key, Object value); + public void remove(Object context, Object key); + + // convenience methods whose context is the object returned by getContext() public Object get(Object key); public void put(Object key, Object value); public void remove(Object key); diff --git a/jdk/src/share/lib/security/java.security b/jdk/src/share/lib/security/java.security index d0dc3c5b423..741f0c2f64d 100644 --- a/jdk/src/share/lib/security/java.security +++ b/jdk/src/share/lib/security/java.security @@ -148,6 +148,9 @@ keystore.type=jks package.access=sun.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.default.,\ + com.sun.jmx.remote.util.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ @@ -166,6 +169,9 @@ package.access=sun.,\ package.definition=sun.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.default.,\ + com.sun.jmx.remote.util.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ From eb67f3f1da2cbf1eeb42f01d9cc778dbbd0820c9 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Fri, 30 Nov 2012 15:51:44 +0400 Subject: [PATCH 028/102] 7201064: Better dialogue checking Reviewed-by: serb, skoivu --- jdk/src/share/classes/java/awt/Dialog.java | 55 ++++++++++++++++++---- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/classes/java/awt/Dialog.java b/jdk/src/share/classes/java/awt/Dialog.java index 800d19c0200..33ae6dde3b9 100644 --- a/jdk/src/share/classes/java/awt/Dialog.java +++ b/jdk/src/share/classes/java/awt/Dialog.java @@ -39,6 +39,7 @@ import sun.awt.PeerEvent; import sun.awt.util.IdentityArrayList; import sun.awt.util.IdentityLinkedList; import sun.security.util.SecurityConstants; +import java.security.AccessControlException; /** * A Dialog is a top-level window with a title and a border @@ -128,6 +129,8 @@ public class Dialog extends Window { */ boolean undecorated = false; + private transient boolean initialized = false; + /** * Modal dialogs block all input to some top-level windows. * Whether a particular window is blocked depends on dialog's type @@ -671,6 +674,7 @@ public class Dialog extends Window { this.title = title; setModalityType(modalityType); SunToolkit.checkAndSetPolicy(this); + initialized = true; } /** @@ -722,6 +726,7 @@ public class Dialog extends Window { this.title = title; setModalityType(modalityType); SunToolkit.checkAndSetPolicy(this); + initialized = true; } /** @@ -851,12 +856,9 @@ public class Dialog extends Window { if (modalityType == type) { return; } - if (type == ModalityType.TOOLKIT_MODAL) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION); - } - } + + checkModalityPermission(type); + modalityType = type; modal = (modalityType != ModalityType.MODELESS); } @@ -1025,6 +1027,11 @@ public class Dialog extends Window { */ @Deprecated public void show() { + if (!initialized) { + throw new IllegalStateException("The dialog component " + + "has not been initialized properly"); + } + beforeFirstShow = false; if (!isModal()) { conditionalShow(null, null); @@ -1600,18 +1607,50 @@ public class Dialog extends Window { } } + private void checkModalityPermission(ModalityType mt) { + if (mt == ModalityType.TOOLKIT_MODAL) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission( + SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION + ); + } + } + } + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException, HeadlessException { GraphicsEnvironment.checkHeadless(); - s.defaultReadObject(); + + java.io.ObjectInputStream.GetField fields = + s.readFields(); + + ModalityType localModalityType = (ModalityType)fields.get("modalityType", null); + + try { + checkModalityPermission(localModalityType); + } catch (AccessControlException ace) { + localModalityType = DEFAULT_MODALITY_TYPE; + } // in 1.5 or earlier modalityType was absent, so use "modal" instead - if (modalityType == null) { + if (localModalityType == null) { + this.modal = fields.get("modal", false); setModal(modal); } + this.resizable = fields.get("resizable", true); + this.undecorated = fields.get("undecorated", false); + this.title = (String)fields.get("title", ""); + this.modalityType = localModalityType; + blockedWindows = new IdentityArrayList(); + + SunToolkit.checkAndSetPolicy(this); + + initialized = true; + } /* From d093c6fbb64b8f9294756755e5e5349f2a616c83 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Wed, 5 Dec 2012 14:02:58 -0800 Subject: [PATCH 029/102] 8004175: Restricted packages added in java.security are missing in java.security-{macosx, solaris, windows} Reviewed-by: alanb, ahgross, mullan --- jdk/src/share/lib/security/java.security-macosx | 6 ++++++ jdk/src/share/lib/security/java.security-solaris | 6 ++++++ jdk/src/share/lib/security/java.security-windows | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx index 9a4f2964e79..5f4d82974ac 100644 --- a/jdk/src/share/lib/security/java.security-macosx +++ b/jdk/src/share/lib/security/java.security-macosx @@ -149,6 +149,9 @@ keystore.type=jks package.access=sun.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.defaults.,\ + com.sun.jmx.remote.util.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ @@ -168,6 +171,9 @@ package.access=sun.,\ package.definition=sun.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.defaults.,\ + com.sun.jmx.remote.util.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index a5b1d577d2e..f8e6774e3a1 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -150,6 +150,9 @@ keystore.type=jks package.access=sun.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.defaults.,\ + com.sun.jmx.remote.util.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ @@ -168,6 +171,9 @@ package.access=sun.,\ package.definition=sun.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.defaults.,\ + com.sun.jmx.remote.util.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows index c2f0ebf8f21..d539f90be63 100644 --- a/jdk/src/share/lib/security/java.security-windows +++ b/jdk/src/share/lib/security/java.security-windows @@ -149,6 +149,9 @@ keystore.type=jks package.access=sun.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.defaults.,\ + com.sun.jmx.remote.util.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ @@ -167,6 +170,9 @@ package.access=sun.,\ package.definition=sun.,\ com.sun.xml.internal.,\ com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.defaults.,\ + com.sun.jmx.remote.util.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ From 07d6fc6bd103f05febb52e76796b6b08790c31d1 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Fri, 7 Dec 2012 22:49:08 +0400 Subject: [PATCH 030/102] 8000537: Contextualize RequiredModelMBean class Contextualize RequiredModelMBean class Reviewed-by: asaha --- .../modelmbean/RequiredModelMBean.java | 225 +++++++++++++----- 1 file changed, 172 insertions(+), 53 deletions(-) diff --git a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java index c1600a94317..6d28adaf0f7 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java +++ b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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,11 +39,13 @@ import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Date; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.logging.Level; import java.util.Map; import java.util.Set; @@ -78,6 +80,8 @@ import javax.management.RuntimeErrorException; import javax.management.RuntimeOperationsException; import javax.management.ServiceNotFoundException; import javax.management.loading.ClassLoaderRepository; +import sun.misc.JavaSecurityAccess; +import sun.misc.SharedSecrets; import sun.reflect.misc.MethodUtil; import sun.reflect.misc.ReflectUtil; @@ -138,6 +142,9 @@ public class RequiredModelMBean private boolean registered = false; private transient MBeanServer server = null; + private final static JavaSecurityAccess javaSecurityAccess = SharedSecrets.getJavaSecurityAccess(); + final private AccessControlContext acc = AccessController.getContext(); + /*************************************/ /* constructors */ /*************************************/ @@ -1025,10 +1032,31 @@ public class RequiredModelMBean if (opClassName != null) { try { - final ClassLoader targetClassLoader = - targetObject.getClass().getClassLoader(); - targetClass = Class.forName(opClassName, false, - targetClassLoader); + AccessControlContext stack = AccessController.getContext(); + final Object obj = targetObject; + final String className = opClassName; + final ClassNotFoundException[] caughtException = new ClassNotFoundException[1]; + + targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction>() { + + @Override + public Class run() { + try { + ReflectUtil.checkPackageAccess(className); + final ClassLoader targetClassLoader = + obj.getClass().getClassLoader(); + return Class.forName(className, false, + targetClassLoader); + } catch (ClassNotFoundException e) { + caughtException[0] = e; + } + return null; + } + }, stack, acc); + + if (caughtException[0] != null) { + throw caughtException[0]; + } } catch (ClassNotFoundException e) { final String msg = "class for invoke " + opName + " not found"; @@ -1061,9 +1089,9 @@ public class RequiredModelMBean return result; } - private static Method resolveMethod(Class targetClass, + private Method resolveMethod(Class targetClass, String opMethodName, - String[] sig) + final String[] sig) throws ReflectionException { final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER); @@ -1078,30 +1106,45 @@ public class RequiredModelMBean if (sig == null) argClasses = null; else { + final AccessControlContext stack = AccessController.getContext(); + final ReflectionException[] caughtException = new ReflectionException[1]; final ClassLoader targetClassLoader = targetClass.getClassLoader(); argClasses = new Class[sig.length]; - for (int i = 0; i < sig.length; i++) { - if (tracing) { - MODELMBEAN_LOGGER.logp(Level.FINER, - RequiredModelMBean.class.getName(),"resolveMethod", - "resolve type " + sig[i]); - } - argClasses[i] = (Class) primitiveClassMap.get(sig[i]); - if (argClasses[i] == null) { - try { - argClasses[i] = - Class.forName(sig[i], false, targetClassLoader); - } catch (ClassNotFoundException e) { + + javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { + + @Override + public Void run() { + for (int i = 0; i < sig.length; i++) { if (tracing) { MODELMBEAN_LOGGER.logp(Level.FINER, - RequiredModelMBean.class.getName(), - "resolveMethod", - "class not found"); + RequiredModelMBean.class.getName(),"resolveMethod", + "resolve type " + sig[i]); + } + argClasses[i] = (Class) primitiveClassMap.get(sig[i]); + if (argClasses[i] == null) { + try { + ReflectUtil.checkPackageAccess(sig[i]); + argClasses[i] = + Class.forName(sig[i], false, targetClassLoader); + } catch (ClassNotFoundException e) { + if (tracing) { + MODELMBEAN_LOGGER.logp(Level.FINER, + RequiredModelMBean.class.getName(), + "resolveMethod", + "class not found"); + } + final String msg = "Parameter class not found"; + caughtException[0] = new ReflectionException(e, msg); + } } - final String msg = "Parameter class not found"; - throw new ReflectionException(e, msg); } + return null; } + }, stack, acc); + + if (caughtException[0] != null) { + throw caughtException[0]; } } @@ -1133,7 +1176,7 @@ public class RequiredModelMBean /* Find a method in RequiredModelMBean as determined by the given parameters. Return null if there is none, or if the parameters exclude using it. Called from invoke. */ - private static Method findRMMBMethod(String opMethodName, + private Method findRMMBMethod(String opMethodName, Object targetObjectField, String opClassName, String[] sig) { @@ -1155,19 +1198,29 @@ public class RequiredModelMBean if (opClassName == null) targetClass = rmmbClass; else { - try { - final ClassLoader targetClassLoader = - rmmbClass.getClassLoader(); - targetClass = Class.forName(opClassName, false, - targetClassLoader); - if (!rmmbClass.isAssignableFrom(targetClass)) - return null; - } catch (ClassNotFoundException e) { - return null; - } + AccessControlContext stack = AccessController.getContext(); + final String className = opClassName; + targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction>() { + + @Override + public Class run() { + try { + ReflectUtil.checkPackageAccess(className); + final ClassLoader targetClassLoader = + rmmbClass.getClassLoader(); + Class clz = Class.forName(className, false, + targetClassLoader); + if (!rmmbClass.isAssignableFrom(clz)) + return null; + return clz; + } catch (ClassNotFoundException e) { + return null; + } + } + }, stack, acc); } try { - return resolveMethod(targetClass, opMethodName, sig); + return targetClass != null ? resolveMethod(targetClass, opMethodName, sig) : null; } catch (ReflectionException e) { return null; } @@ -1177,12 +1230,35 @@ public class RequiredModelMBean * Invoke the given method, and throw the somewhat unpredictable * appropriate exception if the method itself gets an exception. */ - private Object invokeMethod(String opName, Method method, - Object targetObject, Object[] opArgs) + private Object invokeMethod(String opName, final Method method, + final Object targetObject, final Object[] opArgs) throws MBeanException, ReflectionException { try { - ReflectUtil.checkPackageAccess(method.getDeclaringClass()); - return MethodUtil.invoke(method, targetObject, opArgs); + final Throwable[] caughtException = new Throwable[1]; + AccessControlContext stack = AccessController.getContext(); + Object rslt = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { + + @Override + public Object run() { + try { + ReflectUtil.checkPackageAccess(method.getDeclaringClass()); + return MethodUtil.invoke(method, targetObject, opArgs); + } catch (InvocationTargetException e) { + caughtException[0] = e; + } catch (IllegalAccessException e) { + caughtException[0] = e; + } + return null; + } + }, stack, acc); + if (caughtException[0] != null) { + if (caughtException[0] instanceof Exception) { + throw (Exception)caughtException[0]; + } else if(caughtException[0] instanceof Error) { + throw (Error)caughtException[0]; + } + } + return rslt; } catch (RuntimeErrorException ree) { throw new RuntimeOperationsException(ree, "RuntimeException occurred in RequiredModelMBean "+ @@ -1567,7 +1643,7 @@ public class RequiredModelMBean } // make sure response class matches type field - String respType = attrInfo.getType(); + final String respType = attrInfo.getType(); if (response != null) { String responseClass = response.getClass().getName(); if (!respType.equals(responseClass)) { @@ -1590,9 +1666,31 @@ public class RequiredModelMBean // inequality may come from type subclassing boolean subtype; try { - ClassLoader cl = - response.getClass().getClassLoader(); - Class c = Class.forName(respType, true, cl); + final Class respClass = response.getClass(); + final Exception[] caughException = new Exception[1]; + + AccessControlContext stack = AccessController.getContext(); + + Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction>() { + + @Override + public Class run() { + try { + ReflectUtil.checkPackageAccess(respType); + ClassLoader cl = + respClass.getClassLoader(); + return Class.forName(respType, true, cl); + } catch (Exception e) { + caughException[0] = e; + } + return null; + } + }, stack, acc); + + if (caughException[0] != null) { + throw caughException[0]; + } + subtype = c.isInstance(response); } catch (Exception e) { subtype = false; @@ -2745,16 +2843,37 @@ public class RequiredModelMBean return MBeanServerFactory.getClassLoaderRepository(server); } - private Class loadClass(String className) + private Class loadClass(final String className) throws ClassNotFoundException { - try { - return Class.forName(className); - } catch (ClassNotFoundException e) { - final ClassLoaderRepository clr = - getClassLoaderRepository(); - if (clr == null) throw new ClassNotFoundException(className); - return clr.loadClass(className); + AccessControlContext stack = AccessController.getContext(); + final ClassNotFoundException[] caughtException = new ClassNotFoundException[1]; + + Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction>() { + + @Override + public Class run() { + try { + ReflectUtil.checkPackageAccess(className); + return Class.forName(className); + } catch (ClassNotFoundException e) { + final ClassLoaderRepository clr = + getClassLoaderRepository(); + try { + if (clr == null) throw new ClassNotFoundException(className); + return clr.loadClass(className); + } catch (ClassNotFoundException ex) { + caughtException[0] = ex; + } + } + return null; + } + }, stack, acc); + + if (caughtException[0] != null) { + throw caughtException[0]; } + + return c; } From 3780f56b0f987516d3a8d029ded0c11f62f32716 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Wed, 12 Dec 2012 21:08:19 +0400 Subject: [PATCH 031/102] 8004341: Two JCK tests fails with 7u11 b06 Reviewed-by: serb, skoivu --- jdk/src/share/classes/java/awt/Dialog.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/awt/Dialog.java b/jdk/src/share/classes/java/awt/Dialog.java index d24944f2995..d27041fd322 100644 --- a/jdk/src/share/classes/java/awt/Dialog.java +++ b/jdk/src/share/classes/java/awt/Dialog.java @@ -1638,12 +1638,13 @@ public class Dialog extends Window { if (localModalityType == null) { this.modal = fields.get("modal", false); setModal(modal); + } else { + this.modalityType = localModalityType; } this.resizable = fields.get("resizable", true); this.undecorated = fields.get("undecorated", false); this.title = (String)fields.get("title", ""); - this.modalityType = localModalityType; blockedWindows = new IdentityArrayList<>(); From be64e9b087b120e3864b89dca2e5adb61661f777 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Tue, 18 Dec 2012 13:48:48 -0500 Subject: [PATCH 032/102] 8004302: javax/xml/soap/Test7013971.java fails since jdk6u39b01 Reviewed-by: vinnie, skoivu, mgrebac, ohair, tbell --- jdk/src/share/lib/security/java.security-macosx | 8 ++++++-- jdk/src/share/lib/security/java.security-solaris | 8 ++++++-- jdk/src/share/lib/security/java.security-windows | 8 ++++++-- jdk/test/Makefile | 1 + 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx index 5f4d82974ac..707f1cf21a7 100644 --- a/jdk/src/share/lib/security/java.security-macosx +++ b/jdk/src/share/lib/security/java.security-macosx @@ -147,7 +147,9 @@ keystore.type=jks # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. package.access=sun.,\ - com.sun.xml.internal.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ @@ -169,7 +171,9 @@ package.access=sun.,\ # checkPackageDefinition. # package.definition=sun.,\ - com.sun.xml.internal.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index f8e6774e3a1..5f905227d5f 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -148,7 +148,9 @@ keystore.type=jks # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. package.access=sun.,\ - com.sun.xml.internal.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ @@ -169,7 +171,9 @@ package.access=sun.,\ # checkPackageDefinition. # package.definition=sun.,\ - com.sun.xml.internal.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows index d539f90be63..fceb1021d6d 100644 --- a/jdk/src/share/lib/security/java.security-windows +++ b/jdk/src/share/lib/security/java.security-windows @@ -147,7 +147,9 @@ keystore.type=jks # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. package.access=sun.,\ - com.sun.xml.internal.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ @@ -168,7 +170,9 @@ package.access=sun.,\ # checkPackageDefinition. # package.definition=sun.,\ - com.sun.xml.internal.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ diff --git a/jdk/test/Makefile b/jdk/test/Makefile index 408aaaeed25..cac80e27c9f 100644 --- a/jdk/test/Makefile +++ b/jdk/test/Makefile @@ -512,6 +512,7 @@ jdk_other: $(call TestDirs, \ javax/script \ java/sql javax/sql \ javax/smartcardio \ + javax/xml/soap \ javax/xml/ws com/sun/internal/ws \ jdk/asm \ com/sun/org/apache/xerces \ From 3243aaf47a448a5e99cdb09a010fd86aec3d740a Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Thu, 10 Jan 2013 19:43:36 -0800 Subject: [PATCH 033/102] 8005615: Java Logger fails to load tomcat logger implementation (JULI) Reviewed-by: alanb, ahgross --- .../classes/java/util/logging/LogManager.java | 263 +++++++++--------- .../classes/java/util/logging/Logger.java | 37 ++- .../java/util/logging/CustomLogManager.java | 177 ++++++++++++ .../util/logging/CustomLogManagerTest.java | 63 +++++ .../java/util/logging/SimpleLogManager.java | 113 ++++++++ 5 files changed, 513 insertions(+), 140 deletions(-) create mode 100644 jdk/test/java/util/logging/CustomLogManager.java create mode 100644 jdk/test/java/util/logging/CustomLogManagerTest.java create mode 100644 jdk/test/java/util/logging/SimpleLogManager.java diff --git a/jdk/src/share/classes/java/util/logging/LogManager.java b/jdk/src/share/classes/java/util/logging/LogManager.java index 3526c77ac01..58bd1ba7ead 100644 --- a/jdk/src/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/share/classes/java/util/logging/LogManager.java @@ -158,7 +158,7 @@ public class LogManager { // LoggerContext for system loggers and user loggers private final LoggerContext systemContext = new SystemLoggerContext(); - private final LoggerContext userContext = new UserLoggerContext(); + private final LoggerContext userContext = new LoggerContext(); private Logger rootLogger; // Have we done the primordial reading of the configuration file? @@ -196,13 +196,13 @@ public class LogManager { // Create and retain Logger for the root of the namespace. manager.rootLogger = manager.new RootLogger(); - manager.systemContext.addLogger(manager.rootLogger); - manager.userContext.addLogger(manager.rootLogger); + manager.addLogger(manager.rootLogger); + manager.systemContext.addLocalLogger(manager.rootLogger); // Adding the global Logger. Doing so in the Logger. // would deadlock with the LogManager.. - Logger.getGlobal().setLogManager(manager); - manager.systemContext.addLogger(Logger.getGlobal()); + Logger.global.setLogManager(manager); + manager.addLogger(Logger.global); // We don't call readConfiguration() here, as we may be running // very early in the JVM startup sequence. Instead readConfiguration @@ -373,7 +373,7 @@ public class LogManager { // Returns the LoggerContext for the user code (i.e. application or AppContext). // Loggers are isolated from each AppContext. - LoggerContext getUserContext() { + private LoggerContext getUserContext() { LoggerContext context = null; SecurityManager sm = System.getSecurityManager(); @@ -394,8 +394,8 @@ public class LogManager { if (javaAwtAccess.isMainAppContext()) { context = userContext; } else { - context = new UserLoggerContext(); - context.addLogger(manager.rootLogger); + context = new LoggerContext(); + context.addLocalLogger(manager.rootLogger); } javaAwtAccess.put(ecx, LoggerContext.class, context); } @@ -406,10 +406,6 @@ public class LogManager { return context; } - LoggerContext getSystemContext() { - return systemContext; - } - private List contexts() { List cxs = new ArrayList<>(); cxs.add(systemContext); @@ -417,6 +413,58 @@ public class LogManager { return cxs; } + // Find or create a specified logger instance. If a logger has + // already been created with the given name it is returned. + // Otherwise a new logger instance is created and registered + // in the LogManager global namespace. + // This method will always return a non-null Logger object. + // Synchronization is not required here. All synchronization for + // adding a new Logger object is handled by addLogger(). + // + // This method must delegate to the LogManager implementation to + // add a new Logger or return the one that has been added previously + // as a LogManager subclass may override the addLogger, getLogger, + // readConfiguration, and other methods. + Logger demandLogger(String name, String resourceBundleName) { + Logger result = getLogger(name); + if (result == null) { + // only allocate the new logger once + Logger newLogger = new Logger(name, resourceBundleName); + do { + if (addLogger(newLogger)) { + // We successfully added the new Logger that we + // created above so return it without refetching. + return newLogger; + } + + // We didn't add the new Logger that we created above + // because another thread added a Logger with the same + // name after our null check above and before our call + // to addLogger(). We have to refetch the Logger because + // addLogger() returns a boolean instead of the Logger + // reference itself. However, if the thread that created + // the other Logger is not holding a strong reference to + // the other Logger, then it is possible for the other + // Logger to be GC'ed after we saw it in addLogger() and + // before we can refetch it. If it has been GC'ed then + // we'll just loop around and try again. + result = getLogger(name); + } while (result == null); + } + return result; + } + + Logger demandSystemLogger(String name, String resourceBundleName) { + return systemContext.demandLogger(name, resourceBundleName); + } + + // LoggerContext maintains the logger namespace per context. + // The default LogManager implementation has one system context and user + // context. The system context is used to maintain the namespace for + // all system loggers and is queried by the system code. If a system logger + // doesn't exist in the user context, it'll also be added to the user context. + // The user context is queried by the user code and all other loggers are + // added in the user context. static class LoggerContext { // Table of named Loggers that maps names to Loggers. private final Hashtable namedLoggers = new Hashtable<>(); @@ -427,6 +475,12 @@ public class LogManager { this.root = new LogNode(null, this); } + Logger demandLogger(String name, String resourceBundleName) { + // a LogManager subclass may have its own implementation to add and + // get a Logger. So delegate to the LogManager to do the work. + return manager.demandLogger(name, resourceBundleName); + } + synchronized Logger findLogger(String name) { LoggerWeakRef ref = namedLoggers.get(name); if (ref == null) { @@ -441,7 +495,9 @@ public class LogManager { return logger; } - synchronized boolean addLogger(Logger logger) { + // Add a logger to this context. This method will only set its level + // and process parent loggers. It doesn't set its handlers. + synchronized boolean addLocalLogger(Logger logger) { final String name = logger.getName(); if (name == null) { throw new NullPointerException(); @@ -474,9 +530,9 @@ public class LogManager { doSetLevel(logger, level); } - // Do we have a per logger handler too? - // Note: this will add a 200ms penalty - manager.loadLoggerHandlers(logger, name, name + ".handlers"); + // instantiation of the handler is done in the LogManager.addLogger + // implementation as a handler class may be only visible to LogManager + // subclass for the custom log manager case processParentHandlers(logger, name); // Find the new node and its parent. @@ -513,50 +569,21 @@ public class LogManager { return namedLoggers.keys(); } - Logger demandLogger(String name) { - return demandLogger(name, null); - } - - // Find or create a specified logger instance. If a logger has - // already been created with the given name it is returned. - // Otherwise a new logger instance is created and registered - // in the LogManager global namespace. - - // This method will always return a non-null Logger object. - // Synchronization is not required here. All synchronization for - // adding a new Logger object is handled by addLogger(). - Logger demandLogger(String name, String resourceBundleName) { - Logger result = findLogger(name); - if (result == null) { - // only allocate the new logger once - Logger newLogger = new Logger(name, resourceBundleName); - do { - if (addLogger(newLogger)) { - // We successfully added the new Logger that we - // created above so return it without refetching. - return newLogger; - } - - // We didn't add the new Logger that we created above - // because another thread added a Logger with the same - // name after our null check above and before our call - // to addLogger(). We have to refetch the Logger because - // addLogger() returns a boolean instead of the Logger - // reference itself. However, if the thread that created - // the other Logger is not holding a strong reference to - // the other Logger, then it is possible for the other - // Logger to be GC'ed after we saw it in addLogger() and - // before we can refetch it. If it has been GC'ed then - // we'll just loop around and try again. - result = findLogger(name); - } while (result == null); - } - return result; - } - // If logger.getUseParentHandlers() returns 'true' and any of the logger's // parents have levels or handlers defined, make sure they are instantiated. - private void processParentHandlers(Logger logger, String name) { + private void processParentHandlers(final Logger logger, final String name) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + if (logger != manager.rootLogger) { + boolean useParent = manager.getBooleanProperty(name + ".useParentHandlers", true); + if (!useParent) { + logger.setUseParentHandlers(false); + } + } + return null; + } + }); + int ix = 1; for (;;) { int ix2 = name.indexOf(".", ix); @@ -564,12 +591,11 @@ public class LogManager { break; } String pname = name.substring(0, ix2); - if (manager.getProperty(pname + ".level") != null || manager.getProperty(pname + ".handlers") != null) { // This pname has a level/handlers definition. // Make sure it exists. - demandLogger(pname); + demandLogger(pname, null); } ix = ix2+1; } @@ -607,53 +633,51 @@ public class LogManager { } static class SystemLoggerContext extends LoggerContext { - // Default resource bundle for all system loggers - Logger demandLogger(String name) { - // default to use the system logger's resource bundle - return super.demandLogger(name, Logger.SYSTEM_LOGGER_RB_NAME); - } - } - - static class UserLoggerContext extends LoggerContext { - /** - * Returns a Logger of the given name if there is one registered - * in this context. Otherwise, it will return the one registered - * in the system context if there is one. The returned Logger - * instance may be initialized with a different resourceBundleName. - * If no such logger exists, a new Logger instance will be created - * and registered in this context. - */ + // Add a system logger in the system context's namespace as well as + // in the LogManager's namespace if not exist so that there is only + // one single logger of the given name. System loggers are visible + // to applications unless a logger of the same name has been added. Logger demandLogger(String name, String resourceBundleName) { Logger result = findLogger(name); if (result == null) { - // use the system logger if exists; or allocate a new logger. - // The system logger is added to the app logger context so that - // any child logger created in the app logger context can have - // a system logger as its parent if already exist. - Logger logger = manager.systemContext.findLogger(name); - Logger newLogger = - logger != null ? logger : new Logger(name, resourceBundleName); + // only allocate the new system logger once + Logger newLogger = new Logger(name, resourceBundleName); do { - if (addLogger(newLogger)) { + if (addLocalLogger(newLogger)) { // We successfully added the new Logger that we // created above so return it without refetching. - return newLogger; + result = newLogger; + } else { + // We didn't add the new Logger that we created above + // because another thread added a Logger with the same + // name after our null check above and before our call + // to addLogger(). We have to refetch the Logger because + // addLogger() returns a boolean instead of the Logger + // reference itself. However, if the thread that created + // the other Logger is not holding a strong reference to + // the other Logger, then it is possible for the other + // Logger to be GC'ed after we saw it in addLogger() and + // before we can refetch it. If it has been GC'ed then + // we'll just loop around and try again. + result = findLogger(name); } - - // We didn't add the new Logger that we created above - // because another thread added a Logger with the same - // name after our null check above and before our call - // to addLogger(). We have to refetch the Logger because - // addLogger() returns a boolean instead of the Logger - // reference itself. However, if the thread that created - // the other Logger is not holding a strong reference to - // the other Logger, then it is possible for the other - // Logger to be GC'ed after we saw it in addLogger() and - // before we can refetch it. If it has been GC'ed then - // we'll just loop around and try again. - result = findLogger(name); } while (result == null); } + // Add the system logger to the LogManager's namespace if not exists + // The LogManager will set its handlers via the LogManager.addLogger method. + if (!manager.addLogger(result) && result.getHandlers().length == 0) { + // if logger already exists but handlers not set + final Logger l = manager.getLogger(name); + final Logger logger = result; + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + for (Handler hdl : l.getHandlers()) { + logger.addHandler(hdl); + } + return null; + } + }); + } return result; } } @@ -663,22 +687,16 @@ public class LogManager { // be made based on the logging configuration, which can // only be modified by trusted code. private void loadLoggerHandlers(final Logger logger, final String name, - final String handlersPropertyName) { + final String handlersPropertyName) + { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { - if (logger != rootLogger) { - boolean useParent = getBooleanProperty(name + ".useParentHandlers", true); - if (!useParent) { - logger.setUseParentHandlers(false); - } - } - String names[] = parseClassNames(handlersPropertyName); for (int i = 0; i < names.length; i++) { String word = names[i]; try { Class clz = ClassLoader.getSystemClassLoader().loadClass(word); - Handler hdl = (Handler) clz.newInstance(); + Handler hdl = (Handler) clz.newInstance(); // Check if there is a property defining the // this handler's level. String levs = getProperty(word + ".level"); @@ -700,7 +718,8 @@ public class LogManager { } } return null; - }}); + } + }); } @@ -839,13 +858,17 @@ public class LogManager { if (name == null) { throw new NullPointerException(); } - if (systemContext.findLogger(name) != null) { + LoggerContext cx = getUserContext(); + if (cx.addLocalLogger(logger)) { + // Do we have a per logger handler too? + // Note: this will add a 200ms penalty + loadLoggerHandlers(logger, name, name + ".handlers"); + return true; + } else { return false; } - return getUserContext().addLogger(logger); } - // Private method to set a level on a logger. // If necessary, we raise privilege before doing the call. private static void doSetLevel(final Logger logger, final Level level) { @@ -864,8 +887,6 @@ public class LogManager { }}); } - - // Private method to set a parent on a logger. // If necessary, we raise privilege before doing the setParent call. private static void doSetParent(final Logger logger, final Logger parent) { @@ -900,15 +921,7 @@ public class LogManager { * @return matching logger or null if none is found */ public Logger getLogger(String name) { - // return the first logger added - // - // once a system logger is added in the system context, no one can - // adds a logger with the same name in the global context - // (see LogManager.addLogger). So if there is a logger in the global - // context with the same name as one in the system context, it must be - // added before the system logger was created. - Logger logger = getUserContext().findLogger(name); - return logger != null ? logger : systemContext.findLogger(name); + return getUserContext().findLogger(name); } /** @@ -928,10 +941,7 @@ public class LogManager { * @return enumeration of logger name strings */ public Enumeration getLoggerNames() { - // only return unique names - Set names = new HashSet<>(Collections.list(systemContext.getLoggerNames())); - names.addAll(Collections.list(getUserContext().getLoggerNames())); - return Collections.enumeration(names); + return getUserContext().getLoggerNames(); } /** @@ -1329,7 +1339,6 @@ public class LogManager { // that we only instantiate the global handlers when they // are first needed. private class RootLogger extends Logger { - private RootLogger() { super("", null); setLevel(defaultLevel); diff --git a/jdk/src/share/classes/java/util/logging/Logger.java b/jdk/src/share/classes/java/util/logging/Logger.java index 34f96be2112..5d060059e60 100644 --- a/jdk/src/share/classes/java/util/logging/Logger.java +++ b/jdk/src/share/classes/java/util/logging/Logger.java @@ -31,7 +31,6 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.security.*; import java.lang.ref.WeakReference; import java.util.function.Supplier; -import java.util.logging.LogManager.LoggerContext; /** * A Logger object is used to log messages for a specific @@ -321,18 +320,32 @@ public class Logger { // // As an interim solution, if the immediate caller whose caller loader is // null, we assume it's a system logger and add it to the system context. - private static LoggerContext getLoggerContext() { + // These system loggers only set the resource bundle to the given + // resource bundle name (rather than the default system resource bundle). + private static class SystemLoggerHelper { + static boolean disableCallerCheck = getBooleanProperty("sun.util.logging.disableCallerCheck"); + private static boolean getBooleanProperty(final String key) { + String s = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty(key); + } + }); + return Boolean.valueOf(s); + } + } + + private static Logger demandLogger(String name, String resourceBundleName) { LogManager manager = LogManager.getLogManager(); SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // 0: Reflection 1: Logger.getLoggerContext 2: Logger.getLogger 3: caller + if (sm != null && !SystemLoggerHelper.disableCallerCheck) { + // 0: Reflection 1: Logger.demandLogger 2: Logger.getLogger 3: caller final int SKIP_FRAMES = 3; Class caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES); if (caller.getClassLoader() == null) { - return manager.getSystemContext(); + return manager.demandSystemLogger(name, resourceBundleName); } } - return manager.getUserContext(); + return manager.demandLogger(name, resourceBundleName); } /** @@ -376,8 +389,7 @@ public class Logger { // would throw an IllegalArgumentException in the second call // because the wrapper would result in an attempt to replace // the existing "resourceBundleForFoo" with null. - LoggerContext context = getLoggerContext(); - return context.demandLogger(name); + return demandLogger(name, null); } /** @@ -424,8 +436,7 @@ public class Logger { // Synchronization is not required here. All synchronization for // adding a new Logger object is handled by LogManager.addLogger(). public static Logger getLogger(String name, String resourceBundleName) { - LoggerContext context = getLoggerContext(); - Logger result = context.demandLogger(name, resourceBundleName); + Logger result = demandLogger(name, resourceBundleName); // MissingResourceException or IllegalArgumentException can be // thrown by setupResourceInfo(). @@ -438,11 +449,10 @@ public class Logger { // i.e. caller of sun.util.logging.PlatformLogger.getLogger static Logger getPlatformLogger(String name) { LogManager manager = LogManager.getLogManager(); - LoggerContext context = manager.getSystemContext(); // all loggers in the system context will default to // the system logger's resource bundle - Logger result = context.demandLogger(name); + Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME); return result; } @@ -1588,7 +1598,8 @@ public class Logger { public ResourceBundle run() { try { return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME, - locale); + locale, + ClassLoader.getSystemClassLoader()); } catch (MissingResourceException e) { throw new InternalError(e.toString()); } diff --git a/jdk/test/java/util/logging/CustomLogManager.java b/jdk/test/java/util/logging/CustomLogManager.java new file mode 100644 index 00000000000..9542e54ec02 --- /dev/null +++ b/jdk/test/java/util/logging/CustomLogManager.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2013, 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.util.*; +import java.util.logging.*; + +/* + * Custom LogManager implementation to verify that the implementation delegates + * to the LogManager subclass to register both system logger and user logger. + * + * The LogManager implementation is the one configuring the logger's property + * such as level, handler, etc. + */ +public class CustomLogManager extends LogManager { + static LogManager INSTANCE; + Map namedLoggers = new HashMap<>(); + Properties props = initConfig(); + public CustomLogManager() { + if (INSTANCE != null) { + throw new RuntimeException("CustomLogManager already created"); + } + INSTANCE = this; + } + + public synchronized boolean addLogger(Logger logger) { + String name = logger.getName(); + if (namedLoggers.containsKey(name)) { + return false; + } + namedLoggers.put(name, logger); + // set level + if (props.get(name + ".level") != null) { + logger.setLevel(Level.parse(props.getProperty(name + ".level"))); + } + // add handlers + if (props.get(name + ".handlers") != null && logger.getHandlers().length == 0) { + logger.addHandler(new CustomHandler()); + } + // add parent loggers + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + if (props.get(pname + ".level") != null || + props.get(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + // + // The test doesn't set the parent for simplicity. + if (!namedLoggers.containsKey(pname)) { + Logger.getLogger(pname); + } + } + ix = ix2 + 1; + } + return true; + } + + public synchronized Logger getLogger(String name) { + return namedLoggers.get(name); + } + + public synchronized Enumeration getLoggerNames() { + return Collections.enumeration(namedLoggers.keySet()); + } + + public String getProperty(String name) { + return props.getProperty(name); + } + + public void readConfiguration() { + // do nothing + } + + public void readConfiguration(InputStream ins) { + // do nothing + } + + private Properties initConfig() { + Properties props = new Properties(); + props.put(".level", "CONFIG"); + props.put("CustomLogManagerTest.level", "WARNING"); + props.put("CustomLogManagerTest.handlers", "CustomLogManager$CustomHandler"); + props.put("SimpleLogManager.level", "INFO"); + props.put("SimpleLogManager.handlers", "CustomLogManager$CustomHandler"); + props.put("CustomLogManager$CustomHandler.level", "WARNING"); + props.put(".handlers", "CustomLogManager$CustomHandler"); + props.put("org.foo.bar.level", "SEVERE"); + props.put("org.foo.handlers", "CustomLogManager$CustomHandler"); + props.put("org.openjdk.level", "SEVERE"); + props.put("org.openjdk.handlers", "CustomLogManager$CustomHandler"); + props.put("org.openjdk.core.level", "INFO"); + + return props; + } + + public static void checkLogger(String name) { + checkLogger(name, null); + } + + public static void checkLogger(String name, String resourceBundleName) { + Logger logger = INSTANCE.getLogger(name); + if (logger == null) { + throw new RuntimeException("Logger \"" + name + "\" not exist"); + } + System.out.format("Logger \"%s\" level=%s handlers=%s resourcebundle=%s%n", + name, logger.getLevel(), + Arrays.toString(logger.getHandlers()), + logger.getResourceBundleName()); + String rb = logger.getResourceBundleName(); + if (rb != resourceBundleName && (rb == null || rb.equals(resourceBundleName))) { + throw new RuntimeException("Logger \"" + name + + "\" unexpected resource bundle: " + rb); + } + + String value = INSTANCE.getProperty(name + ".level"); + String level = logger.getLevel() != null ? logger.getLevel().getName() : null; + if (level != value && (level == null || level.equals(value))) { + throw new RuntimeException("Logger \"" + name + "\" unexpected level: " + level); + } + + Handler[] handlers = logger.getHandlers(); + String hdl = INSTANCE.getProperty(name + ".handlers"); + if ((hdl == null && handlers.length != 0) || + (hdl != null && handlers.length != 1)) { + throw new RuntimeException("Logger \"" + name + "\" unexpected handler: " + + Arrays.toString(handlers)); + } + checkParents(name); + } + + private static void checkParents(String name) { + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + if (INSTANCE.getProperty(pname + ".level") != null || + INSTANCE.getProperty(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + checkLogger(pname); + } + ix = ix2 + 1; + } + } + + // only CustomLogManager can create an instance of CustomHandler + private class CustomHandler extends StreamHandler { + } +} diff --git a/jdk/test/java/util/logging/CustomLogManagerTest.java b/jdk/test/java/util/logging/CustomLogManagerTest.java new file mode 100644 index 00000000000..2fa89a9a47b --- /dev/null +++ b/jdk/test/java/util/logging/CustomLogManagerTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, 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.util.*; + +import java.util.logging.*; +import sun.util.logging.PlatformLogger; + +/* + * @test + * @bug 8005615 + * @summary Add loggers to custom log manager + * + * @compile -XDignore.symbol.file CustomLogManagerTest.java CustomLogManager.java + * @run main/othervm -Djava.util.logging.manager=CustomLogManager CustomLogManagerTest + */ +public class CustomLogManagerTest { + private static final String RESOURCE_BUNDLE = "sun.util.logging.resources.logging"; + public static void main(String[] args) { + String mgr = System.getProperty("java.util.logging.manager"); + if (!mgr.equals("CustomLogManager")) { + throw new RuntimeException("java.util.logging.manager not set"); + } + + Logger.getLogger(CustomLogManagerTest.class.getName()); + Logger.getLogger("org.foo.Foo"); + Logger.getLogger("org.foo.bar.Foo", RESOURCE_BUNDLE); + // platform logger will be set with the default system resource bundle + PlatformLogger.getLogger("org.openjdk.core.logger"); + + if (LogManager.getLogManager() != CustomLogManager.INSTANCE) { + throw new RuntimeException(LogManager.getLogManager() + " not CustomLogManager"); + } + + CustomLogManager.checkLogger(CustomLogManagerTest.class.getName()); + CustomLogManager.checkLogger("org.foo.Foo"); + CustomLogManager.checkLogger("org.foo.bar.Foo", RESOURCE_BUNDLE); + CustomLogManager.checkLogger(Logger.GLOBAL_LOGGER_NAME); + CustomLogManager.checkLogger(""); + CustomLogManager.checkLogger("org.openjdk.core.logger", RESOURCE_BUNDLE); + } +} diff --git a/jdk/test/java/util/logging/SimpleLogManager.java b/jdk/test/java/util/logging/SimpleLogManager.java new file mode 100644 index 00000000000..f469727654f --- /dev/null +++ b/jdk/test/java/util/logging/SimpleLogManager.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013, 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.util.*; +import java.util.logging.*; +import sun.util.logging.PlatformLogger; + +/* + * @test + * @bug 8005615 + * @summary A LogManager subclass overrides its own implementation of named + * logger (see the subclassing information in the Logger class specification) + * + * @compile -XDignore.symbol.file CustomLogManager.java SimpleLogManager.java + * @run main/othervm -Djava.util.logging.manager=SimpleLogManager SimpleLogManager + */ +public class SimpleLogManager extends CustomLogManager { + public static void main(String[] args) { + String classname = System.getProperty("java.util.logging.manager"); + if (!classname.equals("SimpleLogManager")) { + throw new RuntimeException("java.util.logging.manager not set"); + } + + Logger logger = Logger.getLogger(SimpleLogManager.class.getName()); + Logger.getLogger("org.foo.bar.Foo"); + + // a platform logger used by the system code is just a Logger instance. + PlatformLogger.getLogger("org.openjdk.core.logger"); + + LogManager mgr = LogManager.getLogManager(); + if (mgr != CustomLogManager.INSTANCE || !(mgr instanceof SimpleLogManager)) { + throw new RuntimeException(LogManager.getLogManager() + " not SimpleLogManager"); + } + + checkCustomLogger(SimpleLogManager.class.getName(), null); + checkCustomLogger("org.foo.bar.Foo", null); + checkCustomLogger("org.openjdk.core.logger", "sun.util.logging.resources.logging"); + + // ## The LogManager.demandLogger method does not handle custom log manager + // ## that overrides the getLogger method to return a custom logger + // ## (see the test case in 8005640). Logger.getLogger may return + // ## a Logger instance but LogManager overrides it with a custom Logger + // ## instance like this case. + // + // However, the specification of LogManager and Logger subclassing is + // not clear whether this is supported or not. The following check + // just captures the current behavior. + if (logger instanceof CustomLogger) { + throw new RuntimeException(logger + " not CustomLogger"); + } + } + + private static void checkCustomLogger(String name, String resourceBundleName) { + CustomLogManager.checkLogger(name, resourceBundleName); + Logger logger1 = Logger.getLogger(name); + Logger logger2 = LogManager.getLogManager().getLogger(name); + if (logger1 != logger2) { + throw new RuntimeException(logger1 + " != " + logger2); + } + if (!(logger1 instanceof CustomLogger)) { + throw new RuntimeException(logger1 + " not CustomLogger"); + } + } + + /* + * This SimpleLogManager overrides the addLogger method to replace + * the given logger with a custom logger. + * + * It's unclear what the recommended way to use custom logger is. + * A LogManager subclass might override the getLogger method to return + * a custom Logger and create a new custom logger if not exist so that + * Logger.getLogger() can return a custom Logger instance but that violates + * the LogManager.getLogger() spec which should return null if not found. + */ + public synchronized boolean addLogger(Logger logger) { + String name = logger.getName(); + if (namedLoggers.containsKey(name)) { + return false; + } + CustomLogger newLogger = new CustomLogger(logger); + super.addLogger(newLogger); + return true; + } + + public class CustomLogger extends Logger { + CustomLogger(Logger logger) { + super(logger.getName(), logger.getResourceBundleName()); + } + CustomLogger(String name) { + super(name, null); + } + } +} From 7cb8f824d3f46cf6d3dd1066d7ceb4a0747cde8d Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Mon, 28 Jan 2013 15:53:29 -0800 Subject: [PATCH 034/102] 8006882: Proxy generated classes in sun.proxy package breaks JMockit Reviewed-by: alanb, ahgross --- jdk/src/share/classes/java/lang/reflect/Proxy.java | 2 +- jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java | 4 +++- jdk/src/share/lib/security/java.security-linux | 2 ++ jdk/src/share/lib/security/java.security-macosx | 2 ++ jdk/src/share/lib/security/java.security-solaris | 2 ++ jdk/src/share/lib/security/java.security-windows | 2 ++ 6 files changed, 12 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/java/lang/reflect/Proxy.java b/jdk/src/share/classes/java/lang/reflect/Proxy.java index 5e0c31f2de0..e946ba3226d 100644 --- a/jdk/src/share/classes/java/lang/reflect/Proxy.java +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java @@ -609,7 +609,7 @@ public class Proxy implements java.io.Serializable { } if (proxyPkg == null) { - // if no non-public proxy interfaces, use sun.proxy package + // if no non-public proxy interfaces, use com.sun.proxy package proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } diff --git a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java index 84ab06b080a..0640d92e5d0 100644 --- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java @@ -202,5 +202,7 @@ public final class ReflectUtil { } } - public static final String PROXY_PACKAGE = "sun.proxy"; + // Note that bytecode instrumentation tools may exclude 'sun.*' + // classes but not generated proxy classes and so keep it in com.sun.* + public static final String PROXY_PACKAGE = "com.sun.proxy"; } diff --git a/jdk/src/share/lib/security/java.security-linux b/jdk/src/share/lib/security/java.security-linux index cdda1b47699..c37bb480eb6 100644 --- a/jdk/src/share/lib/security/java.security-linux +++ b/jdk/src/share/lib/security/java.security-linux @@ -153,6 +153,7 @@ package.access=sun.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ com.sun.jmx.remote.util.,\ + com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ @@ -177,6 +178,7 @@ package.definition=sun.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ com.sun.jmx.remote.util.,\ + com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx index 515141de81b..ffb99c06936 100644 --- a/jdk/src/share/lib/security/java.security-macosx +++ b/jdk/src/share/lib/security/java.security-macosx @@ -154,6 +154,7 @@ package.access=sun.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ com.sun.jmx.remote.util.,\ + com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ @@ -179,6 +180,7 @@ package.definition=sun.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ com.sun.jmx.remote.util.,\ + com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index 2cccc0d455b..4236643f55e 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -155,6 +155,7 @@ package.access=sun.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ com.sun.jmx.remote.util.,\ + com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ @@ -179,6 +180,7 @@ package.definition=sun.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ com.sun.jmx.remote.util.,\ + com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows index b6281f741a1..89ec5678646 100644 --- a/jdk/src/share/lib/security/java.security-windows +++ b/jdk/src/share/lib/security/java.security-windows @@ -154,6 +154,7 @@ package.access=sun.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ com.sun.jmx.remote.util.,\ + com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ @@ -178,6 +179,7 @@ package.definition=sun.,\ com.sun.istack.internal.,\ com.sun.jmx.defaults.,\ com.sun.jmx.remote.util.,\ + com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ From 7303280ef5e99aff51f0e1bdcbdbcb66bb7f226e Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 30 Jan 2013 11:33:51 +0100 Subject: [PATCH 035/102] 8006446: Restrict MBeanServer access Reviewed-by: alanb, mchung, darcy, jrose, ahgross, skoivu --- .../ClassLoaderRepositorySupport.java | 2 ++ .../sun/jmx/mbeanserver/JmxMBeanServer.java | 10 ++++++ .../jmx/mbeanserver/MBeanInstantiator.java | 34 ++++++++++++++++--- .../com/sun/jmx/mbeanserver/MBeanSupport.java | 2 ++ .../lang/management/ManagementFactory.java | 18 +++++----- .../share/lib/security/java.security-linux | 6 ++-- .../share/lib/security/java.security-macosx | 6 ++-- .../share/lib/security/java.security-solaris | 6 ++-- .../share/lib/security/java.security-windows | 6 ++-- .../SubjectDelegation2Test.java | 6 ++-- .../SubjectDelegation3Test.java | 6 ++-- 11 files changed, 67 insertions(+), 35 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java index 728fb12a7e8..9fc0e7dbe9e 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java @@ -36,6 +36,7 @@ import java.util.logging.Level; import javax.management.ObjectName; import javax.management.loading.PrivateClassLoader; +import sun.reflect.misc.ReflectUtil; /** * This class keeps the list of Class Loaders registered in the MBean Server. @@ -192,6 +193,7 @@ final class ClassLoaderRepositorySupport final ClassLoader without, final ClassLoader stop) throws ClassNotFoundException { + ReflectUtil.checkPackageAccess(className); final int size = list.length; for(int i=0; i theClass) throws ReflectionException, MBeanException { + + checkMBeanPermission(theClass, null, null, "instantiate"); + Object moi; @@ -260,6 +266,9 @@ public class MBeanInstantiator { public Object instantiate(Class theClass, Object params[], String signature[], ClassLoader loader) throws ReflectionException, MBeanException { + + checkMBeanPermission(theClass, null, null, "instantiate"); + // Instantiate the new object // ------------------------------ @@ -407,6 +416,8 @@ public class MBeanInstantiator { throw new RuntimeOperationsException(new IllegalArgumentException(), "Null className passed in parameter"); } + + ReflectUtil.checkPackageAccess(className); Class theClass; if (loaderName == null) { // Load the class using the agent class loader @@ -619,13 +630,13 @@ public class MBeanInstantiator { **/ static Class loadClass(String className, ClassLoader loader) throws ReflectionException { - Class theClass; if (className == null) { throw new RuntimeOperationsException(new IllegalArgumentException("The class name cannot be null"), "Exception occurred during object instantiation"); } + ReflectUtil.checkPackageAccess(className); try { if (loader == null) loader = MBeanInstantiator.class.getClassLoader(); @@ -676,6 +687,7 @@ public class MBeanInstantiator { // We need to load the class through the class // loader of the target object. // + ReflectUtil.checkPackageAccess(signature[i]); tab[i] = Class.forName(signature[i], false, aLoader); } } catch (ClassNotFoundException e) { @@ -701,7 +713,7 @@ public class MBeanInstantiator { private Constructor findConstructor(Class c, Class[] params) { try { - return c.getConstructor(params); + return ConstructorUtil.getConstructor(c, params); } catch (Exception e) { return null; } @@ -715,4 +727,18 @@ public class MBeanInstantiator { char.class, boolean.class}) primitiveClasses.put(c.getName(), c); } + + private static void checkMBeanPermission(Class clazz, + String member, + ObjectName objectName, + String actions) { + SecurityManager sm = System.getSecurityManager(); + if (clazz != null && sm != null) { + Permission perm = new MBeanPermission(clazz.getName(), + member, + objectName, + actions); + sm.checkPermission(perm); + } + } } diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java index 8109365e8d4..3af4b8b86d7 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java @@ -38,6 +38,7 @@ import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.management.ReflectionException; import com.sun.jmx.mbeanserver.MXBeanMappingFactory; +import sun.reflect.misc.ReflectUtil; /** * Base class for MBeans. There is one instance of this class for @@ -131,6 +132,7 @@ public abstract class MBeanSupport " is not an instance of " + mbeanInterfaceType.getName(); throw new NotCompliantMBeanException(msg); } + ReflectUtil.checkPackageAccess(mbeanInterfaceType); this.resource = resource; MBeanIntrospector introspector = getMBeanIntrospector(); this.perInterface = introspector.getPerInterface(mbeanInterfaceType); diff --git a/jdk/src/share/classes/java/lang/management/ManagementFactory.java b/jdk/src/share/classes/java/lang/management/ManagementFactory.java index d99333c9e11..278ace1d7d1 100644 --- a/jdk/src/share/classes/java/lang/management/ManagementFactory.java +++ b/jdk/src/share/classes/java/lang/management/ManagementFactory.java @@ -802,20 +802,20 @@ public class ManagementFactory { */ private static void addMXBean(final MBeanServer mbs, final PlatformManagedObject pmo) { // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean - final DynamicMBean dmbean; - if (pmo instanceof DynamicMBean) { - dmbean = DynamicMBean.class.cast(pmo); - } else if (pmo instanceof NotificationEmitter) { - dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo); - } else { - dmbean = new StandardMBean(pmo, null, true); - } - try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Void run() throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { + final DynamicMBean dmbean; + if (pmo instanceof DynamicMBean) { + dmbean = DynamicMBean.class.cast(pmo); + } else if (pmo instanceof NotificationEmitter) { + dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo); + } else { + dmbean = new StandardMBean(pmo, null, true); + } + mbs.registerMBean(dmbean, pmo.getObjectName()); return null; } diff --git a/jdk/src/share/lib/security/java.security-linux b/jdk/src/share/lib/security/java.security-linux index c37bb480eb6..8fc53d73677 100644 --- a/jdk/src/share/lib/security/java.security-linux +++ b/jdk/src/share/lib/security/java.security-linux @@ -151,8 +151,7 @@ package.access=sun.,\ com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ - com.sun.jmx.defaults.,\ - com.sun.jmx.remote.util.,\ + com.sun.jmx.,\ com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ @@ -176,8 +175,7 @@ package.definition=sun.,\ com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ - com.sun.jmx.defaults.,\ - com.sun.jmx.remote.util.,\ + com.sun.jmx.,\ com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx index ffb99c06936..5a319fa5445 100644 --- a/jdk/src/share/lib/security/java.security-macosx +++ b/jdk/src/share/lib/security/java.security-macosx @@ -152,8 +152,7 @@ package.access=sun.,\ com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ - com.sun.jmx.defaults.,\ - com.sun.jmx.remote.util.,\ + com.sun.jmx.,\ com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ @@ -178,8 +177,7 @@ package.definition=sun.,\ com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ - com.sun.jmx.defaults.,\ - com.sun.jmx.remote.util.,\ + com.sun.jmx.,\ com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index 4236643f55e..2a781cff75d 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -153,8 +153,7 @@ package.access=sun.,\ com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ - com.sun.jmx.defaults.,\ - com.sun.jmx.remote.util.,\ + com.sun.jmx.,\ com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ @@ -178,8 +177,7 @@ package.definition=sun.,\ com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ - com.sun.jmx.defaults.,\ - com.sun.jmx.remote.util.,\ + com.sun.jmx.,\ com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows index 89ec5678646..a00f4628dd6 100644 --- a/jdk/src/share/lib/security/java.security-windows +++ b/jdk/src/share/lib/security/java.security-windows @@ -152,8 +152,7 @@ package.access=sun.,\ com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ - com.sun.jmx.defaults.,\ - com.sun.jmx.remote.util.,\ + com.sun.jmx.,\ com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ @@ -177,8 +176,7 @@ package.definition=sun.,\ com.sun.xml.internal.ws.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ - com.sun.jmx.defaults.,\ - com.sun.jmx.remote.util.,\ + com.sun.jmx.,\ com.sun.proxy.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ diff --git a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java index ff56c46fbd2..d91ae14ba57 100644 --- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java +++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java @@ -119,9 +119,6 @@ public class SubjectDelegation2Test { System.out.println("Create SimpleStandard MBean"); SimpleStandard s = new SimpleStandard("monitorRole"); mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard")); - // Set Security Manager - // - System.setSecurityManager(new SecurityManager()); // Create Properties containing the username/password entries // Properties props = new Properties(); @@ -132,6 +129,9 @@ public class SubjectDelegation2Test { HashMap env = new HashMap(); env.put("jmx.remote.authenticator", new JMXPluggableAuthenticator(props)); + // Set Security Manager + // + System.setSecurityManager(new SecurityManager()); // Create an RMI connector server // System.out.println("Create an RMI connector server"); diff --git a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java index b3a004e0467..de169987796 100644 --- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java +++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java @@ -120,9 +120,6 @@ public class SubjectDelegation3Test { System.out.println("Create SimpleStandard MBean"); SimpleStandard s = new SimpleStandard("delegate"); mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard")); - // Set Security Manager - // - System.setSecurityManager(new SecurityManager()); // Create Properties containing the username/password entries // Properties props = new Properties(); @@ -133,6 +130,9 @@ public class SubjectDelegation3Test { HashMap env = new HashMap(); env.put("jmx.remote.authenticator", new JMXPluggableAuthenticator(props)); + // Set Security Manager + // + System.setSecurityManager(new SecurityManager()); // Create an RMI connector server // System.out.println("Create an RMI connector server"); From fad9c0e89cf9e887aa6f04e1055a8b6c3248e5ad Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Thu, 24 Jan 2013 16:45:38 -0800 Subject: [PATCH 036/102] 8004937: Improve proxy construction Reviewed-by: jrose, ahgross --- .../java/lang/invoke/MethodHandleNatives.java | 2 ++ .../java/lang/invoke/MethodHandleProxies.java | 25 ++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java index fcc928a327d..8f1d0c3164e 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -476,6 +476,8 @@ class MethodHandleNatives { case "getProxyClass": case "newProxyInstance": return defc == java.lang.reflect.Proxy.class; + case "asInterfaceInstance": + return defc == java.lang.invoke.MethodHandleProxies.class; case "getBundle": case "clearCache": return defc == java.util.ResourceBundle.class; diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java index b000116d875..ade1630dcfb 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -141,12 +141,15 @@ public class MethodHandleProxies { T asInterfaceInstance(final Class intfc, final MethodHandle target) { if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) throw new IllegalArgumentException("not a public interface: "+intfc.getName()); - SecurityManager smgr = System.getSecurityManager(); - if (smgr != null) { + final MethodHandle mh; + if (System.getSecurityManager() != null) { final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller final Class caller = Reflection.getCallerClass(CALLER_FRAME); - final ClassLoader ccl = caller.getClassLoader(); + final ClassLoader ccl = caller != null ? caller.getClassLoader() : null; ReflectUtil.checkProxyPackageAccess(ccl, intfc); + mh = ccl != null ? bindCaller(target, caller) : target; + } else { + mh = target; } ClassLoader proxyLoader = intfc.getClassLoader(); if (proxyLoader == null) { @@ -160,7 +163,7 @@ public class MethodHandleProxies { for (int i = 0; i < methods.length; i++) { Method sm = methods[i]; MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes()); - MethodHandle checkTarget = target.asType(smMT); // make throw WMT + MethodHandle checkTarget = mh.asType(smMT); // make throw WMT checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class)); vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount()); } @@ -183,8 +186,8 @@ public class MethodHandleProxies { } }; - Object proxy; - if (smgr != null) { + final Object proxy; + if (System.getSecurityManager() != null) { // sun.invoke.WrapperInstance is a restricted interface not accessible // by any non-null class loader. final ClassLoader loader = proxyLoader; @@ -204,6 +207,16 @@ public class MethodHandleProxies { return intfc.cast(proxy); } + private static MethodHandle bindCaller(MethodHandle target, Class hostClass) { + MethodHandle cbmh = MethodHandleImpl.bindCaller(target, hostClass); + if (target.isVarargsCollector()) { + MethodType type = cbmh.type(); + int arity = type.parameterCount(); + return cbmh.asVarargsCollector(type.parameterType(arity-1)); + } + return cbmh; + } + /** * Determines if the given object was produced by a call to {@link #asInterfaceInstance asInterfaceInstance}. * @param x any reference From a320378fac78141df43a719d067b135d9c10fca3 Mon Sep 17 00:00:00 2001 From: Edvard Wendelin Date: Mon, 28 Jan 2013 11:07:07 +0100 Subject: [PATCH 037/102] 8006864: Update java.security-linux to include changes in java.security Reviewed-by: mchung, mullan --- .../share/lib/security/java.security-linux | 28 +++++++++++++++++-- .../share/lib/security/java.security-macosx | 2 ++ .../share/lib/security/java.security-solaris | 6 ++-- .../share/lib/security/java.security-windows | 6 ++-- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/lib/security/java.security-linux b/jdk/src/share/lib/security/java.security-linux index dd63fd4d1e2..cdda1b47699 100644 --- a/jdk/src/share/lib/security/java.security-linux +++ b/jdk/src/share/lib/security/java.security-linux @@ -145,7 +145,19 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.access=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.defaults.,\ + com.sun.jmx.remote.util.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # List of comma-separated packages that start with or equal this string @@ -157,7 +169,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.definition=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.defaults.,\ + com.sun.jmx.remote.util.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx index 707f1cf21a7..515141de81b 100644 --- a/jdk/src/share/lib/security/java.security-macosx +++ b/jdk/src/share/lib/security/java.security-macosx @@ -158,6 +158,7 @@ package.access=sun.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ com.sun.org.glassfish.gmbal.,\ + jdk.internal.,\ apple. # @@ -182,6 +183,7 @@ package.definition=sun.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ com.sun.org.glassfish.gmbal.,\ + jdk.internal.,\ apple. # diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index 5f905227d5f..2cccc0d455b 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -158,7 +158,8 @@ package.access=sun.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ - com.sun.org.glassfish.gmbal. + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # List of comma-separated packages that start with or equal this string @@ -181,7 +182,8 @@ package.definition=sun.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ - com.sun.org.glassfish.gmbal. + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows index fceb1021d6d..b6281f741a1 100644 --- a/jdk/src/share/lib/security/java.security-windows +++ b/jdk/src/share/lib/security/java.security-windows @@ -157,7 +157,8 @@ package.access=sun.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ - com.sun.org.glassfish.gmbal. + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # List of comma-separated packages that start with or equal this string @@ -180,7 +181,8 @@ package.definition=sun.,\ com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.glassfish.external.,\ - com.sun.org.glassfish.gmbal. + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # Determines whether this properties file can be appended to From 9d47280d2a5e6dc576cf2314231d35ae78e96a53 Mon Sep 17 00:00:00 2001 From: Michal Frajt Date: Fri, 1 Feb 2013 17:02:36 -0800 Subject: [PATCH 038/102] 7189971: Implement CMSWaitDuration for non-incremental mode of CMS Reviewed-by: jmasa, johnc, ysr --- .../concurrentMarkSweepThread.cpp | 94 ++++++++++++++++++- .../concurrentMarkSweepThread.hpp | 6 ++ hotspot/src/share/vm/runtime/globals.hpp | 4 + 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp index c8e6e518565..7bc1c1ea949 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp @@ -300,8 +300,7 @@ void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) { } } -// Wait until the next synchronous GC, a concurrent full gc request, -// or a timeout, whichever is earlier. +// Wait until any cms_lock event void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) { MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); @@ -315,15 +314,100 @@ void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) { "Should not be set"); } +// Wait until the next synchronous GC, a concurrent full gc request, +// or a timeout, whichever is earlier. +void ConcurrentMarkSweepThread::wait_on_cms_lock_for_scavenge(long t_millis) { + // Wait time in millis or 0 value representing infinite wait for a scavenge + assert(t_millis >= 0, "Wait time for scavenge should be 0 or positive"); + + GenCollectedHeap* gch = GenCollectedHeap::heap(); + double start_time_secs = os::elapsedTime(); + double end_time_secs = start_time_secs + (t_millis / ((double) MILLIUNITS)); + + // Total collections count before waiting loop + unsigned int before_count; + { + MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag); + before_count = gch->total_collections(); + } + + unsigned int loop_count = 0; + + while(!_should_terminate) { + double now_time = os::elapsedTime(); + long wait_time_millis; + + if(t_millis != 0) { + // New wait limit + wait_time_millis = (long) ((end_time_secs - now_time) * MILLIUNITS); + if(wait_time_millis <= 0) { + // Wait time is over + break; + } + } else { + // No wait limit, wait if necessary forever + wait_time_millis = 0; + } + + // Wait until the next event or the remaining timeout + { + MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); + + if (_should_terminate || _collector->_full_gc_requested) { + return; + } + set_CMS_flag(CMS_cms_wants_token); // to provoke notifies + assert(t_millis == 0 || wait_time_millis > 0, "Sanity"); + CGC_lock->wait(Mutex::_no_safepoint_check_flag, wait_time_millis); + clear_CMS_flag(CMS_cms_wants_token); + assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), + "Should not be set"); + } + + // Extra wait time check before entering the heap lock to get the collection count + if(t_millis != 0 && os::elapsedTime() >= end_time_secs) { + // Wait time is over + break; + } + + // Total collections count after the event + unsigned int after_count; + { + MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag); + after_count = gch->total_collections(); + } + + if(before_count != after_count) { + // There was a collection - success + break; + } + + // Too many loops warning + if(++loop_count == 0) { + warning("wait_on_cms_lock_for_scavenge() has looped %u times", loop_count - 1); + } + } +} + void ConcurrentMarkSweepThread::sleepBeforeNextCycle() { while (!_should_terminate) { if (CMSIncrementalMode) { icms_wait(); + if(CMSWaitDuration >= 0) { + // Wait until the next synchronous GC, a concurrent full gc + // request or a timeout, whichever is earlier. + wait_on_cms_lock_for_scavenge(CMSWaitDuration); + } return; } else { - // Wait until the next synchronous GC, a concurrent full gc - // request or a timeout, whichever is earlier. - wait_on_cms_lock(CMSWaitDuration); + if(CMSWaitDuration >= 0) { + // Wait until the next synchronous GC, a concurrent full gc + // request or a timeout, whichever is earlier. + wait_on_cms_lock_for_scavenge(CMSWaitDuration); + } else { + // Wait until any cms_lock event or check interval not to call shouldConcurrentCollect permanently + wait_on_cms_lock(CMSCheckInterval); + } } // Check if we should start a CMS collection cycle if (_collector->shouldConcurrentCollect()) { diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp index f59ce459837..5c3f01583ad 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp @@ -130,6 +130,12 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread { // A concurrent full gc request terminates the wait. void wait_on_cms_lock(long t_millis); + // Wait on CMS lock until the next synchronous GC + // or given timeout, whichever is earlier. A timeout value + // of 0 indicates that there is no upper bound on the wait time. + // A concurrent full gc request terminates the wait. + void wait_on_cms_lock_for_scavenge(long t_millis); + // The CMS thread will yield during the work portion of its cycle // only when requested to. Both synchronous and asychronous requests // are provided: diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 8a0be8f8a4f..ef41b35090b 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1751,6 +1751,10 @@ class CommandLineFlags { manageable(intx, CMSWaitDuration, 2000, \ "Time in milliseconds that CMS thread waits for young GC") \ \ + develop(uintx, CMSCheckInterval, 1000, \ + "Interval in milliseconds that CMS thread checks if it " \ + "should start a collection cycle") \ + \ product(bool, CMSYield, true, \ "Yield between steps of concurrent mark & sweep") \ \ From e84e88f4c9b8375be1764a2d59e2cf2556b3c0a2 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Tue, 5 Feb 2013 22:56:47 -0800 Subject: [PATCH 039/102] 8007393: Possible race condition after JDK-6664509 Reviewed-by: alanb, jgish --- .../classes/java/util/logging/LogManager.java | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/jdk/src/share/classes/java/util/logging/LogManager.java b/jdk/src/share/classes/java/util/logging/LogManager.java index 58bd1ba7ead..55b2f206e76 100644 --- a/jdk/src/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/share/classes/java/util/logging/LogManager.java @@ -455,7 +455,40 @@ public class LogManager { } Logger demandSystemLogger(String name, String resourceBundleName) { - return systemContext.demandLogger(name, resourceBundleName); + // Add a system logger in the system context's namespace + final Logger sysLogger = systemContext.demandLogger(name, resourceBundleName); + + // Add the system logger to the LogManager's namespace if not exist + // so that there is only one single logger of the given name. + // System loggers are visible to applications unless a logger of + // the same name has been added. + Logger logger; + do { + // First attempt to call addLogger instead of getLogger + // This would avoid potential bug in custom LogManager.getLogger + // implementation that adds a logger if does not exist + if (addLogger(sysLogger)) { + // successfully added the new system logger + logger = sysLogger; + } else { + logger = getLogger(name); + } + } while (logger == null); + + // LogManager will set the sysLogger's handlers via LogManager.addLogger method. + if (logger != sysLogger && sysLogger.getHandlers().length == 0) { + // if logger already exists but handlers not set + final Logger l = logger; + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + for (Handler hdl : l.getHandlers()) { + sysLogger.addHandler(hdl); + } + return null; + } + }); + } + return sysLogger; } // LoggerContext maintains the logger namespace per context. @@ -663,21 +696,6 @@ public class LogManager { } } while (result == null); } - // Add the system logger to the LogManager's namespace if not exists - // The LogManager will set its handlers via the LogManager.addLogger method. - if (!manager.addLogger(result) && result.getHandlers().length == 0) { - // if logger already exists but handlers not set - final Logger l = manager.getLogger(name); - final Logger logger = result; - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - for (Handler hdl : l.getHandlers()) { - logger.addHandler(hdl); - } - return null; - } - }); - } return result; } } From 3479e4412ab65b5c582060e502348c7d81a69b0a Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Thu, 7 Feb 2013 09:41:47 -0800 Subject: [PATCH 040/102] 8007611: logging behavior in applet changed Reviewed-by: alanb, jgish --- jdk/src/share/classes/java/util/logging/LogManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/util/logging/LogManager.java b/jdk/src/share/classes/java/util/logging/LogManager.java index 55b2f206e76..40537d2e46e 100644 --- a/jdk/src/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/share/classes/java/util/logging/LogManager.java @@ -395,7 +395,10 @@ public class LogManager { context = userContext; } else { context = new LoggerContext(); - context.addLocalLogger(manager.rootLogger); + // during initialization, rootLogger is null when + // instantiating itself RootLogger + if (manager.rootLogger != null) + context.addLocalLogger(manager.rootLogger); } javaAwtAccess.put(ecx, LoggerContext.class, context); } From e1d6f09bba5aa4bffb1ce6d2ca0b0ebc39166ed9 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Thu, 7 Feb 2013 16:05:55 -0800 Subject: [PATCH 041/102] 8006777: Improve TLS handling of invalid messages Reviewed-by: wetmore, ahgross --- .../classes/sun/security/ssl/CipherBox.java | 202 ++++++++++++---- .../classes/sun/security/ssl/CipherSuite.java | 23 +- .../sun/security/ssl/EngineInputRecord.java | 220 ++++++++++++------ .../sun/security/ssl/EngineOutputRecord.java | 4 +- .../classes/sun/security/ssl/InputRecord.java | 184 ++++++++++++--- .../share/classes/sun/security/ssl/MAC.java | 51 ++-- .../sun/security/ssl/OutputRecord.java | 4 +- .../sun/security/ssl/SSLEngineImpl.java | 26 +-- .../sun/security/ssl/SSLSocketImpl.java | 22 +- 9 files changed, 527 insertions(+), 209 deletions(-) diff --git a/jdk/src/share/classes/sun/security/ssl/CipherBox.java b/jdk/src/share/classes/sun/security/ssl/CipherBox.java index 362f9b5d904..52bb7d95863 100644 --- a/jdk/src/share/classes/sun/security/ssl/CipherBox.java +++ b/jdk/src/share/classes/sun/security/ssl/CipherBox.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -392,7 +392,8 @@ final class CipherBox { * uniformly use the bad_record_mac alert to hide the specific type of * the error. */ - int decrypt(byte[] buf, int offset, int len) throws BadPaddingException { + int decrypt(byte[] buf, int offset, int len, + int tagLen) throws BadPaddingException { if (cipher == null) { return len; } @@ -416,9 +417,10 @@ final class CipherBox { System.out); } catch (IOException e) { } } + if (blockSize != 0) { - newLen = removePadding(buf, offset, newLen, - blockSize, protocolVersion); + newLen = removePadding( + buf, offset, newLen, tagLen, blockSize, protocolVersion); if (protocolVersion.v >= ProtocolVersion.TLS11.v) { if (newLen < blockSize) { @@ -448,7 +450,7 @@ final class CipherBox { * * @see decrypt(byte[], int, int) */ - int decrypt(ByteBuffer bb) throws BadPaddingException { + int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException { int len = bb.remaining(); @@ -471,7 +473,6 @@ final class CipherBox { } if (debug != null && Debug.isOn("plaintext")) { - bb.position(pos); try { HexDumpEncoder hd = new HexDumpEncoder(); @@ -479,7 +480,8 @@ final class CipherBox { "Padded plaintext after DECRYPTION: len = " + newLen); - hd.encodeBuffer(bb, System.out); + hd.encodeBuffer( + (ByteBuffer)bb.duplicate().position(pos), System.out); } catch (IOException e) { } } @@ -488,7 +490,8 @@ final class CipherBox { */ if (blockSize != 0) { bb.position(pos); - newLen = removePadding(bb, blockSize, protocolVersion); + newLen = removePadding( + bb, tagLen, blockSize, protocolVersion); if (protocolVersion.v >= ProtocolVersion.TLS11.v) { if (newLen < blockSize) { @@ -590,6 +593,65 @@ final class CipherBox { return newlen; } + /* + * A constant-time check of the padding. + * + * NOTE that we are checking both the padding and the padLen bytes here. + * + * The caller MUST ensure that the len parameter is a positive number. + */ + private static int[] checkPadding( + byte[] buf, int offset, int len, byte pad) { + + if (len <= 0) { + throw new RuntimeException("padding len must be positive"); + } + + // An array of hits is used to prevent Hotspot optimization for + // the purpose of a constant-time check. + int[] results = {0, 0}; // {missed #, matched #} + for (int i = 0; i <= 256;) { + for (int j = 0; j < len && i <= 256; j++, i++) { // j <= i + if (buf[offset + j] != pad) { + results[0]++; // mismatched padding data + } else { + results[1]++; // matched padding data + } + } + } + + return results; + } + + /* + * A constant-time check of the padding. + * + * NOTE that we are checking both the padding and the padLen bytes here. + * + * The caller MUST ensure that the bb parameter has remaining. + */ + private static int[] checkPadding(ByteBuffer bb, byte pad) { + + if (!bb.hasRemaining()) { + throw new RuntimeException("hasRemaining() must be positive"); + } + + // An array of hits is used to prevent Hotspot optimization for + // the purpose of a constant-time check. + int[] results = {0, 0}; // {missed #, matched #} + bb.mark(); + for (int i = 0; i <= 256; bb.reset()) { + for (; bb.hasRemaining() && i <= 256; i++) { + if (bb.get() != pad) { + results[0]++; // mismatched padding data + } else { + results[1]++; // matched padding data + } + } + } + + return results; + } /* * Typical TLS padding format for a 64 bit block cipher is as follows: @@ -602,86 +664,95 @@ final class CipherBox { * as it makes the data a multiple of the block size */ private static int removePadding(byte[] buf, int offset, int len, - int blockSize, ProtocolVersion protocolVersion) - throws BadPaddingException { + int tagLen, int blockSize, + ProtocolVersion protocolVersion) throws BadPaddingException { + // last byte is length byte (i.e. actual padding length - 1) int padOffset = offset + len - 1; - int pad = buf[padOffset] & 0x0ff; + int padLen = buf[padOffset] & 0xFF; - int newlen = len - (pad + 1); - if (newlen < 0) { - throw new BadPaddingException("Padding length invalid: " + pad); + int newLen = len - (padLen + 1); + if ((newLen - tagLen) < 0) { + // If the buffer is not long enough to contain the padding plus + // a MAC tag, do a dummy constant-time padding check. + // + // Note that it is a dummy check, so we won't care about what is + // the actual padding data. + checkPadding(buf, offset, len, (byte)(padLen & 0xFF)); + + throw new BadPaddingException("Invalid Padding length: " + padLen); } + // The padding data should be filled with the padding length value. + int[] results = checkPadding(buf, offset + newLen, + padLen + 1, (byte)(padLen & 0xFF)); if (protocolVersion.v >= ProtocolVersion.TLS10.v) { - for (int i = 1; i <= pad; i++) { - int val = buf[padOffset - i] & 0xff; - if (val != pad) { - throw new BadPaddingException - ("Invalid TLS padding: " + val); - } + if (results[0] != 0) { // padding data has invalid bytes + throw new BadPaddingException("Invalid TLS padding data"); } } else { // SSLv3 // SSLv3 requires 0 <= length byte < block size // some implementations do 1 <= length byte <= block size, // so accept that as well // v3 does not require any particular value for the other bytes - if (pad > blockSize) { - throw new BadPaddingException("Invalid SSLv3 padding: " + pad); + if (padLen > blockSize) { + throw new BadPaddingException("Invalid SSLv3 padding"); } } - return newlen; + return newLen; } /* * Position/limit is equal the removed padding. */ private static int removePadding(ByteBuffer bb, - int blockSize, ProtocolVersion protocolVersion) - throws BadPaddingException { + int tagLen, int blockSize, + ProtocolVersion protocolVersion) throws BadPaddingException { int len = bb.remaining(); int offset = bb.position(); // last byte is length byte (i.e. actual padding length - 1) int padOffset = offset + len - 1; - int pad = bb.get(padOffset) & 0x0ff; + int padLen = bb.get(padOffset) & 0xFF; - int newlen = len - (pad + 1); - if (newlen < 0) { - throw new BadPaddingException("Padding length invalid: " + pad); + int newLen = len - (padLen + 1); + if ((newLen - tagLen) < 0) { + // If the buffer is not long enough to contain the padding plus + // a MAC tag, do a dummy constant-time padding check. + // + // Note that it is a dummy check, so we won't care about what is + // the actual padding data. + checkPadding(bb.duplicate(), (byte)(padLen & 0xFF)); + + throw new BadPaddingException("Invalid Padding length: " + padLen); } - /* - * We could zero the padding area, but not much useful - * information there. - */ + // The padding data should be filled with the padding length value. + int[] results = checkPadding( + (ByteBuffer)bb.duplicate().position(offset + newLen), + (byte)(padLen & 0xFF)); if (protocolVersion.v >= ProtocolVersion.TLS10.v) { - bb.put(padOffset, (byte)0); // zero the padding. - for (int i = 1; i <= pad; i++) { - int val = bb.get(padOffset - i) & 0xff; - if (val != pad) { - throw new BadPaddingException - ("Invalid TLS padding: " + val); - } + if (results[0] != 0) { // padding data has invalid bytes + throw new BadPaddingException("Invalid TLS padding data"); } } else { // SSLv3 // SSLv3 requires 0 <= length byte < block size // some implementations do 1 <= length byte <= block size, // so accept that as well // v3 does not require any particular value for the other bytes - if (pad > blockSize) { - throw new BadPaddingException("Invalid SSLv3 padding: " + pad); + if (padLen > blockSize) { + throw new BadPaddingException("Invalid SSLv3 padding"); } } /* * Reset buffer limit to remove padding. */ - bb.position(offset + newlen); - bb.limit(offset + newlen); + bb.position(offset + newLen); + bb.limit(offset + newLen); - return newlen; + return newLen; } /* @@ -708,4 +779,45 @@ final class CipherBox { boolean isCBCMode() { return isCBCMode; } + + /** + * Is the cipher null? + * + * @return true if the cipher is null, false otherwise. + */ + boolean isNullCipher() { + return cipher == null; + } + + /** + * Sanity check the length of a fragment before decryption. + * + * In CBC mode, check that the fragment length is one or multiple times + * of the block size of the cipher suite, and is at least one (one is the + * smallest size of padding in CBC mode) bigger than the tag size of the + * MAC algorithm except the explicit IV size for TLS 1.1 or later. + * + * In non-CBC mode, check that the fragment length is not less than the + * tag size of the MAC algorithm. + * + * @return true if the length of a fragment matches above requirements + */ + boolean sanityCheck(int tagLen, int fragmentLen) { + if (!isCBCMode) { + return fragmentLen >= tagLen; + } + + if ((fragmentLen % blockSize) == 0) { + int minimal = tagLen + 1; + minimal = (minimal >= blockSize) ? minimal : blockSize; + if (protocolVersion.v >= ProtocolVersion.TLS11.v) { + minimal += blockSize; // plus the size of the explicit IV + } + + return (fragmentLen >= minimal); + } + + return false; + } + } diff --git a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java index 555304880b7..e0a081ad85d 100644 --- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java +++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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 @@ -549,9 +549,18 @@ final class CipherSuite implements Comparable { // size of the MAC value (and MAC key) in bytes final int size; - MacAlg(String name, int size) { + // block size of the underlying hash algorithm + final int hashBlockSize; + + // minimal padding size of the underlying hash algorithm + final int minimalPaddingSize; + + MacAlg(String name, int size, + int hashBlockSize, int minimalPaddingSize) { this.name = name; this.size = size; + this.hashBlockSize = hashBlockSize; + this.minimalPaddingSize = minimalPaddingSize; } /** @@ -596,11 +605,11 @@ final class CipherSuite implements Comparable { new BulkCipher(CIPHER_AES, 32, 16, true); // MACs - final static MacAlg M_NULL = new MacAlg("NULL", 0); - final static MacAlg M_MD5 = new MacAlg("MD5", 16); - final static MacAlg M_SHA = new MacAlg("SHA", 20); - final static MacAlg M_SHA256 = new MacAlg("SHA256", 32); - final static MacAlg M_SHA384 = new MacAlg("SHA384", 48); + final static MacAlg M_NULL = new MacAlg("NULL", 0, 0, 0); + final static MacAlg M_MD5 = new MacAlg("MD5", 16, 64, 9); + final static MacAlg M_SHA = new MacAlg("SHA", 20, 64, 9); + final static MacAlg M_SHA256 = new MacAlg("SHA256", 32, 64, 9); + final static MacAlg M_SHA384 = new MacAlg("SHA384", 48, 128, 17); /** * PRFs (PseudoRandom Function) from TLS specifications. diff --git a/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java b/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java index 6b064385203..9161d6de8ef 100644 --- a/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java +++ b/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -177,71 +177,6 @@ final class EngineInputRecord extends InputRecord { return len; } - /* - * Verifies and removes the MAC value. Returns true if - * the MAC checks out OK. - * - * On entry: - * position = beginning of app/MAC data - * limit = end of MAC data. - * - * On return: - * position = beginning of app data - * limit = end of app data - */ - boolean checkMAC(MAC signer, ByteBuffer bb) { - if (internalData) { - return checkMAC(signer); - } - - int len = signer.MAClen(); - if (len == 0) { // no mac - return true; - } - - /* - * Grab the original limit - */ - int lim = bb.limit(); - - /* - * Delineate the area to apply a MAC on. - */ - int macData = lim - len; - bb.limit(macData); - - byte[] mac = signer.compute(contentType(), bb); - - if (len != mac.length) { - throw new RuntimeException("Internal MAC error"); - } - - /* - * Delineate the MAC values, position was already set - * by doing the compute above. - * - * We could zero the MAC area, but not much useful information - * there anyway. - */ - bb.position(macData); - bb.limit(lim); - - try { - for (int i = 0; i < len; i++) { - if (bb.get() != mac[i]) { // No BB.equals(byte []); ! - return false; - } - } - return true; - } finally { - /* - * Position to the data. - */ - bb.rewind(); - bb.limit(macData); - } - } - /* * Pass the data down if it's internally cached, otherwise * do it here. @@ -251,20 +186,163 @@ final class EngineInputRecord extends InputRecord { * If external data(app), return a new ByteBuffer with data to * process. */ - ByteBuffer decrypt(CipherBox box, ByteBuffer bb) - throws BadPaddingException { + ByteBuffer decrypt(MAC signer, + CipherBox box, ByteBuffer bb) throws BadPaddingException { if (internalData) { - decrypt(box); + decrypt(signer, box); // MAC is checked during decryption return tmpBB; } - box.decrypt(bb); - bb.rewind(); + BadPaddingException reservedBPE = null; + int tagLen = signer.MAClen(); + int cipheredLength = bb.remaining(); + + if (!box.isNullCipher()) { + // sanity check length of the ciphertext + if (!box.sanityCheck(tagLen, cipheredLength)) { + throw new BadPaddingException( + "ciphertext sanity check failed"); + } + + try { + // Note that the CipherBox.decrypt() does not change + // the capacity of the buffer. + box.decrypt(bb, tagLen); + } catch (BadPaddingException bpe) { + // RFC 2246 states that decryption_failed should be used + // for this purpose. However, that allows certain attacks, + // so we just send bad record MAC. We also need to make + // sure to always check the MAC to avoid a timing attack + // for the same issue. See paper by Vaudenay et al and the + // update in RFC 4346/5246. + // + // Failover to message authentication code checking. + reservedBPE = bpe; + } finally { + bb.rewind(); + } + } + + if (tagLen != 0) { + int macOffset = bb.limit() - tagLen; + + // Note that although it is not necessary, we run the same MAC + // computation and comparison on the payload for both stream + // cipher and CBC block cipher. + if (bb.remaining() < tagLen) { + // negative data length, something is wrong + if (reservedBPE == null) { + reservedBPE = new BadPaddingException("bad record"); + } + + // set offset of the dummy MAC + macOffset = cipheredLength - tagLen; + bb.limit(cipheredLength); + } + + // Run MAC computation and comparison on the payload. + if (checkMacTags(contentType(), bb, signer, false)) { + if (reservedBPE == null) { + reservedBPE = new BadPaddingException("bad record MAC"); + } + } + + // Run MAC computation and comparison on the remainder. + // + // It is only necessary for CBC block cipher. It is used to get a + // constant time of MAC computation and comparison on each record. + if (box.isCBCMode()) { + int remainingLen = calculateRemainingLen( + signer, cipheredLength, macOffset); + + // NOTE: here we use the InputRecord.buf because I did not find + // an effective way to work on ByteBuffer when its capacity is + // less than remainingLen. + + // NOTE: remainingLen may be bigger (less than 1 block of the + // hash algorithm of the MAC) than the cipheredLength. However, + // We won't need to worry about it because we always use a + // maximum buffer for every record. We need a change here if + // we use small buffer size in the future. + if (remainingLen > buf.length) { + // unlikely to happen, just a placehold + throw new RuntimeException( + "Internal buffer capacity error"); + } + + // Won't need to worry about the result on the remainder. And + // then we won't need to worry about what's actual data to + // check MAC tag on. We start the check from the header of the + // buffer so that we don't need to construct a new byte buffer. + checkMacTags(contentType(), buf, 0, remainingLen, signer, true); + } + + bb.limit(macOffset); + } + + // Is it a failover? + if (reservedBPE != null) { + throw reservedBPE; + } return bb.slice(); } + /* + * Run MAC computation and comparison + * + * Please DON'T change the content of the ByteBuffer parameter! + */ + private static boolean checkMacTags(byte contentType, ByteBuffer bb, + MAC signer, boolean isSimulated) { + + int tagLen = signer.MAClen(); + int lim = bb.limit(); + int macData = lim - tagLen; + + bb.limit(macData); + byte[] hash = signer.compute(contentType, bb, isSimulated); + if (hash == null || tagLen != hash.length) { + // Something is wrong with MAC implementation. + throw new RuntimeException("Internal MAC error"); + } + + bb.position(macData); + bb.limit(lim); + try { + int[] results = compareMacTags(bb, hash); + return (results[0] != 0); + } finally { + bb.rewind(); + bb.limit(macData); + } + } + + /* + * A constant-time comparison of the MAC tags. + * + * Please DON'T change the content of the ByteBuffer parameter! + */ + private static int[] compareMacTags(ByteBuffer bb, byte[] tag) { + + // An array of hits is used to prevent Hotspot optimization for + // the purpose of a constant-time check. + int[] results = {0, 0}; // {missed #, matched #} + + // The caller ensures there are enough bytes available in the buffer. + // So we won't need to check the remaining of the buffer. + for (int i = 0; i < tag.length; i++) { + if (bb.get() != tag[i]) { + results[0]++; // mismatched bytes + } else { + results[1]++; // matched bytes + } + } + + return results; + } + /* * Override the actual write below. We do things this way to be * consistent with InputRecord. InputRecord may try to write out diff --git a/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java b/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java index e9d39805b36..ae414c115f2 100644 --- a/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java +++ b/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -118,7 +118,7 @@ final class EngineOutputRecord extends OutputRecord { throws IOException { if (signer.MAClen() != 0) { - byte[] hash = signer.compute(contentType(), bb); + byte[] hash = signer.compute(contentType(), bb, false); /* * position was advanced to limit in compute above. diff --git a/jdk/src/share/classes/sun/security/ssl/InputRecord.java b/jdk/src/share/classes/sun/security/ssl/InputRecord.java index 78e866a07ca..45fdc62dd21 100644 --- a/jdk/src/share/classes/sun/security/ssl/InputRecord.java +++ b/jdk/src/share/classes/sun/security/ssl/InputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -133,43 +133,173 @@ class InputRecord extends ByteArrayInputStream implements Record { return handshakeHash; } + void decrypt(MAC signer, CipherBox box) throws BadPaddingException { + + BadPaddingException reservedBPE = null; + int tagLen = signer.MAClen(); + int cipheredLength = count - headerSize; + + if (!box.isNullCipher()) { + // sanity check length of the ciphertext + if (!box.sanityCheck(tagLen, cipheredLength)) { + throw new BadPaddingException( + "ciphertext sanity check failed"); + } + + try { + // Note that the CipherBox.decrypt() does not change + // the capacity of the buffer. + count = headerSize + + box.decrypt(buf, headerSize, cipheredLength, tagLen); + } catch (BadPaddingException bpe) { + // RFC 2246 states that decryption_failed should be used + // for this purpose. However, that allows certain attacks, + // so we just send bad record MAC. We also need to make + // sure to always check the MAC to avoid a timing attack + // for the same issue. See paper by Vaudenay et al and the + // update in RFC 4346/5246. + // + // Failover to message authentication code checking. + reservedBPE = bpe; + } + } + + if (tagLen != 0) { + int macOffset = count - tagLen; + int contentLen = macOffset - headerSize; + + // Note that although it is not necessary, we run the same MAC + // computation and comparison on the payload for both stream + // cipher and CBC block cipher. + if (contentLen < 0) { + // negative data length, something is wrong + if (reservedBPE == null) { + reservedBPE = new BadPaddingException("bad record"); + } + + // set offset of the dummy MAC + macOffset = headerSize + cipheredLength - tagLen; + contentLen = macOffset - headerSize; + } + + count -= tagLen; // Set the count before any MAC checking + // exception occurs, so that the following + // process can read the actual decrypted + // content (minus the MAC) in the fragment + // if necessary. + + // Run MAC computation and comparison on the payload. + if (checkMacTags(contentType(), + buf, headerSize, contentLen, signer, false)) { + if (reservedBPE == null) { + reservedBPE = new BadPaddingException("bad record MAC"); + } + } + + // Run MAC computation and comparison on the remainder. + // + // It is only necessary for CBC block cipher. It is used to get a + // constant time of MAC computation and comparison on each record. + if (box.isCBCMode()) { + int remainingLen = calculateRemainingLen( + signer, cipheredLength, contentLen); + + // NOTE: remainingLen may be bigger (less than 1 block of the + // hash algorithm of the MAC) than the cipheredLength. However, + // We won't need to worry about it because we always use a + // maximum buffer for every record. We need a change here if + // we use small buffer size in the future. + if (remainingLen > buf.length) { + // unlikely to happen, just a placehold + throw new RuntimeException( + "Internal buffer capacity error"); + } + + // Won't need to worry about the result on the remainder. And + // then we won't need to worry about what's actual data to + // check MAC tag on. We start the check from the header of the + // buffer so that we don't need to construct a new byte buffer. + checkMacTags(contentType(), buf, 0, remainingLen, signer, true); + } + } + + // Is it a failover? + if (reservedBPE != null) { + throw reservedBPE; + } + } + /* - * Verify and remove the MAC ... used for all records. + * Run MAC computation and comparison + * + * Please DON'T change the content of the byte buffer parameter! */ - boolean checkMAC(MAC signer) { - int len = signer.MAClen(); - if (len == 0) { // no mac - return true; - } + static boolean checkMacTags(byte contentType, byte[] buffer, + int offset, int contentLen, MAC signer, boolean isSimulated) { - int offset = count - len; - - if (offset < headerSize) { - // data length would be negative, something is wrong - return false; - } - - byte[] mac = signer.compute(contentType(), buf, - headerSize, offset - headerSize); - - if (len != mac.length) { + int tagLen = signer.MAClen(); + byte[] hash = signer.compute( + contentType, buffer, offset, contentLen, isSimulated); + if (hash == null || tagLen != hash.length) { + // Something is wrong with MAC implementation. throw new RuntimeException("Internal MAC error"); } - for (int i = 0; i < len; i++) { - if (buf[offset + i] != mac[i]) { - return false; + int[] results = compareMacTags(buffer, offset + contentLen, hash); + return (results[0] != 0); + } + + /* + * A constant-time comparison of the MAC tags. + * + * Please DON'T change the content of the byte buffer parameter! + */ + private static int[] compareMacTags( + byte[] buffer, int offset, byte[] tag) { + + // An array of hits is used to prevent Hotspot optimization for + // the purpose of a constant-time check. + int[] results = {0, 0}; // {missed #, matched #} + + // The caller ensures there are enough bytes available in the buffer. + // So we won't need to check the length of the buffer. + for (int i = 0; i < tag.length; i++) { + if (buffer[offset + i] != tag[i]) { + results[0]++; // mismatched bytes + } else { + results[1]++; // matched bytes } } - count -= len; - return true; + + return results; } - void decrypt(CipherBox box) throws BadPaddingException { - int len = count - headerSize; - count = headerSize + box.decrypt(buf, headerSize, len); - } + /* + * Calculate the length of a dummy buffer to run MAC computation + * and comparison on the remainder. + * + * The caller MUST ensure that the fullLen is not less than usedLen. + */ + static int calculateRemainingLen( + MAC signer, int fullLen, int usedLen) { + int blockLen = signer.hashBlockLen(); + int minimalPaddingLen = signer.minimalPaddingLen(); + + // (blockLen - minimalPaddingLen) is the maximum message size of + // the last block of hash function operation. See FIPS 180-4, or + // MD5 specification. + fullLen += 13 - (blockLen - minimalPaddingLen); + usedLen += 13 - (blockLen - minimalPaddingLen); + + // Note: fullLen is always not less than usedLen, and blockLen + // is always bigger than minimalPaddingLen, so we don't worry + // about negative values. 0x01 is added to the result to ensure + // that the return value is positive. The extra one byte does + // not impact the overall MAC compression function evaluations. + return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) - + Math.ceil(usedLen/(1.0d * blockLen))) * signer.hashBlockLen(); + } /* * Well ... hello_request messages are _never_ hashed since we can't diff --git a/jdk/src/share/classes/sun/security/ssl/MAC.java b/jdk/src/share/classes/sun/security/ssl/MAC.java index 753a8c57ac4..e491cc301da 100644 --- a/jdk/src/share/classes/sun/security/ssl/MAC.java +++ b/jdk/src/share/classes/sun/security/ssl/MAC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -43,8 +43,8 @@ import static sun.security.ssl.CipherSuite.*; * provide integrity protection for SSL messages. The MAC is actually * one of several keyed hashes, as associated with the cipher suite and * protocol version. (SSL v3.0 uses one construct, TLS uses another.) - * - *

    NOTE: MAC computation is the only place in the SSL protocol that the + *

    + * NOTE: MAC computation is the only place in the SSL protocol that the * sequence number is used. It's also reset to zero with each change of * a cipher spec, so this is the only place this state is needed. * @@ -58,6 +58,9 @@ final class MAC { // Value of the null MAC is fixed private static final byte nullMAC[] = new byte[0]; + // internal identifier for the MAC algorithm + private final MacAlg macAlg; + // stuff defined by the kind of MAC algorithm private final int macSize; @@ -82,6 +85,7 @@ final class MAC { private MAC() { macSize = 0; + macAlg = M_NULL; mac = null; block = null; } @@ -91,6 +95,7 @@ final class MAC { */ MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key) throws NoSuchAlgorithmException, InvalidKeyException { + this.macAlg = macAlg; this.macSize = macAlg.size; String algorithm; @@ -127,6 +132,20 @@ final class MAC { return macSize; } + /** + * Returns the hash function block length of the MAC alorithm. + */ + int hashBlockLen() { + return macAlg.hashBlockSize; + } + + /** + * Returns the hash function minimal padding length of the MAC alorithm. + */ + int minimalPaddingLen() { + return macAlg.minimalPaddingSize; + } + /** * Computes and returns the MAC for the data in this byte array. * @@ -134,9 +153,11 @@ final class MAC { * @param buf compressed record on which the MAC is computed * @param offset start of compressed record data * @param len the size of the compressed record + * @param isSimulated if true, simulate the the MAC computation */ - final byte[] compute(byte type, byte buf[], int offset, int len) { - return compute(type, null, buf, offset, len); + final byte[] compute(byte type, byte buf[], + int offset, int len, boolean isSimulated) { + return compute(type, null, buf, offset, len, isSimulated); } /** @@ -149,9 +170,10 @@ final class MAC { * @param type record type * @param bb a ByteBuffer in which the position and limit * demarcate the data to be MAC'd. + * @param isSimulated if true, simulate the the MAC computation */ - final byte[] compute(byte type, ByteBuffer bb) { - return compute(type, bb, null, 0, bb.remaining()); + final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) { + return compute(type, bb, null, 0, bb.remaining(), isSimulated); } /** @@ -204,18 +226,21 @@ final class MAC { * or buf/offset/len. */ private byte[] compute(byte type, ByteBuffer bb, byte[] buf, - int offset, int len) { + int offset, int len, boolean isSimulated) { if (macSize == 0) { return nullMAC; } - block[BLOCK_OFFSET_TYPE] = type; - block[block.length - 2] = (byte)(len >> 8); - block[block.length - 1] = (byte)(len ); + // MUST NOT increase the sequence number for a simulated computation. + if (!isSimulated) { + block[BLOCK_OFFSET_TYPE] = type; + block[block.length - 2] = (byte)(len >> 8); + block[block.length - 1] = (byte)(len ); - mac.update(block); - incrementSequenceNumber(); + mac.update(block); + incrementSequenceNumber(); + } // content if (bb != null) { diff --git a/jdk/src/share/classes/sun/security/ssl/OutputRecord.java b/jdk/src/share/classes/sun/security/ssl/OutputRecord.java index 900003dfd0f..0ff27be460d 100644 --- a/jdk/src/share/classes/sun/security/ssl/OutputRecord.java +++ b/jdk/src/share/classes/sun/security/ssl/OutputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -205,7 +205,7 @@ class OutputRecord extends ByteArrayOutputStream implements Record { } if (signer.MAClen() != 0) { byte[] hash = signer.compute(contentType, buf, - headerSize, count - headerSize); + headerSize, count - headerSize, false); write(hash); } } diff --git a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java index 41415337ca1..5534cab0384 100644 --- a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -958,35 +958,15 @@ final public class SSLEngineImpl extends SSLEngine { * throw a fatal alert if the integrity check fails. */ try { - decryptedBB = inputRecord.decrypt(readCipher, readBB); + decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB); } catch (BadPaddingException e) { - // RFC 2246 states that decryption_failed should be used - // for this purpose. However, that allows certain attacks, - // so we just send bad record MAC. We also need to make - // sure to always check the MAC to avoid a timing attack - // for the same issue. See paper by Vaudenay et al. - // - // rewind the BB if necessary. - readBB.rewind(); - - inputRecord.checkMAC(readMAC, readBB); - - // use the same alert types as for MAC failure below byte alertType = (inputRecord.contentType() == Record.ct_handshake) ? Alerts.alert_handshake_failure : Alerts.alert_bad_record_mac; - fatal(alertType, "Invalid padding", e); + fatal(alertType, e.getMessage(), e); } - if (!inputRecord.checkMAC(readMAC, decryptedBB)) { - if (inputRecord.contentType() == Record.ct_handshake) { - fatal(Alerts.alert_handshake_failure, - "bad handshake record MAC"); - } else { - fatal(Alerts.alert_bad_record_mac, "bad record MAC"); - } - } // if (!inputRecord.decompress(c)) // fatal(Alerts.alert_decompression_failure, diff --git a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java index f807c4c58ce..cbc3db69b96 100644 --- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -986,29 +986,13 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { * throw a fatal alert if the integrity check fails. */ try { - r.decrypt(readCipher); + r.decrypt(readMAC, readCipher); } catch (BadPaddingException e) { - // RFC 2246 states that decryption_failed should be used - // for this purpose. However, that allows certain attacks, - // so we just send bad record MAC. We also need to make - // sure to always check the MAC to avoid a timing attack - // for the same issue. See paper by Vaudenay et al. - r.checkMAC(readMAC); - // use the same alert types as for MAC failure below byte alertType = (r.contentType() == Record.ct_handshake) ? Alerts.alert_handshake_failure : Alerts.alert_bad_record_mac; - fatal(alertType, "Invalid padding", e); + fatal(alertType, e.getMessage(), e); } - if (!r.checkMAC(readMAC)) { - if (r.contentType() == Record.ct_handshake) { - fatal(Alerts.alert_handshake_failure, - "bad handshake record MAC"); - } else { - fatal(Alerts.alert_bad_record_mac, "bad record MAC"); - } - } - // if (!r.decompress(c)) // fatal(Alerts.alert_decompression_failure, From 3ae3ac4f875af338d660b8d9f5998e5c327827b9 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Thu, 7 Feb 2013 16:03:43 -0800 Subject: [PATCH 042/102] 8007688: Blacklist known bad certificate Added two known bad certs to the blacklist certs. Reviewed-by: mullan --- .../security/util/UntrustedCertificates.java | 108 +++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java b/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java index 6aad34a73a4..03fdbc78332 100644 --- a/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java +++ b/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -737,5 +737,111 @@ public final class UntrustedCertificates { "B8WfedLHjFW/TMcnXlEWKz4=\n" + "-----END CERTIFICATE-----"); + // + // Revoked DigiCert code signing certificates used to sign malware + // + + // Subject: CN=Buster Paper Comercial Ltda, + // O=Buster Paper Comercial Ltda, + // L=S?o Jos? Dos Campos, + // ST=S?o Paulo, + // C=BR + // Issuer: CN=DigiCert Assured ID Code Signing CA-1, + // OU=www.digicert.com, + // O=DigiCert Inc, + // C=US + // Serial: 07:b4:4c:db:ff:fb:78:de:05:f4:26:16:72:a6:73:12 + add("buster-paper-comercial-ltda-72A67312", + "-----BEGIN CERTIFICATE-----\n" + + "MIIGwzCCBaugAwIBAgIQB7RM2//7eN4F9CYWcqZzEjANBgkqhkiG9w0BAQUFADBv\n" + + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + + "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + + "ZGUgU2lnbmluZyBDQS0xMB4XDTEzMDExNzAwMDAwMFoXDTE0MDEyMjEyMDAwMFow\n" + + "gY4xCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMR4wHAYDVQQHDBVT\n" + + "w6NvIEpvc8OpIERvcyBDYW1wb3MxJDAiBgNVBAoTG0J1c3RlciBQYXBlciBDb21l\n" + + "cmNpYWwgTHRkYTEkMCIGA1UEAxMbQnVzdGVyIFBhcGVyIENvbWVyY2lhbCBMdGRh\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzO0l6jWIpEfO2oUpVHpL\n" + + "HETj5lzivNb0S9jKHgGJax917czh81PnGTxwxFXd6gLJuy/XFHvmiSi8g8jzlymn\n" + + "2Ji5zQ3CPaz7nomJokSUDlMVJ2qYWtctw4jrdjuI4qtn+koXXUFkWjkf8h8251I4\n" + + "tUs7S49HE2Go5owCYP3byajj7fsFAYR/Xb7TdVtndkZsUB/YgOjHovyACjouaNCi\n" + + "mDiRyQ6zLLjZGiyeD65Yiseuhp5b8/BL5h1p7w76QYMYMVQNAdtDKut2R8MBpuWf\n" + + "Ny7Eoi0x/gm1p9X5Rcl5aN7K0G4UtTAJKbkuUfXddsyFoM0Nx8uo8SgNQ8Y/X5Jx\n" + + "BwIDAQABo4IDOTCCAzUwHwYDVR0jBBgwFoAUe2jOKarAF75JeuHlP9an90WPNTIw\n" + + "HQYDVR0OBBYEFFLZ3n5nt/Eer7n1bvtOqMb1qKO5MA4GA1UdDwEB/wQEAwIHgDAT\n" + + "BgNVHSUEDDAKBggrBgEFBQcDAzBzBgNVHR8EbDBqMDOgMaAvhi1odHRwOi8vY3Js\n" + + "My5kaWdpY2VydC5jb20vYXNzdXJlZC1jcy0yMDExYS5jcmwwM6AxoC+GLWh0dHA6\n" + + "Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9hc3N1cmVkLWNzLTIwMTFhLmNybDCCAcQGA1Ud\n" + + "IASCAbswggG3MIIBswYJYIZIAYb9bAMBMIIBpDA6BggrBgEFBQcCARYuaHR0cDov\n" + + "L3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsG\n" + + "AQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABD\n" + + "AGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABh\n" + + "AGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQBy\n" + + "AHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBn\n" + + "ACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABs\n" + + "AGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABp\n" + + "AG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBl\n" + + "AGYAZQByAGUAbgBjAGUALjCBggYIKwYBBQUHAQEEdjB0MCQGCCsGAQUFBzABhhho\n" + + "dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTAYIKwYBBQUHMAKGQGh0dHA6Ly9jYWNl\n" + + "cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENvZGVTaWduaW5nQ0Et\n" + + "MS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOCAQEAPTTQvpOIikXI\n" + + "hTLnNbajaFRR5GhQpTzUNgBfF9VYSlNw/wMjpGsrh5RxaJCip52jbehmTgjMRhft\n" + + "jRYyml44PAVsCcR9uEoDpCZYpI1fHI1R+F8jd1C9rqprbSwwOG4xlg4SmvTHYs6e\n" + + "gBItQ/1p9XY+Sf4Wv1qOuOFL1qvV/5VyR2zdlOQCmKCeMgxt6a/tHLBDiAA67D44\n" + + "/vfdoNJl0CU2It0PO60jdCPFNWIRcxL+OSDqAoePeUC7xQ+JsTEIxuUE8+d6w6fc\n" + + "BV2mYb1flh22t46GLjh4gyo7xw3aL6L0L0jzlTT6IcEw6NIbaPbIKj/npQnHobYj\n" + + "XMuKLxbh7g==\n" + + "-----END CERTIFICATE-----"); + + // Subject: CN=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, + // O=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, + // L=S?o Paulo, + // ST=S?o Paulo, + // C=BR + // Issuer: CN=DigiCert Assured ID Code Signing CA-1, + // OU=www.digicert.com, + // O=DigiCert Inc, + // C=US + // Serial: 0a:38:9b:95:ee:73:6d:d1:3b:c0:ed:74:3f:d7:4d:2f + add("buster-assistencia-tecnica-electronica-ltda-3FD74D2F", + "-----BEGIN CERTIFICATE-----\n" + + "MIIG4DCCBcigAwIBAgIQCjible5zbdE7wO10P9dNLzANBgkqhkiG9w0BAQUFADBv\n" + + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + + "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + + "ZGUgU2lnbmluZyBDQS0xMB4XDTEyMTEwOTAwMDAwMFoXDTEzMTExNDEyMDAwMFow\n" + + "gasxCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMRMwEQYDVQQHDApT\n" + + "w6NvIFBhdWxvMTgwNgYDVQQKEy9CVVNURVIgQVNTSVNURU5DSUEgVEVDTklDQSBF\n" + + "TEVUUk9OSUNBIExUREEgLSBNRTE4MDYGA1UEAxMvQlVTVEVSIEFTU0lTVEVOQ0lB\n" + + "IFRFQ05JQ0EgRUxFVFJPTklDQSBMVERBIC0gTUUwggEiMA0GCSqGSIb3DQEBAQUA\n" + + "A4IBDwAwggEKAoIBAQDAqNeEs5/B2CTXGjTOkUIdu6jV6qulOZwdw4sefHWYj1UR\n" + + "4z6zPk9kjpUgbnb402RFq88QtfInwddZ/wXn9OxMtDd/3TnC7HrhNS7ga79ZFL2V\n" + + "JnmzKHum2Yvh0q82QEJ9tHBR2X9VdKpUIH08Zs3k6cWWM1H0YX0cxA/HohhesQJW\n" + + "kwJ3urOIJiH/HeByDk8a1NS8safcCxk5vxvW4WvCg43iT09LeHY5Aa8abKw8lqVb\n" + + "0tD5ZSIjdmdj3TT1U37iAHLLRM2DXbxfdbhouUX1c5U1ZHAMA67HwjKiseOiDaHj\n" + + "NUGbC37C+cgbc9VVM/cURD8WvS0Kj6fQv7F2QtJDAgMBAAGjggM5MIIDNTAfBgNV\n" + + "HSMEGDAWgBR7aM4pqsAXvkl64eU/1qf3RY81MjAdBgNVHQ4EFgQU88EXKAyDsh30\n" + + "o9+Gu9a4xUy+FSMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMD\n" + + "MHMGA1UdHwRsMGowM6AxoC+GLWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9hc3N1\n" + + "cmVkLWNzLTIwMTFhLmNybDAzoDGgL4YtaHR0cDovL2NybDQuZGlnaWNlcnQuY29t\n" + + "L2Fzc3VyZWQtY3MtMjAxMWEuY3JsMIIBxAYDVR0gBIIBuzCCAbcwggGzBglghkgB\n" + + "hv1sAwEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9z\n" + + "c2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A\n" + + "eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA\n" + + "ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA\n" + + "IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA\n" + + "YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA\n" + + "cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA\n" + + "aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA\n" + + "ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMIGC\n" + + "BggrBgEFBQcBAQR2MHQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0\n" + + "LmNvbTBMBggrBgEFBQcwAoZAaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp\n" + + "Z2lDZXJ0QXNzdXJlZElEQ29kZVNpZ25pbmdDQS0xLmNydDAMBgNVHRMBAf8EAjAA\n" + + "MA0GCSqGSIb3DQEBBQUAA4IBAQAei1QmiXepje8OIfo/WonD4MIXgpPr2dfRaquQ\n" + + "A8q63OpTRSveyqdQDCSPpDRF/nvO1Y30yksZvIH1tNBsW5LBdxAKN3lFdBlqBwtE\n" + + "Q3jHc0KVVYRJ0FBaGE/PJHmRajscdAhYIcMPhTga0u0tDK+wOHEq3993dfl6yHjA\n" + + "XHU2iW5pnk75ZoE39zALD5eKXT8ZXrET5c3XUFJKWA+XuGmdmyzqo0Au49PanBv9\n" + + "UlZnabYfqoMArqMS0tGSX4cGgi9/2E+pHG9BX4sFW+ZDumroOA2pxyMWEKjxePEL\n" + + "zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" + + "-----END CERTIFICATE-----"); + } } From f5e3306d7504137bcfe7f0c493b2d4d74f761aa2 Mon Sep 17 00:00:00 2001 From: Jia-Hong Chen Date: Thu, 14 Feb 2013 14:14:38 -0800 Subject: [PATCH 043/102] 8008173: [parfait] #1173 Uninitialised variable -- TransformHelper.cpp Reviewed-by: prr, vadim --- jdk/src/share/native/sun/java2d/loops/TransformHelper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jdk/src/share/native/sun/java2d/loops/TransformHelper.c b/jdk/src/share/native/sun/java2d/loops/TransformHelper.c index 23bba354756..72334550250 100644 --- a/jdk/src/share/native/sun/java2d/loops/TransformHelper.c +++ b/jdk/src/share/native/sun/java2d/loops/TransformHelper.c @@ -353,6 +353,9 @@ Java_sun_java2d_loops_TransformHelper_Transform pInterpFunc = pBicubicFunc; maxlinepix = LINE_SIZE / 16; break; + default: + // Should not happen, but just in case. + return; } srcInfo.bounds.x1 = sx1; From 5287640ec65a3b3541ff7dfd689f5471f2e4f427 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Fri, 15 Feb 2013 14:24:42 +0400 Subject: [PATCH 044/102] 7173873: JFrame.setDefaultCloseOperation(EXIT_ON_CLOSE) will never lead to SE if EXIT_ON_CLOSE is already set Reviewed-by: malenkov, serb --- jdk/src/share/classes/javax/swing/JFrame.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/JFrame.java b/jdk/src/share/classes/javax/swing/JFrame.java index cccd6f98aa5..aee994eecf9 100644 --- a/jdk/src/share/classes/javax/swing/JFrame.java +++ b/jdk/src/share/classes/javax/swing/JFrame.java @@ -387,13 +387,14 @@ public class JFrame extends Frame implements WindowConstants, operation != EXIT_ON_CLOSE) { throw new IllegalArgumentException("defaultCloseOperation must be one of: DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE, DISPOSE_ON_CLOSE, or EXIT_ON_CLOSE"); } - if (this.defaultCloseOperation != operation) { - if (operation == EXIT_ON_CLOSE) { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkExit(0); - } + + if (operation == EXIT_ON_CLOSE) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkExit(0); } + } + if (this.defaultCloseOperation != operation) { int oldValue = this.defaultCloseOperation; this.defaultCloseOperation = operation; firePropertyChange("defaultCloseOperation", oldValue, operation); From 4615442550640167be71a639b992519b14522cc0 Mon Sep 17 00:00:00 2001 From: Frank Ding Date: Fri, 15 Feb 2013 15:05:58 +0400 Subject: [PATCH 045/102] 8008289: DefaultButtonModel instance keeps stale listeners in html FormView Reviewed-by: malenkov, alexsch --- .../javax/swing/text/html/FormView.java | 63 +++++++- .../swing/text/html/7189299/bug7189299.java | 138 ++++++++++++++++++ 2 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 jdk/test/javax/swing/text/html/7189299/bug7189299.java diff --git a/jdk/src/share/classes/javax/swing/text/html/FormView.java b/jdk/src/share/classes/javax/swing/text/html/FormView.java index 294637272f3..2d25516f339 100644 --- a/jdk/src/share/classes/javax/swing/text/html/FormView.java +++ b/jdk/src/share/classes/javax/swing/text/html/FormView.java @@ -159,6 +159,10 @@ public class FormView extends ComponentView implements ActionListener { attr.getAttribute(StyleConstants.NameAttribute); JComponent c = null; Object model = attr.getAttribute(StyleConstants.ModelAttribute); + + // Remove listeners previously registered in shared model + // when a new UI component is replaced. See bug 7189299. + removeStaleListenerForModel(model); if (t == HTML.Tag.INPUT) { c = createInputComponent(attr, model); } else if (t == HTML.Tag.SELECT) { @@ -310,6 +314,63 @@ public class FormView extends ComponentView implements ActionListener { return c; } + private void removeStaleListenerForModel(Object model) { + if (model instanceof DefaultButtonModel) { + // case of JButton whose model is DefaultButtonModel + // Need to remove stale ActionListener, ChangeListener and + // ItemListener that are instance of AbstractButton$Handler. + DefaultButtonModel buttonModel = (DefaultButtonModel) model; + String listenerClass = "javax.swing.AbstractButton$Handler"; + for (ActionListener listener : buttonModel.getActionListeners()) { + if (listenerClass.equals(listener.getClass().getName())) { + buttonModel.removeActionListener(listener); + } + } + for (ChangeListener listener : buttonModel.getChangeListeners()) { + if (listenerClass.equals(listener.getClass().getName())) { + buttonModel.removeChangeListener(listener); + } + } + for (ItemListener listener : buttonModel.getItemListeners()) { + if (listenerClass.equals(listener.getClass().getName())) { + buttonModel.removeItemListener(listener); + } + } + } else if (model instanceof AbstractListModel) { + // case of JComboBox and JList + // For JList, the stale ListDataListener is instance + // BasicListUI$Handler. + // For JComboBox, there are 2 stale ListDataListeners, which are + // BasicListUI$Handler and BasicComboBoxUI$Handler. + AbstractListModel listModel = (AbstractListModel) model; + String listenerClass1 = + "javax.swing.plaf.basic.BasicListUI$Handler"; + String listenerClass2 = + "javax.swing.plaf.basic.BasicComboBoxUI$Handler"; + for (ListDataListener listener : listModel.getListDataListeners()) { + if (listenerClass1.equals(listener.getClass().getName()) + || listenerClass2.equals(listener.getClass().getName())) + { + listModel.removeListDataListener(listener); + } + } + } else if (model instanceof AbstractDocument) { + // case of JPasswordField, JTextField and JTextArea + // All have 2 stale DocumentListeners. + String listenerClass1 = + "javax.swing.plaf.basic.BasicTextUI$UpdateHandler"; + String listenerClass2 = + "javax.swing.text.DefaultCaret$Handler"; + AbstractDocument docModel = (AbstractDocument) model; + for (DocumentListener listener : docModel.getDocumentListeners()) { + if (listenerClass1.equals(listener.getClass().getName()) + || listenerClass2.equals(listener.getClass().getName())) + { + docModel.removeDocumentListener(listener); + } + } + } + } /** * Determines the maximum span for this view along an @@ -347,7 +408,7 @@ public class FormView extends ComponentView implements ActionListener { /** - * Responsible for processeing the ActionEvent. + * Responsible for processing the ActionEvent. * If the element associated with the FormView, * has a type of "submit", "reset", "text" or "password" * then the action is processed. In the case of a "submit" diff --git a/jdk/test/javax/swing/text/html/7189299/bug7189299.java b/jdk/test/javax/swing/text/html/7189299/bug7189299.java new file mode 100644 index 00000000000..70d2057c89f --- /dev/null +++ b/jdk/test/javax/swing/text/html/7189299/bug7189299.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2013 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. + */ + +/* + * Portions Copyright (c) 2013 IBM Corporation + */ +import java.awt.BorderLayout; +import java.awt.Toolkit; + +import java.awt.event.ActionListener; +import javax.swing.DefaultButtonModel; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; +import javax.swing.text.html.HTMLEditorKit; +import sun.awt.SunToolkit; + + +/* + * @test + * @bug 8008289 + * @summary Shared ButtonModel instance should deregister previous listeners. + * @author Frank Ding + */ +public class bug7189299 { + + private static JEditorPane html; + private static JFrame frame; + + private static void setup() { + /** + * Note the input type is not restricted to "submit". Types "image", + * "checkbox", "radio" have the same problem. + */ + html = new JEditorPane("text/html", + "

    " + + "" + + "
    "); + frame = new JFrame(); + frame.setLayout(new BorderLayout()); + frame.add(html, BorderLayout.CENTER); + frame.setSize(200, 100); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + + private static void doTest() { + /* + * Calling updateComponentTreeUI creates a new FormView instance with + * its own associated JButton instance. The same DefaultButtonModel + * instance is used for both FormView's. + * + * The action listeners associated with (the JButton for) the first + * FormView should be unregistered from this common DefaultButtonModel, + * such that only those for the new FormView remain. + */ + SwingUtilities.updateComponentTreeUI(html); + } + + private static void verifySingleDefaultButtonModelListener() { + HTMLEditorKit htmlEditorKit = (HTMLEditorKit) html.getEditorKit(); + StyleContext.NamedStyle style = ((StyleContext.NamedStyle) htmlEditorKit + .getInputAttributes()); + DefaultButtonModel model = ((DefaultButtonModel) style + .getAttribute(StyleConstants.ModelAttribute)); + ActionListener[] listeners = model.getActionListeners(); + int actionListenerNum = listeners.length; + if (actionListenerNum != 1) { + throw new RuntimeException( + "Expected single ActionListener object registered with " + + "DefaultButtonModel; found " + actionListenerNum + + " listeners registered."); + } + + int changeListenerNum = model.getChangeListeners().length; + if (changeListenerNum != 1) { + throw new RuntimeException( + "Expected at most one ChangeListener object registered " + + "with DefaultButtonModel; found " + changeListenerNum + + " listeners registered."); + } + int itemListenerNum = model.getItemListeners().length; + if (itemListenerNum != 1) { + throw new RuntimeException( + "Expected at most one ItemListener object registered " + + "with DefaultButtonModel; found " + itemListenerNum + + " listeners registered."); + } + } + + public static void main(String[] args) throws Exception { + final SunToolkit toolkit = ((SunToolkit) Toolkit.getDefaultToolkit()); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + setup(); + } + }); + toolkit.realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + verifySingleDefaultButtonModelListener(); + doTest(); + verifySingleDefaultButtonModelListener(); + } finally { + frame.dispose(); + } + } + }); + } +} From d273278133c0c40521669c741791c2d4a22c005f Mon Sep 17 00:00:00 2001 From: Vera Akulova Date: Fri, 15 Feb 2013 17:46:39 +0400 Subject: [PATCH 046/102] 8005920: After pressing combination Windows Key and M key, the frame, the instruction and the dialog can't be minimized Reviewed-by: serb, denis --- .../java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/jdk/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java b/jdk/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java index 9136e79f40e..5b927f8d520 100644 --- a/jdk/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java +++ b/jdk/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, 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 @@ */ /* - @test %I% %E% - @bug 6572263 6571808 + @test + @bug 6572263 6571808 8005920 @summary PIT:FileDialog minimized to taskbar(through 'Show Desktop')selecting the fileDialog using windowList @author dmitry.cherepanov: area=awt.modal @run main/manual Winkey @@ -48,12 +48,14 @@ public class Winkey String[] instructions = { + " 0. This test is for MS Windows only, if you use other OS, press \"pass\" button.", " 1. there is a frame with a 'show modal' button, ", " 2. press the button to show a modal dialog, ", " 3. the modal dialog will be shown over the frame, ", " 4. please verify that all (5.1, 5.2.1, 5.2.2) the following tests pass: ", " ", " 5.1. press combination Windows Key and M key to minimize all windows, ", + " note that the modal dialog and modal blocked windows are NOT minimized", " 5.2. press combination Windows Key and D key to show desktop, ", " 5.2.1. restore the dialog by choosing this one in the ALT-TAB list, ", " 5.2.2. restore the dialog by mouse click on taskbar (on java or any other item)", From 80da999bf3267060b1a38a4f022df6ed0cbc1aab Mon Sep 17 00:00:00 2001 From: Jia-Hong Chen Date: Mon, 18 Feb 2013 14:04:00 -0800 Subject: [PATCH 047/102] 8005191: [parfait] #384 sun/font/layout/LookupProcessor.cpp Null pointer dereference Reviewed-by: prr, vadim --- jdk/src/share/native/sun/font/layout/LookupProcessor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp index 60727aa3f3a..88e9f25ddeb 100644 --- a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp +++ b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp @@ -125,6 +125,10 @@ le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIt } const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex); + if (lookupTable == NULL) { + success = LE_INTERNAL_ERROR; + return 0; + } le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); GlyphIterator tempIterator(*glyphIterator, lookupFlags); le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success); From 49ba72c4637cae1971144040db6cf5a6d85e8cfa Mon Sep 17 00:00:00 2001 From: Petr Pchelko Date: Tue, 19 Feb 2013 11:26:43 +0000 Subject: [PATCH 048/102] 8008374: Build failure (NEWBUILD=false) on Mac Fixed an old build system failure Reviewed-by: art, anthony --- jdk/make/sun/lwawt/FILES_export_macosx.gmk | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/make/sun/lwawt/FILES_export_macosx.gmk b/jdk/make/sun/lwawt/FILES_export_macosx.gmk index 2101fd8ac39..6a2e2f9e93b 100644 --- a/jdk/make/sun/lwawt/FILES_export_macosx.gmk +++ b/jdk/make/sun/lwawt/FILES_export_macosx.gmk @@ -122,7 +122,6 @@ FILES_export = \ sun/lwawt/macosx/CTextPipe.java \ sun/lwawt/macosx/CDesktopPeer.java \ sun/java2d/CRenderer.java \ - sun/lwawt/macosx/EventDispatchAccess.java \ sun/lwawt/macosx/NSPrintInfo.java \ sun/lwawt/macosx/CAccessibility.java \ sun/lwawt/macosx/CAccessible.java \ From 88eea092fb2de66a9c547464fef118231b673f12 Mon Sep 17 00:00:00 2001 From: Konstantin Shefov Date: Tue, 19 Feb 2013 17:26:40 +0400 Subject: [PATCH 049/102] 8008379: TEST_BUG: Fail automatically with java.lang.NullPointerException Reviewed-by: serb, anthony --- .../ModalDialogMultiscreenTest.java | 441 ++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 jdk/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java diff --git a/jdk/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java b/jdk/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java new file mode 100644 index 00000000000..156bfe5df0e --- /dev/null +++ b/jdk/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2013, 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 6430802 8008379 + @summary WM should not hang after show()/close() + @author anthony.petrov@sun.com: area=awt.modal + @run main/manual ModalDialogMultiscreenTest +*/ + + +/** + * ModalDialogMultiscreenTest.java + * + * summary: Tests whether a WM will hang on show()/close() a modal dialog in multiscreen mode + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + + +public class ModalDialogMultiscreenTest +{ + + private static class ButtonActionListener implements ActionListener { + JFrame frame; + JDialog dialog; + public ButtonActionListener(JFrame frame, JDialog dialog) { + this.frame = frame; + this.dialog = dialog; + } + public void actionPerformed(ActionEvent e) { + dialog.setLocationRelativeTo(frame); + dialog.setVisible(true); + } + } + public static class TestDialog extends JDialog { + public TestDialog(Frame owner, String title, boolean modal, GraphicsConfiguration gc) { + super(owner, title, modal, gc); + setSize(200, 100); + JButton button = new JButton("Close"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + getContentPane().add(button); + } + } + + private static void init() + { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gs = ge.getScreenDevices(); + + Sysout.createDialog( ); + + if (gs.length < 2) { + System.out.println("Not multi-head environment, test not valid!"); + ModalDialogMultiscreenTest.pass( ); + } + + String[] instructions = + { + "The test should be run on a multi-head X (non-xinerama) systems.", + "Otherwise click the Pass button right now.", + "You will see an open Frame on each screen your system has.", + "The frame has an 'Open dialog' button.", + "Clicking the button opens a modal dialog with a Close button.", + "The test procedure:", + "1. Open a dialog and close it with appropriate buttons.", + "2. Switch to another screen ($ DISPLAY=X.Y xprop)", + "3. Repeat steps 1-2 several times (about 3*)", + "If the test doesn't cause the window manager to hang, it's passed." + }; + Sysout.printInstructions( instructions ); + + + for (int i = 0; i < gs.length; i++) { + JFrame frame = new JFrame("Frame "+i,gs[i].getDefaultConfiguration()); + JButton button = new JButton("Open Dialog"); + button.setMinimumSize(new Dimension(200, 100)); + button.setPreferredSize(new Dimension(200, 100)); + button.setSize(new Dimension(200, 100)); + button.addActionListener(new ButtonActionListener(frame, new TestDialog(frame, "Dialog #"+i, true, gs[i].getDefaultConfiguration()))); + frame.getContentPane().add(button); + frame.pack(); + frame.setVisible(true); + } + + }//End init() + + + //ap203012: NO MORE CHANGES BELOW THIS LINE + + + + /***************************************************** + * Standard Test Machinery Section + * DO NOT modify anything in this section -- it's a + * standard chunk of code which has all of the + * synchronisation necessary for the test harness. + * By keeping it the same in all tests, it is easier + * to read and understand someone else's test, as + * well as insuring that all tests behave correctly + * with the test harness. + * There is a section following this for test-defined + * classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + public static void main( String args[] ) throws InterruptedException + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test passed nor test failed has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + +}// class ModalDialogMultiscreenTest + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException +{ +} + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// make listeners in a class defined here, and instantiate them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + ModalDialogMultiscreenTest.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + ModalDialogMultiscreenTest.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog implements ActionListener +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //ModalDialogMultiscreenTest + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + ModalDialogMultiscreenTest.pass(); + } + else + { + ModalDialogMultiscreenTest.fail(); + } + } + +}// TestDialog class From a97003cb2242d44f567200b78cb0604878c2e677 Mon Sep 17 00:00:00 2001 From: Konstantin Shefov Date: Tue, 19 Feb 2013 20:00:02 +0400 Subject: [PATCH 050/102] 8006070: TEST_BUG: Up and down the Y coordinate of the mouse position, the selected item doesn't change for the single list Reviewed-by: serb, anthony --- .../MouseDraggedOutCauseScrollingTest.html | 43 +++ .../MouseDraggedOutCauseScrollingTest.java | 246 ++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html create mode 100644 jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java diff --git a/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html b/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html new file mode 100644 index 00000000000..7049e827033 --- /dev/null +++ b/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html @@ -0,0 +1,43 @@ + + + + + + ManualYesNoTest + + + +

    ManualYesNoTest
    Bug ID:

    + +

    See the dialog box (usually in upper left corner) for instructions

    + + + + diff --git a/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java b/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java new file mode 100644 index 00000000000..8b509a12311 --- /dev/null +++ b/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2013, 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 6243382 8006070 + @summary Dragging of mouse outside of a List and Choice area don't work properly on XAWT + @author Dmitry.Cherepanov@SUN.COM area=awt.list + @run applet/manual=yesno MouseDraggedOutCauseScrollingTest.html +*/ + +import java.applet.Applet; +import java.awt.*; + +public class MouseDraggedOutCauseScrollingTest extends Applet +{ + Choice choice; + List singleList; + List multipleList; + + public void init() + { + this.setLayout (new GridLayout (1, 3)); + + choice = new Choice(); + singleList = new List(3, false); + multipleList = new List(3, true); + + choice.add("Choice"); + for (int i = 1; i < 100; i++){ + choice.add(""+i); + } + + singleList.add("Single list"); + for (int i = 1; i < 100; i++) + singleList.add(""+i); + + multipleList.add("Multiple list"); + for (int i = 1; i < 100; i++) + multipleList.add(""+i); + + this.add(choice); + this.add(singleList); + this.add(multipleList); + + String toolkitName = Toolkit.getDefaultToolkit().getClass().getName(); + if (!toolkitName.equals("sun.awt.X11.XToolkit")) { + String[] instructions = + { + "This test is not applicable to the current platform. Press PASS" + }; + Sysout.createDialogWithInstructions( instructions ); + } else { + String[] instructions = + { + "0) Please note, that this is only Motif/XAWT test. At first, make the applet active", + "1.1) Click on the choice", + "1.2) Press the left button of the mouse and keep on any item of the choice, for example 5", + "1.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", + "1.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", + "1.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", + "-----------------------------------", + "2.1) Click on the single list", + "2.2) Press the left button of the mouse and keep on any item of the list, for example 5", + "2.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", + "2.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", + "2.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", + "-----------------------------------", + "3.1) Click on the multiple list", + "3.2) Press the left button of the mouse and keep on any item of the list, for example 5", + "3.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", + "3.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the upper. If not, the test failed", + "3.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the lower. If not, the test failed", + "4) Test passed." + }; + Sysout.createDialogWithInstructions( instructions ); + } + + }//End init() + + public void start () + { + setSize (400,100); + setVisible(true); + validate(); + + }// start() + +}// class ManualYesNoTest + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class From 9ed09d08f5756a996f46215401f99f9bfcb29d3d Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Thu, 21 Feb 2013 17:22:15 +0100 Subject: [PATCH 051/102] 8008549: NPG: SystemDictionary::find(...) unnecessarily keeps class loaders alive SystemDictionary::find(...) should not create and register ClassLoaderData objects for class loaders. Co-authored-by: Erik Helin Reviewed-by: coleenp, acorn --- hotspot/src/share/vm/classfile/classLoaderData.hpp | 1 + .../share/vm/classfile/classLoaderData.inline.hpp | 10 ++++++++-- hotspot/src/share/vm/classfile/dictionary.cpp | 1 + .../src/share/vm/classfile/systemDictionary.cpp | 14 ++++++++++---- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index f72645db1c4..8fbf454fed6 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -234,6 +234,7 @@ class ClassLoaderData : public CHeapObj { void add_to_deallocate_list(Metadata* m); static ClassLoaderData* class_loader_data(oop loader); + static ClassLoaderData* class_loader_data_or_null(oop loader); static ClassLoaderData* anonymous_class_loader_data(oop loader, TRAPS); static void print_loader(ClassLoaderData *loader_data, outputStream *out); diff --git a/hotspot/src/share/vm/classfile/classLoaderData.inline.hpp b/hotspot/src/share/vm/classfile/classLoaderData.inline.hpp index 770856fe803..b3a5ccf86d1 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.inline.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.inline.hpp @@ -25,9 +25,15 @@ #include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" +inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) { + if (loader == NULL) { + return ClassLoaderData::the_null_class_loader_data(); + } + return java_lang_ClassLoader::loader_data(loader); +} + inline ClassLoaderData* ClassLoaderData::class_loader_data(oop loader) { - if (loader == NULL) return ClassLoaderData::the_null_class_loader_data(); - ClassLoaderData* loader_data = java_lang_ClassLoader::loader_data(loader); + ClassLoaderData* loader_data = class_loader_data_or_null(loader); assert(loader_data != NULL, "Must be"); return loader_data; } diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index 32ebb27104f..f400a0c0e3f 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -347,6 +347,7 @@ void Dictionary::add_klass(Symbol* class_name, ClassLoaderData* loader_data, assert_locked_or_safepoint(SystemDictionary_lock); assert(obj() != NULL, "adding NULL obj"); assert(obj()->name() == class_name, "sanity check on name"); + assert(loader_data != NULL, "Must be non-NULL"); unsigned int hash = compute_hash(class_name, loader_data); int index = hash_to_index(hash); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index a7370fcce29..002d781f928 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -866,16 +866,22 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle cla // the new entry. Klass* SystemDictionary::find(Symbol* class_name, - Handle class_loader, - Handle protection_domain, - TRAPS) { + Handle class_loader, + Handle protection_domain, + TRAPS) { // UseNewReflection // The result of this call should be consistent with the result // of the call to resolve_instance_class_or_null(). // See evaluation 6790209 and 4474172 for more details. class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader())); - ClassLoaderData* loader_data = register_loader(class_loader, CHECK_NULL); + ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(class_loader()); + + if (loader_data == NULL) { + // If the ClassLoaderData has not been setup, + // then the class loader has no entries in the dictionary. + return NULL; + } unsigned int d_hash = dictionary()->compute_hash(class_name, loader_data); int d_index = dictionary()->hash_to_index(d_hash); From 98e5a4b3938563472ee1572373bacf845936b7d4 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 22 Feb 2013 03:00:48 -0800 Subject: [PATCH 052/102] 8006439: Improve MethodHandles coverage Reviewed-by: jrose, twisti --- .../java/lang/invoke/MethodHandleImpl.java | 24 +------- .../java/lang/invoke/MethodHandleNatives.java | 16 ++++- .../java/lang/invoke/MethodHandles.java | 60 ++++++++++++++----- 3 files changed, 62 insertions(+), 38 deletions(-) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java index 3cdd99cc4a1..1b35e0fc8bf 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -801,12 +801,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static MethodHandle bindCaller(MethodHandle mh, Class hostClass) { // Do not use this function to inject calls into system classes. - if (hostClass == null) { - hostClass = C_Trampoline; - } else if (hostClass.isArray() || + if (hostClass == null + || (hostClass.isArray() || hostClass.isPrimitive() || hostClass.getName().startsWith("java.") || - hostClass.getName().startsWith("sun.")) { + hostClass.getName().startsWith("sun."))) { throw new InternalError(); // does not happen, and should not anyway } // For simplicity, convert mh to a varargs-like method. @@ -816,23 +815,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return restoreToType(bccInvoker.bindTo(vamh), mh.type()); } - // This class ("Trampoline") is known to be inside a dead-end class loader. - // Inject all doubtful calls into this class. - private static Class C_Trampoline; - static { - Class tramp = null; - try { - final int FRAME_COUNT_ARG = 1; // [0] Reflection [1] Trampoline - java.lang.reflect.Method gcc = sun.reflect.Reflection.class.getMethod("getCallerClass", int.class); - tramp = (Class) sun.reflect.misc.MethodUtil.invoke(gcc, null, new Object[]{ FRAME_COUNT_ARG }); - if (tramp.getClassLoader() == BindCaller.class.getClassLoader()) - throw new RuntimeException(tramp.getName()+" class loader"); - } catch (Throwable ex) { - throw new InternalError(ex); - } - C_Trampoline = tramp; - } - private static MethodHandle makeInjectedInvoker(Class hostClass) { Class bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null); if (hostClass.getClassLoader() != bcc.getClassLoader()) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java index 8f1d0c3164e..8d40ac96726 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -393,11 +393,14 @@ class MethodHandleNatives { */ // FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive. static boolean isCallerSensitive(MemberName mem) { - assert(mem.isInvocable()); + if (!mem.isInvocable()) return false; // fields are not caller sensitive Class defc = mem.getDeclaringClass(); switch (mem.getName()) { case "doPrivileged": + case "doPrivilegedWithCombiner": return defc == java.security.AccessController.class; + case "checkMemberAccess": + return canBeCalledVirtual(mem, java.lang.SecurityManager.class); case "getUnsafe": return defc == sun.misc.Unsafe.class; case "lookup": @@ -455,7 +458,7 @@ class MethodHandleNatives { if (defc == java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class) return true; break; case "getContextClassLoader": - return defc == java.lang.Thread.class; + return canBeCalledVirtual(mem, java.lang.Thread.class); case "getPackage": case "getPackages": return defc == java.lang.Package.class; @@ -473,6 +476,8 @@ class MethodHandleNatives { break; case "getCallerClassLoader": return defc == java.lang.ClassLoader.class; + case "registerAsParallelCapable": + return canBeCalledVirtual(mem, java.lang.ClassLoader.class); case "getProxyClass": case "newProxyInstance": return defc == java.lang.reflect.Proxy.class; @@ -494,4 +499,11 @@ class MethodHandleNatives { throw new InternalError(e); } } + static boolean canBeCalledVirtual(MemberName symbolicRef, Class definingClass) { + Class symbolicRefClass = symbolicRef.getDeclaringClass(); + if (symbolicRefClass == definingClass) return true; + if (symbolicRef.isStatic() || symbolicRef.isPrivate()) return false; + return (definingClass.isAssignableFrom(symbolicRefClass) || // Msym overrides Mdef + symbolicRefClass.isInterface()); // Mdef implements Msym + } } diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java index e7007dd2b89..d2a499e9867 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java @@ -598,7 +598,8 @@ public class MethodHandles { MethodHandle findStatic(Class refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - return getDirectMethod(REF_invokeStatic, refc, method); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor + return getDirectMethod(REF_invokeStatic, refc, method, callerClass); } /** @@ -652,7 +653,8 @@ public class MethodHandles { byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); MemberName method = resolveOrFail(refKind, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - return getDirectMethod(refKind, refc, method); + Class callerClass = findBoundCallerClass(method); + return getDirectMethod(refKind, refc, method, callerClass); } private MethodHandle findVirtualForMH(String name, MethodType type) { // these names require special lookups because of the implicit MethodType argument @@ -736,7 +738,8 @@ public class MethodHandles { Lookup specialLookup = this.in(specialCaller); MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method); + Class callerClass = findBoundCallerClass(method); + return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass); } /** @@ -879,7 +882,8 @@ return mh1; Class refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor + MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass); return mh.bindReceiver(receiver).setVarargs(method); } @@ -910,8 +914,9 @@ return mh1; if (refKind == REF_invokeSpecial) refKind = REF_invokeVirtual; assert(method.isMethod()); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method); + return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass); } /** @@ -940,8 +945,9 @@ return mh1; Lookup specialLookup = this.in(specialCaller); MemberName method = new MemberName(m, true); assert(method.isMethod()); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor // ignore m.isAccessible: this is a new kind of access - return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method); + return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass); } /** @@ -1039,8 +1045,30 @@ return mh1; throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this); } + /** + * Find my trustable caller class if m is a caller sensitive method. + * If this lookup object has private access, then the caller class is the lookupClass. + * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). + * This is the same caller class as is used by checkSecurityManager. + * This function performs stack walk magic: do not refactor it. + */ + Class findBoundCallerClass(MemberName m) { + Class callerClass = null; + if (MethodHandleNatives.isCallerSensitive(m)) { + // Do not refactor this to a more "logical" place, since it is stack walk magic. + // Note that this is the same expression as in Step 2 below in checkSecurityManager. + callerClass = ((allowedModes & PRIVATE) != 0 + ? lookupClass // for strong access modes, no extra check + // next line does stack walk magic; do not refactor: + : getCallerClassAtEntryPoint(true)); + } + return callerClass; + } /** * Perform necessary access checks. + * Determines a trustable caller class to compare with refc, the symbolic reference class. + * If this lookup object has private access, then the caller class is the lookupClass. + * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). * This function performs stack walk magic: do not refactor it. */ void checkSecurityManager(Class refc, MemberName m) { @@ -1195,22 +1223,22 @@ return mh1; return mh.viewAsType(narrowType); } - private MethodHandle getDirectMethod(byte refKind, Class refc, MemberName method) throws IllegalAccessException { + private MethodHandle getDirectMethod(byte refKind, Class refc, MemberName method, Class callerClass) throws IllegalAccessException { return getDirectMethodCommon(refKind, refc, method, (refKind == REF_invokeSpecial || (MethodHandleNatives.refKindHasReceiver(refKind) && - restrictProtectedReceiver(method)))); + restrictProtectedReceiver(method))), callerClass); } - private MethodHandle getDirectMethodNoRestrict(byte refKind, Class refc, MemberName method) throws IllegalAccessException { - return getDirectMethodCommon(refKind, refc, method, false); + private MethodHandle getDirectMethodNoRestrict(byte refKind, Class refc, MemberName method, Class callerClass) throws IllegalAccessException { + return getDirectMethodCommon(refKind, refc, method, false, callerClass); } private MethodHandle getDirectMethodCommon(byte refKind, Class refc, MemberName method, - boolean doRestrict) throws IllegalAccessException { + boolean doRestrict, Class callerClass) throws IllegalAccessException { checkMethod(refKind, refc, method); if (method.isMethodHandleInvoke()) return fakeMethodHandleInvoke(method); MethodHandle mh = DirectMethodHandle.make(refc, method); - mh = maybeBindCaller(method, mh); + mh = maybeBindCaller(method, mh, callerClass); mh = mh.setVarargs(method); if (doRestrict) mh = restrictReceiver(method, mh, lookupClass()); @@ -1219,12 +1247,14 @@ return mh1; private MethodHandle fakeMethodHandleInvoke(MemberName method) { return throwException(method.getReturnType(), UnsupportedOperationException.class); } - private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh) throws IllegalAccessException { + private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, + Class callerClass) + throws IllegalAccessException { if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) return mh; Class hostClass = lookupClass; if ((allowedModes & PRIVATE) == 0) // caller must use full-power lookup - hostClass = null; + hostClass = callerClass; // callerClass came from a security manager style stack walk MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass); // Note: caller will apply varargs after this step happens. return cbmh; @@ -1262,7 +1292,7 @@ return mh1; } else if (MethodHandleNatives.refKindIsMethod(refKind)) { MemberName method = (resolved != null) ? resolved : resolveOrFail(refKind, defc, name, (MethodType) type); - return getDirectMethod(refKind, defc, method); + return getDirectMethod(refKind, defc, method, lookupClass); } else if (refKind == REF_newInvokeSpecial) { assert(name == null || name.equals("")); MemberName ctor = (resolved != null) ? resolved From f179e269b978443b6e45f86faffb5cfcd2cfa92b Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 22 Feb 2013 03:00:12 -0800 Subject: [PATCH 053/102] 8006179: JSR292 MethodHandles lookup with interface using findVirtual() Reviewed-by: jrose, twisti --- .../classes/java/lang/invoke/DirectMethodHandle.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java index 0df8e730937..db8d35fd400 100644 --- a/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -51,6 +51,16 @@ class DirectMethodHandle extends MethodHandle { private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) { super(mtype, form); if (!member.isResolved()) throw new InternalError(); + + if (member.getDeclaringClass().isInterface() && !member.isAbstract()) { + // Check for corner case: invokeinterface of Object method + MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind()); + m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null); + if (m != null && m.isPublic()) { + member = m; + } + } + this.member = member; } From 0ae708ca99b6aebd91cf3486ddffc7fc8e742722 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 22 Feb 2013 02:59:24 -0800 Subject: [PATCH 054/102] 8006125: Update MethodHandles library interactions Reviewed-by: jrose --- jdk/src/share/classes/sun/reflect/misc/MethodUtil.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java b/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java index 0eade8de571..9d9c5ab6015 100644 --- a/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java +++ b/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java @@ -252,6 +252,12 @@ public final class MethodUtil extends SecureClassLoader { public static Object invoke(Method m, Object obj, Object[] params) throws InvocationTargetException, IllegalAccessException { if (m.getDeclaringClass().equals(AccessController.class) || + (m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.class) + && m.getName().equals("lookup")) || + (m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.Lookup.class) + && (m.getName().startsWith("find") || + m.getName().startsWith("bind") || + m.getName().startsWith("unreflect"))) || m.getDeclaringClass().equals(Method.class)) throw new InvocationTargetException( new UnsupportedOperationException("invocation not supported")); From 17992b9ac9c1509c24eb0d072c7ff79cdb294151 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 22 Feb 2013 02:58:38 -0800 Subject: [PATCH 055/102] 8004933: Improve MethodHandle interaction with libraries Reviewed-by: jrose --- .../java/lang/invoke/MethodHandleNatives.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java index 8d40ac96726..db072126e1f 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -405,6 +405,21 @@ class MethodHandleNatives { return defc == sun.misc.Unsafe.class; case "lookup": return defc == java.lang.invoke.MethodHandles.class; + case "findStatic": + case "findVirtual": + case "findConstructor": + case "findSpecial": + case "findGetter": + case "findSetter": + case "findStaticGetter": + case "findStaticSetter": + case "bind": + case "unreflect": + case "unreflectSpecial": + case "unreflectConstructor": + case "unreflectGetter": + case "unreflectSetter": + return defc == java.lang.invoke.MethodHandles.Lookup.class; case "invoke": return defc == java.lang.reflect.Method.class; case "get": From a8305fc6e6f713c2c2762d8dbed869bd158d9aa9 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 22 Feb 2013 15:13:13 +0400 Subject: [PATCH 056/102] 8006406: lightweight embedding in other Java UI toolkits Reviewed-by: serb, anthony, art --- .../classes/sun/lwawt/LWComponentPeer.java | 2 +- .../sun/lwawt/LWLightweightFramePeer.java | 115 ++++++++ .../macosx/classes/sun/lwawt/LWToolkit.java | 19 ++ .../classes/sun/lwawt/LWWindowPeer.java | 12 +- .../sun/lwawt/macosx/CPlatformComponent.java | 2 +- .../lwawt/macosx/CPlatformLWComponent.java | 53 ++++ .../sun/lwawt/macosx/CPlatformLWView.java | 82 ++++++ .../sun/lwawt/macosx/CPlatformLWWindow.java | 202 ++++++++++++++ .../sun/lwawt/macosx/CPlatformView.java | 8 +- .../sun/lwawt/macosx/CPlatformWindow.java | 18 +- .../classes/sun/lwawt/macosx/LWCToolkit.java | 7 + .../classes/java/awt/peer/FramePeer.java | 6 + .../classes/java/awt/peer/WindowPeer.java | 2 - .../share/classes/sun/awt/EmbeddedFrame.java | 5 +- jdk/src/share/classes/sun/awt/HToolkit.java | 5 + .../classes/sun/awt/LightweightFrame.java | 127 +++++++++ jdk/src/share/classes/sun/awt/SunToolkit.java | 3 + .../classes/sun/swing/JLightweightFrame.java | 250 ++++++++++++++++++ .../classes/sun/swing/LightweightContent.java | 164 ++++++++++++ .../classes/sun/awt/X11/XFramePeer.java | 2 + .../solaris/classes/sun/awt/X11/XToolkit.java | 4 + .../sun/awt/windows/WEmbeddedFrame.java | 8 +- .../sun/awt/windows/WEmbeddedFramePeer.java | 2 - .../classes/sun/awt/windows/WFramePeer.java | 7 + .../awt/windows/WLightweightFramePeer.java | 86 ++++++ .../classes/sun/awt/windows/WToolkit.java | 7 + .../windows/native/sun/windows/awt_Frame.cpp | 55 +++- .../windows/native/sun/windows/awt_Frame.h | 5 + .../windows/native/sun/windows/awt_Window.h | 5 +- 29 files changed, 1229 insertions(+), 34 deletions(-) create mode 100644 jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java create mode 100644 jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java create mode 100644 jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java create mode 100644 jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java create mode 100644 jdk/src/share/classes/sun/awt/LightweightFrame.java create mode 100644 jdk/src/share/classes/sun/swing/JLightweightFrame.java create mode 100644 jdk/src/share/classes/sun/swing/LightweightContent.java create mode 100644 jdk/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java diff --git a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java index aa9b798c617..301fbb476d8 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -439,7 +439,7 @@ public abstract class LWComponentPeer } @Override - public final Graphics getGraphics() { + public Graphics getGraphics() { final Graphics g = getOnscreenGraphics(); if (g != null) { synchronized (getPeerTreeLock()){ diff --git a/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java b/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java new file mode 100644 index 00000000000..90e2e88c441 --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013, 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.lwawt; + +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.dnd.DropTarget; + +import sun.awt.CausedFocusEvent; +import sun.awt.LightweightFrame; + +public class LWLightweightFramePeer extends LWWindowPeer { + + public LWLightweightFramePeer(LightweightFrame target, + PlatformComponent platformComponent, + PlatformWindow platformWindow) + { + super(target, platformComponent, platformWindow, LWWindowPeer.PeerType.LW_FRAME); + } + + private LightweightFrame getLwTarget() { + return (LightweightFrame)getTarget(); + } + + @Override + public Graphics getGraphics() { + return getLwTarget().getGraphics(); + } + + @Override + protected void setVisibleImpl(final boolean visible) { + } + + @Override + public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { + if (!focusAllowedFor()) { + return false; + } + if (getPlatformWindow().rejectFocusRequest(cause)) { + return false; + } + + Window opposite = LWKeyboardFocusManagerPeer.getInstance(). + getCurrentFocusedWindow(); + + changeFocusedWindow(true, opposite); + + return true; + } + + @Override + public Point getLocationOnScreen() { + Rectangle bounds = getBounds(); + return new Point(bounds.x, bounds.y); // todo + } + + @Override + public Insets getInsets() { + return new Insets(0, 0, 0, 0); + } + + @Override + public void setBounds(int x, int y, int w, int h, int op) { + setBounds(x, y, w, h, op, true, false); + } + + @Override + public void updateCursorImmediately() { + // TODO: tries to switch to the awt/fx toolkit thread and causes a deadlock on macosx + } + + @Override + public void addDropTarget(DropTarget dt) { + } + + @Override + public void removeDropTarget(DropTarget dt) { + } + + @Override + public void grab() { + getLwTarget().grabFocus(); + } + + @Override + public void ungrab() { + getLwTarget().ungrabFocus(); + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java index 89f39fccbf8..cad6e4353ba 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java @@ -218,6 +218,23 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { return peer; } + private LWLightweightFramePeer createDelegatedLwPeer(LightweightFrame target, + PlatformComponent platformComponent, + PlatformWindow platformWindow) + { + LWLightweightFramePeer peer = new LWLightweightFramePeer(target, platformComponent, platformWindow); + targetCreatedPeer(target, peer); + peer.initialize(); + return peer; + } + + @Override + public FramePeer createLightweightFrame(LightweightFrame target) { + PlatformComponent platformComponent = createLwPlatformComponent(); + PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.LW_FRAME); + return createDelegatedLwPeer(target, platformComponent, platformWindow); + } + @Override public WindowPeer createWindow(Window target) { PlatformComponent platformComponent = createPlatformComponent(); @@ -502,6 +519,8 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { protected abstract PlatformComponent createPlatformComponent(); + protected abstract PlatformComponent createLwPlatformComponent(); + protected abstract FileDialogPeer createFileDialogPeer(FileDialog target); // ---- UTILITY METHODS ---- // diff --git a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 5b19788f244..d50335f7cd5 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -48,7 +48,8 @@ public class LWWindowPeer FRAME, DIALOG, EMBEDDED_FRAME, - VIEW_EMBEDDED_FRAME + VIEW_EMBEDDED_FRAME, + LW_FRAME } private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWWindowPeer"); @@ -1090,7 +1091,7 @@ public class LWWindowPeer return platformWindow.requestWindowFocus(); } - private boolean focusAllowedFor() { + protected boolean focusAllowedFor() { Window window = getTarget(); // TODO: check if modal blocked return window.isVisible() && window.isEnabled() && isFocusableWindow(); @@ -1113,10 +1114,15 @@ public class LWWindowPeer return !(window instanceof Dialog || window instanceof Frame); } + @Override + public void emulateActivation(boolean activate) { + changeFocusedWindow(activate, null); + } + /* * Changes focused window on java level. */ - private void changeFocusedWindow(boolean becomesFocused, Window opposite) { + protected void changeFocusedWindow(boolean becomesFocused, Window opposite) { if (focusLog.isLoggable(PlatformLogger.FINE)) { focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this); } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java index 370b930ea98..978f65c3c91 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java @@ -35,7 +35,7 @@ import sun.lwawt.PlatformWindow; * On OSX {@code CPlatformComponent} stores pointer to the native CAlayer which * can be used from JAWT. */ -final class CPlatformComponent extends CFRetainedResource +class CPlatformComponent extends CFRetainedResource implements PlatformComponent { private volatile PlatformWindow platformWindow; diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java new file mode 100644 index 00000000000..fd76cf5c898 --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013, 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.lwawt.macosx; + +import sun.lwawt.PlatformWindow; + +class CPlatformLWComponent extends CPlatformComponent { + + CPlatformLWComponent() { + super(); + } + + @Override + public long getPointer() { + return 0; + } + + @Override + public void initialize(final PlatformWindow platformWindow) { + } + + @Override + public void setBounds(final int x, final int y, final int w, final int h) { + } + + @Override + public void dispose() { + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java new file mode 100644 index 00000000000..e5d99678b18 --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, 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.lwawt.macosx; + +import sun.lwawt.LWWindowPeer; +import sun.java2d.SurfaceData; + +public class CPlatformLWView extends CPlatformView { + + public CPlatformLWView() { + super(); + } + + @Override + public void initialize(LWWindowPeer peer, CPlatformResponder responder) { + initializeBase(peer, responder); + } + + @Override + public long getAWTView() { + return 0; + } + + @Override + public boolean isOpaque() { + return true; + } + + @Override + public void setBounds(int x, int y, int width, int height) { + } + + @Override + public void enterFullScreenMode() { + } + + @Override + public void exitFullScreenMode() { + } + + @Override + public SurfaceData replaceSurfaceData() { + return null; + } + + @Override + public SurfaceData getSurfaceData() { + return null; + } + + @Override + public void dispose() { + } + + @Override + public long getWindowLayerPtr() { + return 0; + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java new file mode 100644 index 00000000000..d7a91264328 --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2013, 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.lwawt.macosx; + +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GraphicsDevice; +import java.awt.Insets; +import java.awt.MenuBar; +import java.awt.Point; +import java.awt.Window; +import sun.awt.CausedFocusEvent; +import sun.java2d.SurfaceData; +import sun.lwawt.LWWindowPeer; +import sun.lwawt.PlatformWindow; + +public class CPlatformLWWindow extends CPlatformWindow { + + @Override + public void initialize(Window target, LWWindowPeer peer, PlatformWindow owner) { + initializeBase(target, peer, owner, new CPlatformLWView()); + } + + @Override + public void toggleFullScreen() { + } + + @Override + public void setMenuBar(MenuBar mb) { + } + + @Override + public void dispose() { + } + + @Override + public FontMetrics getFontMetrics(Font f) { + return null; + } + + @Override + public Insets getInsets() { + return new Insets(0, 0, 0, 0); + } + + @Override + public Point getLocationOnScreen() { + return null; + } + + @Override + public GraphicsDevice getGraphicsDevice() { + return null; + } + + @Override + public SurfaceData getScreenSurface() { + return null; + } + + @Override + public SurfaceData replaceSurfaceData() { + return null; + } + + @Override + public void setBounds(int x, int y, int w, int h) { + if (getPeer() != null) { + getPeer().notifyReshape(x, y, w, h); + } + } + + @Override + public void setVisible(boolean visible) { + } + + @Override + public void setTitle(String title) { + } + + @Override + public void updateIconImages() { + } + + @Override + public long getNSWindowPtr() { + return 0; + } + + @Override + public SurfaceData getSurfaceData() { + return null; + } + + @Override + public void toBack() { + } + + @Override + public void toFront() { + } + + @Override + public void setResizable(final boolean resizable) { + } + + @Override + public void setSizeConstraints(int minW, int minH, int maxW, int maxH) { + } + + @Override + public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) { + return false; + } + + @Override + public boolean requestWindowFocus() { + return true; + } + + @Override + public boolean isActive() { + return true; + } + + @Override + public void updateFocusableWindowState() { + } + + @Override + public Graphics transformGraphics(Graphics g) { + return null; + } + + @Override + public void setAlwaysOnTop(boolean isAlwaysOnTop) { + } + + @Override + public PlatformWindow getTopmostPlatformWindowUnderMouse(){ + return null; + } + + @Override + public void setOpacity(float opacity) { + } + + @Override + public void setOpaque(boolean isOpaque) { + } + + @Override + public void enterFullScreenMode() { + } + + @Override + public void exitFullScreenMode() { + } + + @Override + public void setWindowState(int windowState) { + } + + @Override + public LWWindowPeer getPeer() { + return super.getPeer(); + } + + @Override + public CPlatformView getContentView() { + return super.getContentView(); + } + + @Override + public long getLayerPtr() { + return 0; + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java index 495657963bd..3a0bec48629 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java @@ -54,8 +54,7 @@ public class CPlatformView extends CFRetainedResource { } public void initialize(LWWindowPeer peer, CPlatformResponder responder) { - this.peer = peer; - this.responder = responder; + initializeBase(peer, responder); if (!LWCToolkit.getSunAwtDisableCALayers()) { this.windowLayer = new CGLLayer(peer); @@ -63,6 +62,11 @@ public class CPlatformView extends CFRetainedResource { setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr())); } + protected void initializeBase(LWWindowPeer peer, CPlatformResponder responder) { + this.peer = peer; + this.responder = responder; + } + public long getAWTView() { return ptr; } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 8f83702a209..dc51373cc1b 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -44,7 +44,7 @@ import com.apple.laf.*; import com.apple.laf.ClientPropertyApplicator.Property; import com.sun.awt.AWTUtilities; -public final class CPlatformWindow extends CFRetainedResource implements PlatformWindow { +public class CPlatformWindow extends CFRetainedResource implements PlatformWindow { private native long nativeCreateNSWindow(long nsViewPtr, long styleBits, double x, double y, double w, double h); private static native void nativeSetNSWindowStyleBits(long nsWindowPtr, int mask, int data); private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr); @@ -218,11 +218,7 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor */ @Override // PlatformWindow public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner) { - this.peer = _peer; - this.target = _target; - if (_owner instanceof CPlatformWindow) { - this.owner = (CPlatformWindow)_owner; - } + initializeBase(_target, _peer, _owner, new CPlatformView()); final int styleBits = getInitialStyleBits(); @@ -231,7 +227,6 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor String warningString = target.getWarningString(); responder = new CPlatformResponder(peer, false); - contentView = new CPlatformView(); contentView.initialize(peer, responder); final long nativeWindowPtr = nativeCreateNSWindow(contentView.getAWTView(), styleBits, 0, 0, 0, 0); @@ -253,6 +248,15 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor validateSurface(); } + protected void initializeBase(Window target, LWWindowPeer peer, PlatformWindow owner, CPlatformView view) { + this.peer = peer; + this.target = target; + if (owner instanceof CPlatformWindow) { + this.owner = (CPlatformWindow)owner; + } + this.contentView = view; + } + private int getInitialStyleBits() { // defaults style bits int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE; diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index ae6a4f77662..801c3d41605 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -160,6 +160,8 @@ public final class LWCToolkit extends LWToolkit { return new CPlatformEmbeddedFrame(); } else if (peerType == PeerType.VIEW_EMBEDDED_FRAME) { return new CViewPlatformEmbeddedFrame(); + } else if (peerType == PeerType.LW_FRAME) { + return new CPlatformLWWindow(); } else { assert (peerType == PeerType.SIMPLEWINDOW || peerType == PeerType.DIALOG || peerType == PeerType.FRAME); return new CPlatformWindow(); @@ -171,6 +173,11 @@ public final class LWCToolkit extends LWToolkit { return new CPlatformComponent(); } + @Override + protected PlatformComponent createLwPlatformComponent() { + return new CPlatformLWComponent(); + } + @Override protected FileDialogPeer createFileDialogPeer(FileDialog target) { return new CFileDialog(target); diff --git a/jdk/src/share/classes/java/awt/peer/FramePeer.java b/jdk/src/share/classes/java/awt/peer/FramePeer.java index 8bb3b07add9..e9d2b002fb0 100644 --- a/jdk/src/share/classes/java/awt/peer/FramePeer.java +++ b/jdk/src/share/classes/java/awt/peer/FramePeer.java @@ -125,4 +125,10 @@ public interface FramePeer extends WindowPeer { // into an EmbeddedFramePeer which would extend FramePeer Rectangle getBoundsPrivate(); + /** + * Requests the peer to emulate window activation. + * + * @param activate activate or deactivate the window + */ + void emulateActivation(boolean activate); } diff --git a/jdk/src/share/classes/java/awt/peer/WindowPeer.java b/jdk/src/share/classes/java/awt/peer/WindowPeer.java index f2e8993e101..fca78b7eed4 100644 --- a/jdk/src/share/classes/java/awt/peer/WindowPeer.java +++ b/jdk/src/share/classes/java/awt/peer/WindowPeer.java @@ -27,8 +27,6 @@ package java.awt.peer; import java.awt.*; -import java.awt.image.BufferedImage; - /** * The peer interface for {@link Window}. * diff --git a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java index d05e30fe742..0ae1ec762df 100644 --- a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java +++ b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java @@ -582,5 +582,8 @@ public abstract class EmbeddedFrame extends Frame public void repositionSecurityWarning() { } - } + + public void emulateActivation(boolean activate) { + } + } } // class EmbeddedFrame diff --git a/jdk/src/share/classes/sun/awt/HToolkit.java b/jdk/src/share/classes/sun/awt/HToolkit.java index 57217678bfc..8671d8b5150 100644 --- a/jdk/src/share/classes/sun/awt/HToolkit.java +++ b/jdk/src/share/classes/sun/awt/HToolkit.java @@ -64,6 +64,11 @@ public class HToolkit extends SunToolkit throw new HeadlessException(); } + public FramePeer createLightweightFrame(LightweightFrame target) + throws HeadlessException { + throw new HeadlessException(); + } + public FramePeer createFrame(Frame target) throws HeadlessException { throw new HeadlessException(); diff --git a/jdk/src/share/classes/sun/awt/LightweightFrame.java b/jdk/src/share/classes/sun/awt/LightweightFrame.java new file mode 100644 index 00000000000..71e3dd30333 --- /dev/null +++ b/jdk/src/share/classes/sun/awt/LightweightFrame.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2013, 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.awt; + +import java.awt.Container; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.MenuBar; +import java.awt.MenuComponent; +import java.awt.Toolkit; +import java.awt.peer.FramePeer; + +/** + * The class provides basic functionality for a lightweight frame + * implementation. A subclass is expected to provide painting to an + * offscreen image and access to it. Thus it can be used for lightweight + * embedding. + * + * @author Artem Ananiev + * @author Anton Tarasov + */ +@SuppressWarnings("serial") +public abstract class LightweightFrame extends Frame { + + /** + * Constructs a new, initially invisible {@code LightweightFrame} + * instance. + */ + public LightweightFrame() { + setUndecorated(true); + setResizable(true); + setEnabled(true); + } + + /** + * Blocks introspection of a parent window by this child. + * + * @return null + */ + @Override public final Container getParent() { return null; } + + @Override public Graphics getGraphics() { return null; } + + @Override public final boolean isResizable() { return true; } + + // Block modification of any frame attributes, since they aren't + // applicable for a lightweight frame. + + @Override public final void setTitle(String title) {} + @Override public final void setIconImage(Image image) {} + @Override public final void setIconImages(java.util.List icons) {} + @Override public final void setMenuBar(MenuBar mb) {} + @Override public final void setResizable(boolean resizable) {} + @Override public final void remove(MenuComponent m) {} + @Override public final void toFront() {} + @Override public final void toBack() {} + + @Override public void addNotify() { + synchronized (getTreeLock()) { + if (getPeer() == null) { + SunToolkit stk = (SunToolkit)Toolkit.getDefaultToolkit(); + try { + setPeer(stk.createLightweightFrame(this)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + super.addNotify(); + } + } + + private void setPeer(final FramePeer p) { + AWTAccessor.getComponentAccessor().setPeer(this, p); + } + + /** + * Requests the peer to emulate activation or deactivation of the + * frame. Peers should override this method if they are to implement + * this functionality. + * + * @param activate if true, activates the frame; + * otherwise, deactivates the frame + */ + public void emulateActivation(boolean activate) { + ((FramePeer)getPeer()).emulateActivation(activate); + } + + /** + * Delegates the focus grab action to the client (embedding) application. + * The method is called by the AWT grab machinery. + * + * @see SunToolkit#grab(java.awt.Window) + */ + public abstract void grabFocus(); + + /** + * Delegates the focus ungrab action to the client (embedding) application. + * The method is called by the AWT grab machinery. + * + * @see SunToolkit#ungrab(java.awt.Window) + */ + public abstract void ungrabFocus(); +} diff --git a/jdk/src/share/classes/sun/awt/SunToolkit.java b/jdk/src/share/classes/sun/awt/SunToolkit.java index 4ae6a94f0dc..8fc568913fb 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -131,6 +131,9 @@ public abstract class SunToolkit extends Toolkit public abstract FramePeer createFrame(Frame target) throws HeadlessException; + public abstract FramePeer createLightweightFrame(LightweightFrame target) + throws HeadlessException; + public abstract DialogPeer createDialog(Dialog target) throws HeadlessException; diff --git a/jdk/src/share/classes/sun/swing/JLightweightFrame.java b/jdk/src/share/classes/sun/swing/JLightweightFrame.java new file mode 100644 index 00000000000..f7ea0aead1e --- /dev/null +++ b/jdk/src/share/classes/sun/swing/JLightweightFrame.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2013, 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.swing; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.EventQueue; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; + +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.LayoutFocusTraversalPolicy; +import javax.swing.RootPaneContainer; + +import sun.awt.LightweightFrame; + +/** + * The frame serves as a lightweight container which paints its content + * to an offscreen image and provides access to the image's data via the + * {@link LightweightContent} interface. Note, that it may not be shown + * as a standalone toplevel frame. Its purpose is to provide functionality + * for lightweight embedding. + * + * @author Artem Ananiev + * @author Anton Tarasov + */ +public final class JLightweightFrame extends LightweightFrame implements RootPaneContainer { + + private final JRootPane rootPane = new JRootPane(); + + private LightweightContent content; + + private Component component; + private JPanel contentPane; + + private BufferedImage bbImage; + + /** + * Constructs a new, initially invisible {@code JLightweightFrame} + * instance. + */ + public JLightweightFrame() { + super(); + add(rootPane, BorderLayout.CENTER); + setBackground(new Color(0, 0, 0, 0)); + setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); + } + + /** + * Sets the {@link LightweightContent} instance for this frame. + * The {@code JComponent} object returned by the + * {@link LightweightContent#getComponent()} method is immediately + * added to the frame's content pane. + * + * @param content the {@link LightweightContent} instance + */ + public void setContent(LightweightContent content) { + this.content = content; + this.component = content.getComponent(); + + initInterior(); + } + + @Override + public Graphics getGraphics() { + if (bbImage == null) return null; + + Graphics2D g = bbImage.createGraphics(); + g.setBackground(getBackground()); + g.setColor(getForeground()); + g.setFont(getFont()); + return g; + } + + /** + * {@inheritDoc} + * + * @see LightweightContent#focusGrabbed() + */ + @Override + public void grabFocus() { + if (content != null) content.focusGrabbed(); + } + + /** + * {@inheritDoc} + * + * @see LightweightContent#focusUngrabbed() + */ + @Override + public void ungrabFocus() { + if (content != null) content.focusUngrabbed(); + } + + private void initInterior() { + contentPane = new JPanel() { + @Override + public void paint(Graphics g) { + content.paintLock(); + try { + super.paint(g); + + final Rectangle clip = g.getClipBounds() != null ? + g.getClipBounds() : new Rectangle(0, 0, contentPane.getWidth(), contentPane.getHeight()); + + clip.x = Math.max(0, clip.x); + clip.y = Math.max(0, clip.y); + clip.width = Math.min(contentPane.getWidth(), clip.width); + clip.height = Math.min(contentPane.getHeight(), clip.height); + + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + content.imageUpdated(clip.x, clip.y, clip.width, clip.height); + } + }); + } finally { + content.paintUnlock(); + } + } + @Override + protected boolean isPaintingOrigin() { + return true; + } + }; + contentPane.setLayout(new BorderLayout()); + contentPane.add(component); + setContentPane(contentPane); + } + + @SuppressWarnings("deprecation") + @Override public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + + if (width == 0 || height == 0) { + return; + } + + content.paintLock(); + try { + if ((bbImage == null) || (width != bbImage.getWidth()) || (height != bbImage.getHeight())) { + boolean createBB = true; + int newW = width; + int newH = height; + if (bbImage != null) { + int oldW = bbImage.getWidth(); + int oldH = bbImage.getHeight(); + if ((oldW >= newW) && (oldH >= newH)) { + createBB = false; + } else { + if (oldW >= newW) { + newW = oldW; + } else { + newW = Math.max((int)(oldW * 1.2), width); + } + if (oldH >= newH) { + newH = oldH; + } else { + newH = Math.max((int)(oldH * 1.2), height); + } + } + } + if (createBB) { + BufferedImage oldBB = bbImage; + bbImage = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB_PRE); + if (oldBB != null) { + Graphics g = bbImage.getGraphics(); + try { + g.drawImage(oldBB, 0, 0, newW, newH, null); + } finally { + g.dispose(); + oldBB.flush(); + } + } + DataBufferInt dataBuf = (DataBufferInt)bbImage.getRaster().getDataBuffer(); + content.imageBufferReset(dataBuf.getData(), 0, 0, width, height, bbImage.getWidth()); + } else { + content.imageReshaped(0, 0, width, height); + } + } + } finally { + content.paintUnlock(); + } + } + + @Override + public JRootPane getRootPane() { + return rootPane; + } + + @Override + public void setContentPane(Container contentPane) { + getRootPane().setContentPane(contentPane); + } + + @Override + public Container getContentPane() { + return getRootPane().getContentPane(); + } + + @Override + public void setLayeredPane(JLayeredPane layeredPane) { + getRootPane().setLayeredPane(layeredPane); + } + + @Override + public JLayeredPane getLayeredPane() { + return getRootPane().getLayeredPane(); + } + + @Override + public void setGlassPane(Component glassPane) { + getRootPane().setGlassPane(glassPane); + } + + @Override + public Component getGlassPane() { + return getRootPane().getGlassPane(); + } +} diff --git a/jdk/src/share/classes/sun/swing/LightweightContent.java b/jdk/src/share/classes/sun/swing/LightweightContent.java new file mode 100644 index 00000000000..2d443fba23c --- /dev/null +++ b/jdk/src/share/classes/sun/swing/LightweightContent.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2013, 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.swing; + +import javax.swing.JComponent; + +/** + * The interface by means of which the {@link JLightweightFrame} class + * communicates to its client application. + *

    + * The client application implements this interface so it can response + * to requests and process notifications from {@code JLightweightFrame}. + * An implementation of this interface is associated with a {@code + * JLightweightFrame} instance via the {@link JLightweightFrame#setContent} + * method. + * + * A hierarchy of components contained in the {@code JComponent} instance + * returned by the {@link #getComponent} method should not contain any + * heavyweight components, otherwise {@code JLightweightFrame} may fail + * to paint it. + * + * @author Artem Ananiev + * @author Anton Tarasov + * @author Jim Graham + */ +public interface LightweightContent { + + /** + * The client application overrides this method to return the {@code + * JComponent} instance which the {@code JLightweightFrame} container + * will paint as its lightweight content. A hierarchy of components + * contained in this component should not contain any heavyweight objects. + * + * @return the component to paint + */ + public JComponent getComponent(); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that it acquires the paint lock. The client application + * should implement the locking mechanism in order to synchronize access + * to the content image data, shared between {@code JLightweightFrame} + * and the client application. + * + * @see #paintUnlock + */ + public void paintLock(); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that it releases the paint lock. The client application + * should implement the locking mechanism in order to synchronize access + * to the content image data, shared between {@code JLightweightFrame} + * and the client application. + * + * @see #paintLock + */ + public void paintUnlock(); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that a new data buffer has been set as a content pixel + * buffer. Typically this occurs when a buffer of a larger size is + * created in response to a content resize event. The method reports + * a reference to the pixel data buffer, the content image bounds + * within the buffer and the line stride of the buffer. These values + * have the following correlation. + *

    + * The {@code width} and {@code height} matches the size of the content + * (the component returned from the {@link #getComponent} method). The + * {@code x} and {@code y} is the origin of the content, {@code (0, 0)} + * in the coordinate space of the content, appearing at + * {@code data[y * linestride + x]} in the buffer. All indices + * {@code data[(y + j) * linestride + (x + i)]} where + * {@code (0 <= i < width)} and {@code (0 <= j < height)} will represent + * valid pixel data, {@code (i, j)} in the coordinate space of the content. + * + * @param data the content pixel data buffer of INT_ARGB_PRE type + * @param x the x coordinate of the image + * @param y the y coordinate of the image + * @param width the width of the image + * @param height the height of the image + * @param linestride the line stride of the pixel buffer + */ + public void imageBufferReset(int[] data, + int x, int y, + int width, int height, + int linestride); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that the content image bounds have been changed within the + * image's pixel buffer. + * + * @param x the x coordinate of the image + * @param y the y coordinate of the image + * @param width the width of the image + * @param height the height of the image + * + * @see #imageBufferReset + */ + public void imageReshaped(int x, int y, int width, int height); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that a part of the content image, or the whole image has + * been updated. The method reports bounds of the rectangular dirty region. + * The {@code dirtyX} and {@code dirtyY} is the origin of the dirty + * rectangle, which is relative to the origin of the content, appearing + * at {@code data[(y + dirtyY] * linestride + (x + dirtyX)]} in the pixel + * buffer (see {@link #imageBufferReset}). All indices + * {@code data[(y + dirtyY + j) * linestride + (x + dirtyX + i)]} where + * {@code (0 <= i < dirtyWidth)} and {@code (0 <= j < dirtyHeight)} + * will represent valid pixel data, {@code (i, j)} in the coordinate space + * of the dirty rectangle. + * + * @param dirtyX the x coordinate of the dirty rectangle, + * relative to the image origin + * @param dirtyY the y coordinate of the dirty rectangle, + * relative to the image origin + * @param dirtyWidth the width of the dirty rectangle + * @param dirtyHeight the height of the dirty rectangle + * + * @see #imageBufferReset + * @see #imageReshaped + */ + public void imageUpdated(int dirtyX, int dirtyY, + int dirtyWidth, int dirtyHeight); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that the frame has grabbed focus. + */ + public void focusGrabbed(); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that the frame has ungrabbed focus. + */ + public void focusUngrabbed(); +} diff --git a/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java b/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java index fdefb1047ce..0c540b17855 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java @@ -641,4 +641,6 @@ class XFramePeer extends XDecoratedPeer implements FramePeer { public Rectangle getBoundsPrivate() { return getBounds(); } + + public void emulateActivation(boolean doActivate) {} } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java index 7c40e8260ef..b4fb9c76f17 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -419,6 +419,10 @@ public final class XToolkit extends UNIXToolkit implements Runnable { return peer; } + public FramePeer createLightweightFrame(LightweightFrame target) { + return null; + } + public FramePeer createFrame(Frame target) { FramePeer peer = new XFramePeer(target); targetCreatedPeer(target, peer); diff --git a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java index b0f9cd3279d..ba6ae8aefb2 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java +++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java @@ -226,15 +226,15 @@ public class WEmbeddedFrame extends EmbeddedFrame { } @SuppressWarnings("deprecation") - public void synthesizeWindowActivation(final boolean doActivate) { - if (!doActivate || EventQueue.isDispatchThread()) { - ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate); + public void synthesizeWindowActivation(final boolean activate) { + if (!activate || EventQueue.isDispatchThread()) { + ((WFramePeer)getPeer()).emulateActivation(activate); } else { // To avoid focus concurrence b/w IE and EmbeddedFrame // activation is postponed by means of posting it to EDT. EventQueue.invokeLater(new Runnable() { public void run() { - ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true); + ((WFramePeer)getPeer()).emulateActivation(true); } }); } diff --git a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java index 3b6d298bda8..ec551e30ced 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java @@ -65,8 +65,6 @@ public class WEmbeddedFramePeer extends WFramePeer { public native Rectangle getBoundsPrivate(); - public native void synthesizeWmActivate(boolean doActivate); - @Override public boolean isAccelCapable() { // REMIND: Temp workaround for issues with using HW acceleration diff --git a/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java b/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java index 368b8f60696..588b3caebdd 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java @@ -200,4 +200,11 @@ class WFramePeer extends WWindowPeer implements FramePeer { public Rectangle getBoundsPrivate() { return getBounds(); } + + // TODO: implement it in peers. WLightweightFramePeer may implement lw version. + public void emulateActivation(boolean activate) { + synthesizeWmActivate(activate); + } + + private native void synthesizeWmActivate(boolean activate); } diff --git a/jdk/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java b/jdk/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java new file mode 100644 index 00000000000..c2c1604bef4 --- /dev/null +++ b/jdk/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013, 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.awt.windows; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.event.ComponentEvent; +import java.awt.event.MouseEvent; + +import sun.awt.LightweightFrame; + +public class WLightweightFramePeer extends WFramePeer { + + public WLightweightFramePeer(LightweightFrame target) { + super(target); + } + + private LightweightFrame getLwTarget() { + return (LightweightFrame)target; + } + + @Override + public Graphics getGraphics() { + return getLwTarget().getGraphics(); + } + + @Override + public void show() { + super.show(); + postEvent(new ComponentEvent((Component)getTarget(), ComponentEvent.COMPONENT_SHOWN)); + } + + @Override + public void hide() { + super.hide(); + postEvent(new ComponentEvent((Component)getTarget(), ComponentEvent.COMPONENT_HIDDEN)); + } + + @Override + public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + postEvent(new ComponentEvent((Component) getTarget(), ComponentEvent.COMPONENT_MOVED)); + postEvent(new ComponentEvent((Component) getTarget(), ComponentEvent.COMPONENT_RESIZED)); + } + + @Override + public void handleEvent(java.awt.AWTEvent e) { + if (e.getID() == MouseEvent.MOUSE_PRESSED) { + emulateActivation(true); + } + super.handleEvent(e); + } + + @Override + public void grab() { + getLwTarget().grabFocus(); + } + + @Override + public void ungrab() { + getLwTarget().ungrabFocus(); + } +} diff --git a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java index afbdfa6c1f9..e87b0ad8c08 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java +++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java @@ -37,6 +37,7 @@ import java.beans.PropertyChangeListener; import java.security.AccessController; import java.security.PrivilegedAction; import sun.awt.AWTAutoShutdown; +import sun.awt.LightweightFrame; import sun.awt.SunToolkit; import sun.awt.Win32GraphicsDevice; import sun.awt.Win32GraphicsEnvironment; @@ -398,6 +399,12 @@ public class WToolkit extends SunToolkit implements Runnable { return peer; } + public FramePeer createLightweightFrame(LightweightFrame target) { + FramePeer peer = new WLightweightFramePeer(target); + targetCreatedPeer(target, peer); + return peer; + } + public CanvasPeer createCanvas(Canvas target) { CanvasPeer peer = new WCanvasPeer(target); targetCreatedPeer(target, peer); diff --git a/jdk/src/windows/native/sun/windows/awt_Frame.cpp b/jdk/src/windows/native/sun/windows/awt_Frame.cpp index da1df839535..41c5624f001 100644 --- a/jdk/src/windows/native/sun/windows/awt_Frame.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Frame.cpp @@ -105,6 +105,7 @@ AwtFrame::AwtFrame() { m_parentWnd = NULL; menuBar = NULL; m_isEmbedded = FALSE; + m_isLightweight = FALSE; m_ignoreWmSize = FALSE; m_isMenuDropped = FALSE; m_isInputMethodWindow = FALSE; @@ -170,14 +171,13 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) * area of the browser is a Java Frame for parenting purposes, but * really a Windows child window */ + BOOL isEmbeddedInstance = FALSE; + BOOL isEmbedded = FALSE; cls = env->FindClass("sun/awt/EmbeddedFrame"); - if (cls == NULL) { - return NULL; + if (cls) { + isEmbeddedInstance = env->IsInstanceOf(target, cls); } INT_PTR handle; - jboolean isEmbeddedInstance = env->IsInstanceOf(target, cls); - jboolean isEmbedded = FALSE; - if (isEmbeddedInstance) { handle = static_cast(env->GetLongField(target, AwtFrame::handleID)); if (handle != 0) { @@ -186,6 +186,13 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) } frame->m_isEmbedded = isEmbedded; + BOOL isLightweight = FALSE; + cls = env->FindClass("sun/awt/LightweightFrame"); + if (cls) { + isLightweight = env->IsInstanceOf(target, cls); + } + frame->m_isLightweight = isLightweight; + if (isEmbedded) { hwndParent = (HWND)handle; RECT rect; @@ -230,6 +237,23 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) rect.bottom-rect.top); frame->InitPeerGraphicsConfig(env, self); AwtToolkit::GetInstance().RegisterEmbedderProcessId(hwndParent); + } else if (isLightweight) { + frame->m_isUndecorated = true; + frame->m_peerObject = env->NewGlobalRef(self); + frame->RegisterClass(); + + DWORD exStyle = 0; + DWORD style = WS_POPUP; + + frame->CreateHWnd(env, L"", + style, + exStyle, + 0, 0, 0, 0, + 0, + NULL, + ::GetSysColor(COLOR_WINDOWTEXT), + ::GetSysColor(COLOR_WINDOWFRAME), + self); } else { jint state = env->CallIntMethod(self, AwtFrame::getExtendedStateMID); DWORD exStyle; @@ -345,16 +369,20 @@ LRESULT AwtFrame::ProxyWindowProc(UINT message, WPARAM wParam, LPARAM lParam, Ms case WM_SETFOCUS: if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain - if (!sm_suppressFocusAndActivation && IsEmbeddedFrame()) { - AwtSetActiveWindow(); + if (!sm_suppressFocusAndActivation) { + if (IsLightweightFrame() || IsEmbeddedFrame()) { + AwtSetActiveWindow(); + } } mr = mrConsume; break; case WM_KILLFOCUS: if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain - if (!sm_suppressFocusAndActivation && IsEmbeddedFrame()) { - AwtWindow::SynthesizeWmActivate(FALSE, GetHWnd(), NULL); + if (!sm_suppressFocusAndActivation) { + if (IsLightweightFrame() || IsEmbeddedFrame()) { + AwtWindow::SynthesizeWmActivate(FALSE, GetHWnd(), NULL); + } } else if (sm_restoreFocusAndActivation) { if (AwtComponent::GetFocusedWindow() != NULL) { @@ -640,6 +668,10 @@ AwtFrame::Show() HWND hwnd = GetHWnd(); JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + if (IsLightweightFrame()) { + return; + } + DTRACE_PRINTLN3("AwtFrame::Show:%s%s%s", m_iconic ? " iconic" : "", m_zoomed ? " zoomed" : "", @@ -992,6 +1024,9 @@ BOOL AwtFrame::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest) // b) focus is requested to some of the frame's child. m_actualFocusedWindow = NULL; } + if (IsLightweightFrame()) { + return TRUE; + } return AwtWindow::AwtSetActiveWindow(isMouseEventCause); } @@ -1873,7 +1908,7 @@ Java_sun_awt_windows_WEmbeddedFramePeer_getBoundsPrivate(JNIEnv *env, jobject se } JNIEXPORT void JNICALL -Java_sun_awt_windows_WEmbeddedFramePeer_synthesizeWmActivate(JNIEnv *env, jobject self, jboolean doActivate) +Java_sun_awt_windows_WFramePeer_synthesizeWmActivate(JNIEnv *env, jobject self, jboolean doActivate) { TRY; diff --git a/jdk/src/windows/native/sun/windows/awt_Frame.h b/jdk/src/windows/native/sun/windows/awt_Frame.h index f6d692b87eb..e151c17c2a5 100644 --- a/jdk/src/windows/native/sun/windows/awt_Frame.h +++ b/jdk/src/windows/native/sun/windows/awt_Frame.h @@ -72,6 +72,8 @@ public: /* Returns whether this frame is embedded in an external native frame. */ INLINE BOOL IsEmbeddedFrame() { return m_isEmbedded; } + /* Returns whether this frame is lightweight. */ + INLINE virtual BOOL IsLightweightFrame() { return m_isLightweight; } INLINE BOOL IsSimpleWindow() { return FALSE; } @@ -169,6 +171,9 @@ private: /* The frame is an EmbeddedFrame. */ BOOL m_isEmbedded; + /* The frame is a LightweightFrame */ + BOOL m_isLightweight; + /* used so that calls to ::MoveWindow in SetMenuBar don't propogate because they are immediately followed by calls to Component.resize */ BOOL m_ignoreWmSize; diff --git a/jdk/src/windows/native/sun/windows/awt_Window.h b/jdk/src/windows/native/sun/windows/awt_Window.h index 8ad2b0902b2..0ee23322d4b 100644 --- a/jdk/src/windows/native/sun/windows/awt_Window.h +++ b/jdk/src/windows/native/sun/windows/awt_Window.h @@ -143,6 +143,7 @@ public: INLINE HICON GetHIcon() {return m_hIcon;}; INLINE HICON GetHIconSm() {return m_hIconSm;}; INLINE BOOL IsIconInherited() {return m_iconInherited;}; + INLINE virtual BOOL IsLightweightFrame() {return FALSE;} /* Post events to the EventQueue */ void SendComponentEvent(jint eventId); @@ -193,8 +194,10 @@ public: // Execute on Toolkit only. INLINE static LRESULT SynthesizeWmActivate(BOOL doActivate, HWND targetHWnd, HWND oppositeHWnd) { + AwtWindow *win = static_cast(AwtComponent::GetComponent(targetHWnd)); if (doActivate && - (!::IsWindowVisible(targetHWnd) || ::IsIconic(::GetAncestor(targetHWnd, GA_ROOT)))) + (!::IsWindowVisible(targetHWnd) || ::IsIconic(::GetAncestor(targetHWnd, GA_ROOT))) && + (win == NULL || !win->IsLightweightFrame())) { // The activation is rejected if either: // - The toplevel is not visible From 3cc83d24adb47c31e1deba1ef1b8586a0d64a495 Mon Sep 17 00:00:00 2001 From: Jennifer Godinez Date: Fri, 22 Feb 2013 11:01:23 -0800 Subject: [PATCH 057/102] 8006110: pageDialog is showing the swing dialog with DialogTypeSelection.NATIVE Reviewed-by: bae, prr --- .../classes/sun/print/RasterPrinterJob.java | 169 ++++++++++-------- 1 file changed, 96 insertions(+), 73 deletions(-) diff --git a/jdk/src/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/share/classes/sun/print/RasterPrinterJob.java index 404f66cc26f..24bece595f8 100644 --- a/jdk/src/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/share/classes/sun/print/RasterPrinterJob.java @@ -527,9 +527,92 @@ public abstract class RasterPrinterJob extends PrinterJob { } } + private PageFormat attributeToPageFormat(PrintService service, + PrintRequestAttributeSet attSet) { + PageFormat page = defaultPage(); + + if (service == null) { + return page; + } + + OrientationRequested orient = (OrientationRequested) + attSet.get(OrientationRequested.class); + if (orient == null) { + orient = (OrientationRequested) + service.getDefaultAttributeValue(OrientationRequested.class); + } + if (orient == OrientationRequested.REVERSE_LANDSCAPE) { + page.setOrientation(PageFormat.REVERSE_LANDSCAPE); + } else if (orient == OrientationRequested.LANDSCAPE) { + page.setOrientation(PageFormat.LANDSCAPE); + } else { + page.setOrientation(PageFormat.PORTRAIT); + } + + Media media = (Media)attSet.get(Media.class); + if (media == null) { + media = + (Media)service.getDefaultAttributeValue(Media.class); + } + if (!(media instanceof MediaSizeName)) { + media = MediaSizeName.NA_LETTER; + } + MediaSize size = + MediaSize.getMediaSizeForName((MediaSizeName)media); + if (size == null) { + size = MediaSize.NA.LETTER; + } + Paper paper = new Paper(); + float dim[] = size.getSize(1); //units == 1 to avoid FP error + double w = Math.rint((dim[0]*72.0)/Size2DSyntax.INCH); + double h = Math.rint((dim[1]*72.0)/Size2DSyntax.INCH); + paper.setSize(w, h); + MediaPrintableArea area = + (MediaPrintableArea) + attSet.get(MediaPrintableArea.class); + double ix, iw, iy, ih; + + if (area != null) { + // Should pass in same unit as updatePageAttributes + // to avoid rounding off errors. + ix = Math.rint( + area.getX(MediaPrintableArea.INCH) * DPI); + iy = Math.rint( + area.getY(MediaPrintableArea.INCH) * DPI); + iw = Math.rint( + area.getWidth(MediaPrintableArea.INCH) * DPI); + ih = Math.rint( + area.getHeight(MediaPrintableArea.INCH) * DPI); + } + else { + if (w >= 72.0 * 6.0) { + ix = 72.0; + iw = w - 2 * 72.0; + } else { + ix = w / 6.0; + iw = w * 0.75; + } + if (h >= 72.0 * 6.0) { + iy = 72.0; + ih = h - 2 * 72.0; + } else { + iy = h / 6.0; + ih = h * 0.75; + } + } + paper.setImageableArea(ix, iy, iw, ih); + page.setPaper(paper); + return page; + } protected void updatePageAttributes(PrintService service, PageFormat page) { + updateAttributesWithPageFormat(service, page, this.attributes); + } + + protected void updateAttributesWithPageFormat(PrintService service, + PageFormat page, + PrintRequestAttributeSet attributes) { if (service == null || page == null) { return; } @@ -659,6 +742,18 @@ public abstract class RasterPrinterJob extends PrinterJob { throw new HeadlessException(); } + DialogTypeSelection dlg = + (DialogTypeSelection)attributes.get(DialogTypeSelection.class); + + // Check for native, note that default dialog is COMMON. + if (dlg == DialogTypeSelection.NATIVE) { + PrintService pservice = getPrintService(); + PageFormat page = pageDialog(attributeToPageFormat(pservice, + attributes)); + updateAttributesWithPageFormat(pservice, page, attributes); + return page; + } + final GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().getDefaultConfiguration(); @@ -698,77 +793,7 @@ public abstract class RasterPrinterJob extends PrinterJob { attributes.remove(amCategory); } attributes.addAll(newas); - - PageFormat page = defaultPage(); - - OrientationRequested orient = - (OrientationRequested) - attributes.get(OrientationRequested.class); - int pfOrient = PageFormat.PORTRAIT; - if (orient != null) { - if (orient == OrientationRequested.REVERSE_LANDSCAPE) { - pfOrient = PageFormat.REVERSE_LANDSCAPE; - } else if (orient == OrientationRequested.LANDSCAPE) { - pfOrient = PageFormat.LANDSCAPE; - } - } - page.setOrientation(pfOrient); - - Media media = (Media)attributes.get(Media.class); - if (media == null) { - media = - (Media)service.getDefaultAttributeValue(Media.class); - } - if (!(media instanceof MediaSizeName)) { - media = MediaSizeName.NA_LETTER; - } - MediaSize size = - MediaSize.getMediaSizeForName((MediaSizeName)media); - if (size == null) { - size = MediaSize.NA.LETTER; - } - Paper paper = new Paper(); - float dim[] = size.getSize(1); //units == 1 to avoid FP error - double w = Math.rint((dim[0]*72.0)/Size2DSyntax.INCH); - double h = Math.rint((dim[1]*72.0)/Size2DSyntax.INCH); - paper.setSize(w, h); - MediaPrintableArea area = - (MediaPrintableArea) - attributes.get(MediaPrintableArea.class); - double ix, iw, iy, ih; - - if (area != null) { - // Should pass in same unit as updatePageAttributes - // to avoid rounding off errors. - ix = Math.rint( - area.getX(MediaPrintableArea.INCH) * DPI); - iy = Math.rint( - area.getY(MediaPrintableArea.INCH) * DPI); - iw = Math.rint( - area.getWidth(MediaPrintableArea.INCH) * DPI); - ih = Math.rint( - area.getHeight(MediaPrintableArea.INCH) * DPI); - } - else { - if (w >= 72.0 * 6.0) { - ix = 72.0; - iw = w - 2 * 72.0; - } else { - ix = w / 6.0; - iw = w * 0.75; - } - if (h >= 72.0 * 6.0) { - iy = 72.0; - ih = h - 2 * 72.0; - } else { - iy = h / 6.0; - ih = h * 0.75; - } - } - paper.setImageableArea(ix, iy, iw, ih); - page.setPaper(paper); - - return page; + return attributeToPageFormat(service, attributes); } else { return null; } @@ -795,7 +820,6 @@ public abstract class RasterPrinterJob extends PrinterJob { throw new HeadlessException(); } - DialogTypeSelection dlg = (DialogTypeSelection)attributes.get(DialogTypeSelection.class); @@ -816,7 +840,6 @@ public abstract class RasterPrinterJob extends PrinterJob { } - /* A security check has already been performed in the * java.awt.print.printerJob.getPrinterJob method. * So by the time we get here, it is OK for the current thread From d1643f183326476e986c22393b66a9bdb1137745 Mon Sep 17 00:00:00 2001 From: Jia-Hong Chen Date: Fri, 22 Feb 2013 13:20:16 -0800 Subject: [PATCH 058/102] 8005796: [parfait] Possible uninitialised variable at jdk/src/share/native/sun/java2d/loops/ByteBinary1Bit.c Reviewed-by: prr, vadim, flar --- jdk/src/share/native/sun/java2d/loops/AnyByteBinary.h | 5 ++++- jdk/src/share/native/sun/java2d/loops/ByteIndexed.h | 5 ++++- jdk/src/share/native/sun/java2d/loops/IntArgb.h | 3 ++- jdk/src/share/native/sun/java2d/loops/IntArgbBm.h | 3 ++- jdk/src/share/native/sun/java2d/loops/IntArgbPre.h | 3 ++- jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h | 3 ++- jdk/src/share/native/sun/java2d/loops/UshortIndexed.h | 5 ++++- 7 files changed, 20 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/native/sun/java2d/loops/AnyByteBinary.h b/jdk/src/share/native/sun/java2d/loops/AnyByteBinary.h index abe7f230bee..3b1fa03b06a 100644 --- a/jdk/src/share/native/sun/java2d/loops/AnyByteBinary.h +++ b/jdk/src/share/native/sun/java2d/loops/AnyByteBinary.h @@ -153,7 +153,10 @@ jint PREFIX ## rgb; #define InitByteBinaryAlphaLoadData(TYPE, PREFIX, pRasInfo) \ - PREFIX ## Lut = (pRasInfo)->lutBase + do { \ + PREFIX ## Lut = (pRasInfo)->lutBase; \ + PREFIX ## rgb = 0; \ + } while (0) #define LoadAlphaFromByteBinaryFor4ByteArgb(TYPE, pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/ByteIndexed.h b/jdk/src/share/native/sun/java2d/loops/ByteIndexed.h index 3917c238e48..215cfc0e111 100644 --- a/jdk/src/share/native/sun/java2d/loops/ByteIndexed.h +++ b/jdk/src/share/native/sun/java2d/loops/ByteIndexed.h @@ -202,7 +202,10 @@ typedef jubyte ByteIndexedBmDataType; jint PREFIX ## rgb; #define InitByteIndexedAlphaLoadData(PREFIX, pRasInfo) \ - PREFIX ## Lut = (pRasInfo)->lutBase + do { \ + PREFIX ## Lut = (pRasInfo)->lutBase; \ + PREFIX ## rgb = 0; \ + } while (0) #define LoadAlphaFromByteIndexedFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/IntArgb.h b/jdk/src/share/native/sun/java2d/loops/IntArgb.h index aec63431cb1..f4ec00524cc 100644 --- a/jdk/src/share/native/sun/java2d/loops/IntArgb.h +++ b/jdk/src/share/native/sun/java2d/loops/IntArgb.h @@ -122,7 +122,8 @@ typedef jint IntArgbDataType; #define DeclareIntArgbAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitIntArgbAlphaLoadData(PREFIX, pRasInfo) +#define InitIntArgbAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromIntArgbFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h b/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h index 81d551820a8..675fba1d228 100644 --- a/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h +++ b/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h @@ -133,7 +133,8 @@ typedef jint IntArgbBmDataType; #define DeclareIntArgbBmAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitIntArgbBmAlphaLoadData(PREFIX, pRasInfo) +#define InitIntArgbBmAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromIntArgbBmFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h b/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h index 5ffb9dacb0b..c45013d0e00 100644 --- a/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h +++ b/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h @@ -153,7 +153,8 @@ typedef jint IntArgbPreDataType; #define DeclareIntArgbPreAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitIntArgbPreAlphaLoadData(PREFIX, pRasInfo) +#define InitIntArgbPreAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromIntArgbPreFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h b/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h index 348e03b7df4..aa50d8b0ff3 100644 --- a/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h +++ b/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h @@ -120,7 +120,8 @@ typedef jushort Ushort4444ArgbDataType; #define DeclareUshort4444ArgbAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitUshort4444ArgbAlphaLoadData(PREFIX, pRasInfo) +#define InitUshort4444ArgbAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromUshort4444ArgbFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/UshortIndexed.h b/jdk/src/share/native/sun/java2d/loops/UshortIndexed.h index 7786bda3829..6a4b5b13e5d 100644 --- a/jdk/src/share/native/sun/java2d/loops/UshortIndexed.h +++ b/jdk/src/share/native/sun/java2d/loops/UshortIndexed.h @@ -170,7 +170,10 @@ typedef jushort UshortIndexedBmDataType; jint PREFIX ## rgb; #define InitUshortIndexedAlphaLoadData(PREFIX, pRasInfo) \ - PREFIX ## Lut = (pRasInfo)->lutBase + do { \ + PREFIX ## Lut = (pRasInfo)->lutBase; \ + PREFIX ## rgb = 0; \ + } while (0) #define LoadAlphaFromUshortIndexedFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ From 68d2d95f008bec155e83626b06d42584b3eb1bea Mon Sep 17 00:00:00 2001 From: Petr Pchelko Date: Mon, 25 Feb 2013 10:17:25 +0000 Subject: [PATCH 059/102] 8006634: Unify LWCToolkit.invokeAndWait() and sun.awt.datatransfer.ToolkitThreadBlockedHandler Changed the logic for the nested event loops and deleted deadlock detection Reviewed-by: art, denis --- .../sun/lwawt/macosx/CPlatformWindow.java | 12 +- .../macosx/CToolkitThreadBlockedHandler.java | 32 ++--- .../classes/sun/lwawt/macosx/LWCToolkit.java | 99 ++++++---------- jdk/src/macosx/native/sun/awt/AWTView.m | 6 +- .../native/sun/awt/ApplicationDelegate.m | 5 +- jdk/src/macosx/native/sun/awt/CClipboard.m | 8 +- jdk/src/macosx/native/sun/awt/CDropTarget.m | 3 +- jdk/src/macosx/native/sun/awt/CMenu.m | 10 +- jdk/src/macosx/native/sun/awt/CMenuBar.m | 8 +- jdk/src/macosx/native/sun/awt/CMenuItem.m | 2 +- .../sun/awt/JavaComponentAccessibility.m | 24 ++-- jdk/src/macosx/native/sun/awt/LWCToolkit.m | 52 +++------ .../native/sun/osxapp/ThreadUtilities.h | 9 +- .../native/sun/osxapp/ThreadUtilities.m | 109 ------------------ 14 files changed, 113 insertions(+), 266 deletions(-) diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index dc51373cc1b..3fb585bdb53 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -30,6 +30,7 @@ import java.awt.Dialog.ModalityType; import java.awt.event.*; import java.awt.peer.WindowPeer; import java.beans.*; +import java.lang.reflect.InvocationTargetException; import java.util.List; import javax.swing.*; @@ -861,7 +862,16 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo private void flushBuffers() { if (isVisible() && !nativeBounds.isEmpty()) { - LWCToolkit.getLWCToolkit().flushPendingEventsOnAppkit(target); + try { + LWCToolkit.invokeAndWait(new Runnable() { + @Override + public void run() { + //Posting an empty to flush the EventQueue without blocking the main thread + } + }, target); + } catch (InterruptedException | InvocationTargetException e) { + e.printStackTrace(); + } } } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java index 94a74e5174b..6bc6cc7c41b 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java @@ -25,27 +25,33 @@ package sun.lwawt.macosx; +import sun.awt.Mutex; import sun.awt.datatransfer.ToolkitThreadBlockedHandler; -final class CToolkitThreadBlockedHandler implements ToolkitThreadBlockedHandler { - private final LWCToolkit toolkit = (LWCToolkit)java.awt.Toolkit.getDefaultToolkit(); +final class CToolkitThreadBlockedHandler extends Mutex implements ToolkitThreadBlockedHandler { + private long awtRunLoopMediator = 0; + private final boolean processEvents; - public void lock() { - } - - public void unlock() { - } - - protected boolean isOwned() { - return false; + CToolkitThreadBlockedHandler() { + super(); + this.processEvents = true; } public void enter() { - // Execute the next AppKit event while we are waiting for system to - // finish our request - this will save us from biting our own tail - toolkit.executeNextAppKitEvent(); + if (!isOwned()) { + throw new IllegalMonitorStateException(); + } + awtRunLoopMediator = LWCToolkit.createAWTRunLoopMediator(); + unlock(); + LWCToolkit.doAWTRunLoop(awtRunLoopMediator, processEvents); + lock(); } public void exit() { + if (!isOwned()) { + throw new IllegalMonitorStateException(); + } + LWCToolkit.stopAWTRunLoop(awtRunLoopMediator); + awtRunLoopMediator = 0; } } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 801c3d41605..83bc9f1f700 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -63,8 +63,6 @@ public final class LWCToolkit extends LWToolkit { private static native void initIDs(); - static native void executeNextAppKitEvent(); - private static CInputMethodDescriptor sInputMethodDescriptor; static { @@ -502,30 +500,6 @@ public final class LWCToolkit extends LWToolkit { synchronized(ret) { return ret[0]; } } - /** - * Just a wrapper for LWCToolkit.invokeAndWait. Posts an empty event to the - * appropriate event queue and waits for it to finish. - */ - public static void flushPendingEventsOnAppkit(final Component component) { - try { - invokeAndWait(new Runnable() { - @Override - public void run() { - } - }, component); - } catch (Exception e) { - e.printStackTrace(); - } - } - - // Kicks an event over to the appropriate eventqueue and waits for it to finish - // To avoid deadlocking, we manually run the NSRunLoop while waiting - // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop - // The CInvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop - public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException { - invokeAndWait(event, component, true); - } - public static T invokeAndWait(final Callable callable, Component component) throws Exception { final CallableWrapper wrapper = new CallableWrapper(callable); invokeAndWait(wrapper, component); @@ -555,10 +529,27 @@ public final class LWCToolkit extends LWToolkit { } } - public static void invokeAndWait(Runnable event, Component component, boolean detectDeadlocks) throws InterruptedException, InvocationTargetException { - long mediator = createAWTRunLoopMediator(); + // Kicks an event over to the appropriate eventqueue and waits for it to finish + // To avoid deadlocking, we manually run the NSRunLoop while waiting + // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop + // The InvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop + // Does not dispatch native events while in the loop + public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException { + final long mediator = createAWTRunLoopMediator(); - InvocationEvent invocationEvent = new CPeerEvent(event, mediator); + InvocationEvent invocationEvent = + new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event) { + @Override + public void dispatch() { + try { + super.dispatch(); + } finally { + if (mediator != 0) { + stopAWTRunLoop(mediator); + } + } + } + }; if (component != null) { AppContext appContext = SunToolkit.targetToAppContext(component); @@ -571,7 +562,7 @@ public final class LWCToolkit extends LWToolkit { ((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent); } - doAWTRunLoop(mediator, true, detectDeadlocks); + doAWTRunLoop(mediator, false); Throwable eventException = invocationEvent.getException(); if (eventException != null) { @@ -583,7 +574,8 @@ public final class LWCToolkit extends LWToolkit { } public static void invokeLater(Runnable event, Component component) throws InvocationTargetException { - final InvocationEvent invocationEvent = new CPeerEvent(event, 0); + final InvocationEvent invocationEvent = + new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event); if (component != null) { final AppContext appContext = SunToolkit.targetToAppContext(component); @@ -688,31 +680,6 @@ public final class LWCToolkit extends LWToolkit { return false; } - // Extends PeerEvent because we want to pass long an ObjC mediator object and because we want these events to be posted early - // Typically, rather than relying on the notifier to call notifyAll(), we use the mediator to stop the runloop - public static class CPeerEvent extends PeerEvent { - private long _mediator = 0; - - public CPeerEvent(Runnable runnable, long mediator) { - super(Toolkit.getDefaultToolkit(), runnable, null, true, 0); - _mediator = mediator; - } - - public void dispatch() { - try { - super.dispatch(); - } finally { - if (_mediator != 0) { - LWCToolkit.stopAWTRunLoop(_mediator); - } - } - } - } - - // Call through to native methods - public static void doAWTRunLoop(long mediator, boolean awtMode) { doAWTRunLoop(mediator, awtMode, true); } - public static void doAWTRunLoop(long mediator) { doAWTRunLoop(mediator, true); } - private static Boolean sunAwtDisableCALayers = null; /** @@ -737,12 +704,20 @@ public final class LWCToolkit extends LWToolkit { * Native methods section ************************/ - // These are public because they are accessed from WebKitPluginObject in JavaDeploy - // Basic usage: - // createAWTRunLoopMediator. Start client code on another thread. doAWTRunLoop. When client code is finished, stopAWTRunLoop. - public static native long createAWTRunLoopMediator(); - public static native void doAWTRunLoop(long mediator, boolean awtMode, boolean detectDeadlocks); - public static native void stopAWTRunLoop(long mediator); + static native long createAWTRunLoopMediator(); + /** + * Method to run a nested run-loop. The nested loop is spinned in the javaRunLoop mode, so selectors sent + * by [JNFRunLoop performOnMainThreadWaiting] are processed. + * @param mediator a native pointer to the mediator object created by createAWTRunLoopMediator + * @param processEvents if true - dispatches event while in the nested loop. Used in DnD. + * Additional attention is needed when using this feature as we short-circuit normal event + * processing which could break Appkit. + * (One known example is when the window is resized with the mouse) + * + * if false - all events come after exit form the nested loop + */ + static native void doAWTRunLoop(long mediator, boolean processEvents); + static native void stopAWTRunLoop(long mediator); private native boolean nativeSyncQueue(long timeout); diff --git a/jdk/src/macosx/native/sun/awt/AWTView.m b/jdk/src/macosx/native/sun/awt/AWTView.m index cc16a2026ee..7e1f248c7ed 100644 --- a/jdk/src/macosx/native/sun/awt/AWTView.m +++ b/jdk/src/macosx/native/sun/awt/AWTView.m @@ -227,7 +227,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void) mouseMoved: (NSEvent *)event { // TODO: better way to redirect move events to the "under" view - + NSPoint eventLocation = [event locationInWindow]; NSPoint localPoint = [self convertPoint: eventLocation fromView: nil]; @@ -668,7 +668,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void) setDropTarget:(CDropTarget *)target { self._dropTarget = target; - [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) onObject:self._dropTarget withObject:nil waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) on:self._dropTarget withObject:nil waitUntilDone:YES]; } /******************************** BEGIN NSDraggingSource Interface ********************************/ @@ -1215,7 +1215,7 @@ JNF_CLASS_CACHE(jc_CInputMethod, "sun/lwawt/macosx/CInputMethod"); fprintf(stderr, "AWTView InputMethod Selector Called : [abandonInput]\n"); #endif // IM_DEBUG - [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) onObject:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) on:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES]; [self unmarkText]; } diff --git a/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m b/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m index 9a5aee94d44..6b584b21ca3 100644 --- a/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m +++ b/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m @@ -567,10 +567,9 @@ JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeRegisterForNo { JNF_COCOA_ENTER(env); [ThreadUtilities performOnMainThread:@selector(_registerForNotification:) - onObject:[ApplicationDelegate class] + on:[ApplicationDelegate class] withObject:[NSNumber numberWithInt:notificationType] - waitUntilDone:NO - awtMode:NO]; // AWT_THREADING Safe (non-blocking) + waitUntilDone:NO]; // AWT_THREADING Safe (non-blocking) JNF_COCOA_EXIT(env); } diff --git a/jdk/src/macosx/native/sun/awt/CClipboard.m b/jdk/src/macosx/native/sun/awt/CClipboard.m index fb300f72971..bfba06b47d1 100644 --- a/jdk/src/macosx/native/sun/awt/CClipboard.m +++ b/jdk/src/macosx/native/sun/awt/CClipboard.m @@ -120,7 +120,7 @@ static CClipboard *sClipboard = nil; fClipboardOwner = JNFNewGlobalRef(inEnv, inClipboard); } } - [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) onObject:self withObject:inTypes waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) on:self withObject:inTypes waitUntilDone:YES]; } - (void) _nativeDeclareTypes:(NSArray *)inTypes { @@ -135,7 +135,7 @@ static CClipboard *sClipboard = nil; - (NSArray *) javaGetTypes { NSMutableArray *args = [NSMutableArray arrayWithCapacity:1]; - [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) on:self withObject:args waitUntilDone:YES]; //NSLog(@"CClipboard getTypes returns %@", [args lastObject]); return [args lastObject]; @@ -152,7 +152,7 @@ static CClipboard *sClipboard = nil; - (void) javaSetData:(NSData *)inData forType:(NSString *) inFormat { CClipboardUpdate *newUpdate = [[CClipboardUpdate alloc] initWithData:inData withFormat:inFormat]; - [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) onObject:self withObject:newUpdate waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) on:self withObject:newUpdate waitUntilDone:YES]; [newUpdate release]; //NSLog(@"CClipboard javaSetData forType %@", inFormat); @@ -170,7 +170,7 @@ static CClipboard *sClipboard = nil; - (NSData *) javaGetDataForType:(NSString *) inFormat { NSMutableArray *args = [NSMutableArray arrayWithObject:inFormat]; - [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) on:self withObject:args waitUntilDone:YES]; //NSLog(@"CClipboard javaGetDataForType %@ returns an NSData", inFormat); return [args lastObject]; diff --git a/jdk/src/macosx/native/sun/awt/CDropTarget.m b/jdk/src/macosx/native/sun/awt/CDropTarget.m index 60cd7818254..9dda8ae3551 100644 --- a/jdk/src/macosx/native/sun/awt/CDropTarget.m +++ b/jdk/src/macosx/native/sun/awt/CDropTarget.m @@ -390,8 +390,7 @@ extern JNFClassInfo jc_CDropTargetContextPeer; // Release dragging data if any when Java's AWT event thread is all finished. // Make sure dragging data is released on the native event thread. - [ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) onObject:self - withObject:draggingSequenceNumberID waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) on:self withObject:draggingSequenceNumberID waitUntilDone:NO]; } - (jint)currentJavaActions { diff --git a/jdk/src/macosx/native/sun/awt/CMenu.m b/jdk/src/macosx/native/sun/awt/CMenu.m index e6325c2c3db..8b643b3bca0 100644 --- a/jdk/src/macosx/native/sun/awt/CMenu.m +++ b/jdk/src/macosx/native/sun/awt/CMenu.m @@ -55,11 +55,11 @@ AWT_ASSERT_APPKIT_THREAD; //- (void)finalize { [super finalize]; } - (void)addJavaSubmenu:(CMenu *)submenu { - [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) onObject:self withObject:submenu waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:submenu waitUntilDone:YES]; } - (void)addJavaMenuItem:(CMenuItem *)theMenuItem { - [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) onObject:self withObject:theMenuItem waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:theMenuItem waitUntilDone:YES]; } - (void)addNativeItem_OnAppKitThread:(CMenuItem *)itemModified { @@ -70,7 +70,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void)setJavaMenuTitle:(NSString *)title { if (title) { - [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) onObject:self withObject:title waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) on:self withObject:title waitUntilDone:YES]; } } @@ -93,7 +93,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void)deleteJavaItem:(jint)index { - [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) onObject:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES]; } - (void)deleteNativeJavaItem_OnAppKitThread:(NSNumber *)number { @@ -139,7 +139,7 @@ CMenu * createCMenu (jobject cPeerObjGlobal) { // We use an array here only to be able to get a return value NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) onObject:[CMenu alloc] withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES]; aCMenu = (CMenu *)[args objectAtIndex: 0]; diff --git a/jdk/src/macosx/native/sun/awt/CMenuBar.m b/jdk/src/macosx/native/sun/awt/CMenuBar.m index 23c79496189..b0d67f71a2a 100644 --- a/jdk/src/macosx/native/sun/awt/CMenuBar.m +++ b/jdk/src/macosx/native/sun/awt/CMenuBar.m @@ -197,7 +197,7 @@ static BOOL sSetupHelpMenu = NO; if (self == sActiveMenuBar) { NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:-1], nil]; - [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES]; [args release]; } } @@ -216,7 +216,7 @@ static BOOL sSetupHelpMenu = NO; if (self == sActiveMenuBar) { NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:index], nil]; - [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES]; [args release]; } } @@ -286,7 +286,7 @@ static BOOL sSetupHelpMenu = NO; - (void) javaDeleteMenu: (jint)index { if (self == sActiveMenuBar) { - [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) onObject:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES]; } @synchronized(self) { @@ -388,7 +388,7 @@ Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar // We use an array here only to be able to get a return value NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) onObject:[CMenuBar alloc] withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES]; aCMenuBar = (CMenuBar *)[args objectAtIndex: 0]; diff --git a/jdk/src/macosx/native/sun/awt/CMenuItem.m b/jdk/src/macosx/native/sun/awt/CMenuItem.m index 2281d8bcd95..b67c70658dd 100644 --- a/jdk/src/macosx/native/sun/awt/CMenuItem.m +++ b/jdk/src/macosx/native/sun/awt/CMenuItem.m @@ -386,7 +386,7 @@ JNF_COCOA_ENTER(env); args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO], nil]; } - [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) onObject:[CMenuItem alloc] withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES]; aCMenuItem = (CMenuItem *)[args objectAtIndex: 0]; diff --git a/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m b/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m index f886c4afbe1..a01bd781faa 100644 --- a/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m +++ b/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m @@ -1113,18 +1113,10 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv *env = [ThreadUtilities getJNIEnv]; id value = nil; - // This code frequently gets called indirectly by Java when VoiceOver is active. - // Basically, we just have to know when we going to be a bad state, and do something "special". - // Note that while NSApplication isn't technically correct, we post a focus changed notification - // (which will call this method, but with the correct codepath) shortly afterwards. See +postFocusChanged. - if (sInPerformFromJava) { - return [NSApplication sharedApplication]; - } else { - jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) - if (focused != NULL) { - if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { - value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; - } + jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) + if (focused != NULL) { + if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { + value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; } } @@ -1149,7 +1141,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessibility_focusChanged { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(postFocusChanged:) onObject:[JavaComponentAccessibility class] withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(postFocusChanged:) on:[JavaComponentAccessibility class] withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } @@ -1164,7 +1156,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_valueChanged (JNIEnv *env, jclass jklass, jlong element) { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(postValueChanged) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(postValueChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } @@ -1177,7 +1169,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_selectionChanged (JNIEnv *env, jclass jklass, jlong element) { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } @@ -1191,7 +1183,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_unregisterFromCocoaAXSy (JNIEnv *env, jclass jklass, jlong element) { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } diff --git a/jdk/src/macosx/native/sun/awt/LWCToolkit.m b/jdk/src/macosx/native/sun/awt/LWCToolkit.m index 45c546181f0..ec4870eba69 100644 --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m @@ -332,7 +332,7 @@ AWT_ASSERT_APPKIT_THREAD; * Signature: (JZZ)V */ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoop -(JNIEnv *env, jclass clz, jlong mediator, jboolean awtMode, jboolean detectDeadlocks) +(JNIEnv *env, jclass clz, jlong mediator, jboolean processEvents) { AWT_ASSERT_APPKIT_THREAD; JNF_COCOA_ENTER(env); @@ -341,26 +341,25 @@ JNF_COCOA_ENTER(env); if (mediatorObject == nil) return; - if (!sInPerformFromJava || !detectDeadlocks) { + // Don't use acceptInputForMode because that doesn't setup autorelease pools properly + BOOL isRunning = true; + while (![mediatorObject shouldEndRunLoop] && isRunning) { + isRunning = [[NSRunLoop currentRunLoop] runMode:[JNFRunLoop javaRunLoopMode] + beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]]; + if (processEvents) { + //We do not spin a runloop here as date is nil, so does not matter which mode to use + NSEvent *event; + if ((event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:YES]) != nil) { + [NSApp sendEvent:event]; + } - NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; - NSDate *distantFuture = [NSDate distantFuture]; - NSString *mode = (awtMode) ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode; - - BOOL isRunning = YES; - while (isRunning && ![mediatorObject shouldEndRunLoop]) { - // Don't use acceptInputForMode because that doesn't setup autorelease pools properly - isRunning = [currentRunLoop runMode:mode beforeDate:distantFuture]; } - } -#ifndef PRODUCT_BUILD - if (sInPerformFromJava) { - NSLog(@"Apple AWT: Short-circuiting CToolkit.invokeAndWait trampoline deadlock!!!!!"); - NSLog(@"\tPlease file a bug report with this message and a reproducible test case."); - } -#endif + CFRelease(mediatorObject); JNF_COCOA_EXIT(env); @@ -379,7 +378,7 @@ JNF_COCOA_ENTER(env); AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator); - [ThreadUtilities performOnMainThread:@selector(endRunLoop) onObject:mediatorObject withObject:nil waitUntilDone:NO awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO]; CFRelease(mediatorObject); @@ -463,20 +462,3 @@ Java_sun_font_FontManager_populateFontFileNameMap } -/* - * Class: sun_lwawt_macosx_LWCToolkit - * Method: executeNextAppKitEvent - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_executeNextAppKitEvent -(JNIEnv *env, jclass cls) -{ - // Simply get the next event in native loop and pass it to execution - // We'll be called repeatedly so there's no need to block here - NSRunLoop *theRL = [NSRunLoop currentRunLoop]; - NSApplication * app = [NSApplication sharedApplication]; - NSEvent * event = [app nextEventMatchingMask: 0xFFFFFFFF untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]; - if (event != nil) { - [app sendEvent: event]; - } -} diff --git a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h index c0d2054f6e3..2ee65e94c65 100644 --- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h +++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h @@ -122,19 +122,12 @@ do { \ #endif /* AWT_THREAD_ASSERTS */ // -------------------------------------------------------------------------- -// This tracks if we are current inside of a performOnMainThread that is both waiting and in the AWTRunLoopMode -extern BOOL sInPerformFromJava; - -// This is an empty Obj-C object just so that -performSelectorOnMainThread -// can be used, and to use the Obj-C +initialize feature. __attribute__((visibility("default"))) -@interface ThreadUtilities : NSObject { } +@interface ThreadUtilities { } + (JNIEnv*)getJNIEnv; + (JNIEnv*)getJNIEnvUncached; -+ (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT; - //Wrappers for the corresponding JNFRunLoop methods with a check for main thread + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block; + (void)performOnMainThread:(SEL)aSelector on:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait; diff --git a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m index 0b42f1b5896..d431386bbdb 100644 --- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m +++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m @@ -34,85 +34,6 @@ JavaVM *jvm = NULL; static JNIEnv *appKitEnv = NULL; -static NSArray *sPerformModes = nil; -static NSArray *sAWTPerformModes = nil; - -static BOOL sLoggingEnabled = YES; - -#ifdef AWT_THREAD_ASSERTS_ENV_ASSERT -int sAWTThreadAsserts = 0; -#endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */ - -BOOL sInPerformFromJava = NO; - -// This class is used so that performSelectorOnMainThread can be -// controlled a little more easily by us. It has 2 roles. -// The first is to set/unset a flag (sInPerformFromJava) that code can -// check to see if we are in a synchronous perform initiated by a java thread. -// The second is to implement the CocoaComponent backward compatibility mode. -@interface CPerformer : NSObject { - id fTarget; - SEL fSelector; - id fArg; - BOOL fWait; -} - -- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg wait:(BOOL)wait; -- (void) perform; -@end - - -@implementation CPerformer - -- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg { - return [self initWithTarget:target selector:selector arg:arg wait:YES]; -} - -- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg wait:(BOOL)wait { - self = [super init]; - if (self != nil) { - fTarget = [target retain]; - fSelector = selector; - fArg = [arg retain]; - // Only set sInPerformFromJava if this is a synchronous perform - fWait = wait; - } - return self; -} - -- (void) dealloc { - [fTarget release]; - [fArg release]; - [super dealloc]; -} -//- (void)finalize { [super finalize]; } - -- (void) perform { - AWT_ASSERT_APPKIT_THREAD; - - // If this is the first time we're going from java thread -> appkit thread, - // set sInPerformFromJava for the duration of the invocation - BOOL nestedPerform = sInPerformFromJava; - if (fWait) { - sInPerformFromJava = YES; - } - - // Actually do the work (cheat to avoid a method call) - @try { - objc_msgSend(fTarget, fSelector, fArg); - //[fTarget performSelector:fSelector withObject:fArg]; - } @catch (NSException *e) { - NSLog(@"*** CPerformer: ignoring exception '%@' raised during perform of selector '%@' on target '%@' with args '%@'", e, NSStringFromSelector(fSelector), fTarget, fArg); - } @finally { - // If we actually set sInPerformFromJava, unset it now - if (!nestedPerform && fWait) { - sInPerformFromJava = NO; - } - } -} -@end - - @implementation ThreadUtilities + (JNIEnv*)getJNIEnv { @@ -129,36 +50,6 @@ AWT_ASSERT_APPKIT_THREAD; return env; } -+ (void)initialize { - // Headless: BOTH - // Embedded: BOTH - // Multiple Calls: NO - // Caller: Obj-C class initialization - // Thread: ? - - if (sPerformModes == nil) { - // Create list of Run Loop modes to perform on - // The default performSelector, with no mode argument, runs in Default, - // ModalPanel, and EventTracking modes - sPerformModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, nil]; - sAWTPerformModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, NSEventTrackingRunLoopMode, [JNFRunLoop javaRunLoopMode], nil]; - -#ifdef AWT_THREAD_ASSERTS_ENV_ASSERT - sAWTThreadAsserts = (getenv("COCOA_AWT_DISABLE_THREAD_ASSERTS") == NULL); -#endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */ - } -} - -// These methods can behave slightly differently than the normal -// performSelector... In particular, we define a special runloop mode -// (AWTRunLoopMode) so that we can "block" the main thread against the -// java event thread without deadlocking. See CToolkit.invokeAndWait. -+ (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT { - CPerformer *performer = [[CPerformer alloc] initWithTarget:target selector:aSelector arg:arg wait:wait]; - [performer performSelectorOnMainThread:@selector(perform) withObject:nil waitUntilDone:wait modes:((inAWT) ? sAWTPerformModes : sPerformModes)]; // AWT_THREADING Safe (cover method) - [performer release]; -} - + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block { if ([NSThread isMainThread] && wait == YES) { block(); From 960480c53da0859eb4860533d224cec7ad8ea81a Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Tue, 26 Feb 2013 08:54:03 -0800 Subject: [PATCH 060/102] 8008081: Print outs do not have matching arguments Corrected formatted prints to have matching arguments, removed dead print_frame_layout function Reviewed-by: sla, dholmes --- hotspot/src/share/vm/c1/c1_FrameMap.cpp | 21 ------------------- hotspot/src/share/vm/c1/c1_FrameMap.hpp | 2 -- .../parNew/parCardTableModRefBS.cpp | 2 ++ .../src/share/vm/memory/cardTableModRefBS.cpp | 2 +- hotspot/src/share/vm/memory/cardTableRS.cpp | 2 +- hotspot/src/share/vm/prims/jvmtiEnter.xsl | 8 +++---- hotspot/src/share/vm/services/memReporter.cpp | 4 ++-- hotspot/src/share/vm/utilities/numberSeq.cpp | 2 +- 8 files changed, 11 insertions(+), 32 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_FrameMap.cpp b/hotspot/src/share/vm/c1/c1_FrameMap.cpp index 212499caf98..f5eef6f0b3b 100644 --- a/hotspot/src/share/vm/c1/c1_FrameMap.cpp +++ b/hotspot/src/share/vm/c1/c1_FrameMap.cpp @@ -308,27 +308,6 @@ ByteSize FrameMap::sp_offset_for_monitor_object(int index) const { return sp_offset_for_monitor_base(index) + in_ByteSize(BasicObjectLock::obj_offset_in_bytes()); } -void FrameMap::print_frame_layout() const { - int svar; - tty->print_cr("#####################################"); - tty->print_cr("Frame size in words %d", framesize()); - - if( _num_monitors > 0) { - tty->print_cr("monitor [0]:%d | [%2d]:%d", - in_bytes(sp_offset_for_monitor_base(0)), - in_bytes(sp_offset_for_monitor_base(_num_monitors))); - } - if( _num_spills > 0) { - svar = _num_spills - 1; - if(svar == 0) - tty->print_cr("spill [0]:%d", in_bytes(sp_offset_for_spill(0))); - else - tty->print_cr("spill [0]:%d | [%2d]:%d", in_bytes(sp_offset_for_spill(0)), - svar, - in_bytes(sp_offset_for_spill(svar))); - } -} - // For OopMaps, map a local variable or spill index to an VMReg. // This is the offset from sp() in the frame of the slot for the index, diff --git a/hotspot/src/share/vm/c1/c1_FrameMap.hpp b/hotspot/src/share/vm/c1/c1_FrameMap.hpp index 1062f7a8ecd..98bb86f8f74 100644 --- a/hotspot/src/share/vm/c1/c1_FrameMap.hpp +++ b/hotspot/src/share/vm/c1/c1_FrameMap.hpp @@ -226,8 +226,6 @@ class FrameMap : public CompilationResourceObj { return make_new_address(sp_offset_for_monitor_object(monitor_index)); } - void print_frame_layout() const; - // Creates Location describing desired slot and returns it via pointer // to Location object. Returns true if the stack frame offset was legal // (as defined by Location::legal_offset_in_bytes()), false otherwise. diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp index 564b24c7460..047c463d39e 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp @@ -373,6 +373,8 @@ process_chunk_boundaries(Space* sp, " does not exceed used.end() = " PTR_FORMAT "," " yet last_chunk_index_to_check " INTPTR_FORMAT " exceeds last_chunk_index " INTPTR_FORMAT, + last_block, last_block + last_block_size, + used.end(), last_chunk_index_to_check, last_chunk_index)); assert(sp->used_region().end() > used.end(), err_msg("Expansion did not happen: " diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp index d3fa82d8566..3c65d29a5f2 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp @@ -694,7 +694,7 @@ void CardTableModRefBS::verify_region(MemRegion mr, if (failed) { if (!failures) { tty->cr(); - tty->print_cr("== CT verification failed: ["PTR_FORMAT","PTR_FORMAT"]"); + tty->print_cr("== CT verification failed: ["PTR_FORMAT","PTR_FORMAT"]", start, end); tty->print_cr("== %sexpecting value: %d", (val_equals) ? "" : "not ", val); failures = true; diff --git a/hotspot/src/share/vm/memory/cardTableRS.cpp b/hotspot/src/share/vm/memory/cardTableRS.cpp index d92de481644..bd1cd9dd2cd 100644 --- a/hotspot/src/share/vm/memory/cardTableRS.cpp +++ b/hotspot/src/share/vm/memory/cardTableRS.cpp @@ -353,7 +353,7 @@ protected: assert(jp >= _begin && jp < _end, err_msg("Error: jp " PTR_FORMAT " should be within " "[_begin, _end) = [" PTR_FORMAT "," PTR_FORMAT ")", - _begin, _end)); + jp, _begin, _end)); oop obj = oopDesc::load_decode_heap_oop(p); guarantee(obj == NULL || (HeapWord*)obj >= _boundary, err_msg("pointer " PTR_FORMAT " at " PTR_FORMAT " on " diff --git a/hotspot/src/share/vm/prims/jvmtiEnter.xsl b/hotspot/src/share/vm/prims/jvmtiEnter.xsl index a1d128b1377..f31bd5143b7 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnter.xsl +++ b/hotspot/src/share/vm/prims/jvmtiEnter.xsl @@ -773,7 +773,7 @@ static jvmtiError JNICALL JVMTI_ERROR_INVALID_THREAD - - jthread resolved to NULL - jthread = %0x%x + - jthread resolved to NULL - jthread = 0x%x , @@ -782,7 +782,7 @@ static jvmtiError JNICALL JVMTI_ERROR_INVALID_THREAD - - oop is not a thread - jthread = %0x%x + - oop is not a thread - jthread = 0x%x , @@ -794,7 +794,7 @@ static jvmtiError JNICALL JVMTI_ERROR_THREAD_NOT_ALIVE - - not a Java thread - jthread = %0x%x + - not a Java thread - jthread = 0x%x , @@ -838,7 +838,7 @@ static jvmtiError JNICALL JVMTI_ERROR_ILLEGAL_ARGUMENT - - negative depth - jthread = %0x%x + - negative depth - jthread = 0x%x , diff --git a/hotspot/src/share/vm/services/memReporter.cpp b/hotspot/src/share/vm/services/memReporter.cpp index fca2897d6fe..0311675f349 100644 --- a/hotspot/src/share/vm/services/memReporter.cpp +++ b/hotspot/src/share/vm/services/memReporter.cpp @@ -419,7 +419,7 @@ void BaselineTTYOutputer::virtual_memory_callsite(address pc, size_t reserved_am _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset); _output->print("%28s", " "); } else { - _output->print("[" PTR_FORMAT "]%18s", " "); + _output->print("[" PTR_FORMAT "]%18s", pc, " "); } _output->print_cr("(mmap: reserved=%d%s, committed=%d%s)", @@ -596,7 +596,7 @@ void BaselineTTYOutputer::diff_virtual_memory_callsite(address pc, _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset); _output->print("%28s", " "); } else { - _output->print("[" PTR_FORMAT "]%18s", " "); + _output->print("[" PTR_FORMAT "]%18s", pc, " "); } } diff --git a/hotspot/src/share/vm/utilities/numberSeq.cpp b/hotspot/src/share/vm/utilities/numberSeq.cpp index 907c3a15c5e..398ba32f481 100644 --- a/hotspot/src/share/vm/utilities/numberSeq.cpp +++ b/hotspot/src/share/vm/utilities/numberSeq.cpp @@ -245,7 +245,7 @@ void AbsSeq::dump_on(outputStream* s) { void NumberSeq::dump_on(outputStream* s) { AbsSeq::dump_on(s); - s->print_cr("\t\t _last = %7.3f, _maximum = %7.3f"); + s->print_cr("\t\t _last = %7.3f, _maximum = %7.3f", _last, _maximum); } void TruncatedSeq::dump_on(outputStream* s) { From 76fa59559979354c8a8cc6681df5e33cde3e0c32 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 27 Feb 2013 09:40:30 +0100 Subject: [PATCH 061/102] 8008959: Fix non-PCH build on Linux, Windows and MacOS X Fix the build without precompiled headers by either including the missing ".inline.hpp" files into the appropriate files or by turning inline-functions declared in header files into ordinary functions in ".cpp" files. Reviewed-by: coleenp, stefank, dholmes --- hotspot/src/os/bsd/vm/os_bsd.cpp | 16 ++++----- hotspot/src/os/bsd/vm/os_bsd.hpp | 35 +++++++----------- hotspot/src/os/bsd/vm/os_bsd.inline.hpp | 18 +++++++++- hotspot/src/os/linux/vm/os_linux.cpp | 16 ++++----- hotspot/src/os/linux/vm/os_linux.hpp | 36 +++++++------------ hotspot/src/os/linux/vm/os_linux.inline.hpp | 18 +++++++++- .../src/os/solaris/vm/os_solaris.inline.hpp | 1 - hotspot/src/os/windows/vm/decoder_windows.cpp | 3 +- .../src/os/windows/vm/os_windows.inline.hpp | 1 - .../bsd_x86/vm/atomic_bsd_x86.inline.hpp | 3 +- .../bsd_x86/vm/orderAccess_bsd_x86.inline.hpp | 5 +-- .../bsd_zero/vm/atomic_bsd_zero.inline.hpp | 3 +- .../vm/atomic_linux_sparc.inline.hpp | 3 +- .../linux_x86/vm/atomic_linux_x86.inline.hpp | 3 +- .../vm/orderAccess_linux_x86.inline.hpp | 5 +-- .../vm/atomic_linux_zero.inline.hpp | 3 +- .../vm/atomic_solaris_sparc.inline.hpp | 3 +- .../vm/orderAccess_solaris_sparc.inline.hpp | 3 +- .../vm/atomic_solaris_x86.inline.hpp | 3 +- .../vm/orderAccess_solaris_x86.inline.hpp | 4 +-- .../vm/atomic_windows_x86.inline.hpp | 3 +- .../vm/orderAccess_windows_x86.inline.hpp | 9 ++--- .../src/share/vm/memory/allocation.inline.hpp | 3 +- hotspot/src/share/vm/oops/symbol.cpp | 25 ++++++++++++- hotspot/src/share/vm/oops/symbol.hpp | 29 ++------------- 25 files changed, 126 insertions(+), 125 deletions(-) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 1bc86d13bce..fdf5772a764 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -2695,7 +2695,7 @@ static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { assert(thread->is_VM_thread(), "Must be VMThread"); // read current suspend action int action = osthread->sr.suspend_action(); - if (action == SR_SUSPEND) { + if (action == os::Bsd::SuspendResume::SR_SUSPEND) { suspend_save_context(osthread, siginfo, context); // Notify the suspend action is about to be completed. do_suspend() @@ -2717,12 +2717,12 @@ static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { do { sigsuspend(&suspend_set); // ignore all returns until we get a resume signal - } while (osthread->sr.suspend_action() != SR_CONTINUE); + } while (osthread->sr.suspend_action() != os::Bsd::SuspendResume::SR_CONTINUE); resume_clear_context(osthread); } else { - assert(action == SR_CONTINUE, "unexpected sr action"); + assert(action == os::Bsd::SuspendResume::SR_CONTINUE, "unexpected sr action"); // nothing special to do - just leave the handler } @@ -2776,7 +2776,7 @@ static int SR_finalize() { // but this seems the normal response to library errors static bool do_suspend(OSThread* osthread) { // mark as suspended and send signal - osthread->sr.set_suspend_action(SR_SUSPEND); + osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_SUSPEND); int status = pthread_kill(osthread->pthread_id(), SR_signum); assert_status(status == 0, status, "pthread_kill"); @@ -2785,18 +2785,18 @@ static bool do_suspend(OSThread* osthread) { for (int i = 0; !osthread->sr.is_suspended(); i++) { os::yield_all(i); } - osthread->sr.set_suspend_action(SR_NONE); + osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE); return true; } else { - osthread->sr.set_suspend_action(SR_NONE); + osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE); return false; } } static void do_resume(OSThread* osthread) { assert(osthread->sr.is_suspended(), "thread should be suspended"); - osthread->sr.set_suspend_action(SR_CONTINUE); + osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_CONTINUE); int status = pthread_kill(osthread->pthread_id(), SR_signum); assert_status(status == 0, status, "pthread_kill"); @@ -2806,7 +2806,7 @@ static void do_resume(OSThread* osthread) { os::yield_all(i); } } - osthread->sr.set_suspend_action(SR_NONE); + osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE); } //////////////////////////////////////////////////////////////////////////////// diff --git a/hotspot/src/os/bsd/vm/os_bsd.hpp b/hotspot/src/os/bsd/vm/os_bsd.hpp index ebdbdc22a03..81562b4f8d3 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.hpp +++ b/hotspot/src/os/bsd/vm/os_bsd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -151,36 +151,25 @@ class Bsd { // for BsdThreads are no longer needed. class SuspendResume { private: - volatile int _suspend_action; - // values for suspend_action: - #define SR_NONE (0x00) - #define SR_SUSPEND (0x01) // suspend request - #define SR_CONTINUE (0x02) // resume request - + volatile int _suspend_action; volatile jint _state; - // values for _state: + SR_NONE - #define SR_SUSPENDED (0x20) public: + // values for suspend_action: + enum { + SR_NONE = 0x00, + SR_SUSPEND = 0x01, // suspend request + SR_CONTINUE = 0x02, // resume request + SR_SUSPENDED = 0x20 // values for _state: + SR_NONE + }; + SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; } int suspend_action() const { return _suspend_action; } void set_suspend_action(int x) { _suspend_action = x; } // atomic updates for _state - void set_suspended() { - jint temp, temp2; - do { - temp = _state; - temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp); - } while (temp2 != temp); - } - void clear_suspended() { - jint temp, temp2; - do { - temp = _state; - temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp); - } while (temp2 != temp); - } + inline void set_suspended(); + inline void clear_suspended(); bool is_suspended() { return _state & SR_SUSPENDED; } #undef SR_SUSPENDED diff --git a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp index 8fc3c2b0878..723543efe92 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp +++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp @@ -25,7 +25,6 @@ #ifndef OS_BSD_VM_OS_BSD_INLINE_HPP #define OS_BSD_VM_OS_BSD_INLINE_HPP -#include "runtime/atomic.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" @@ -286,4 +285,21 @@ inline int os::set_sock_opt(int fd, int level, int optname, const char* optval, socklen_t optlen) { return ::setsockopt(fd, level, optname, optval, optlen); } + +inline void os::Bsd::SuspendResume::set_suspended() { + jint temp, temp2; + do { + temp = _state; + temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp); + } while (temp2 != temp); +} + +inline void os::Bsd::SuspendResume::clear_suspended() { + jint temp, temp2; + do { + temp = _state; + temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp); + } while (temp2 != temp); +} + #endif // OS_BSD_VM_OS_BSD_INLINE_HPP diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 9f09507e67b..b14615e58e8 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -3461,7 +3461,7 @@ static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { assert(thread->is_VM_thread(), "Must be VMThread"); // read current suspend action int action = osthread->sr.suspend_action(); - if (action == SR_SUSPEND) { + if (action == os::Linux::SuspendResume::SR_SUSPEND) { suspend_save_context(osthread, siginfo, context); // Notify the suspend action is about to be completed. do_suspend() @@ -3483,12 +3483,12 @@ static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { do { sigsuspend(&suspend_set); // ignore all returns until we get a resume signal - } while (osthread->sr.suspend_action() != SR_CONTINUE); + } while (osthread->sr.suspend_action() != os::Linux::SuspendResume::SR_CONTINUE); resume_clear_context(osthread); } else { - assert(action == SR_CONTINUE, "unexpected sr action"); + assert(action == os::Linux::SuspendResume::SR_CONTINUE, "unexpected sr action"); // nothing special to do - just leave the handler } @@ -3542,7 +3542,7 @@ static int SR_finalize() { // but this seems the normal response to library errors static bool do_suspend(OSThread* osthread) { // mark as suspended and send signal - osthread->sr.set_suspend_action(SR_SUSPEND); + osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_SUSPEND); int status = pthread_kill(osthread->pthread_id(), SR_signum); assert_status(status == 0, status, "pthread_kill"); @@ -3551,18 +3551,18 @@ static bool do_suspend(OSThread* osthread) { for (int i = 0; !osthread->sr.is_suspended(); i++) { os::yield_all(i); } - osthread->sr.set_suspend_action(SR_NONE); + osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_NONE); return true; } else { - osthread->sr.set_suspend_action(SR_NONE); + osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_NONE); return false; } } static void do_resume(OSThread* osthread) { assert(osthread->sr.is_suspended(), "thread should be suspended"); - osthread->sr.set_suspend_action(SR_CONTINUE); + osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_CONTINUE); int status = pthread_kill(osthread->pthread_id(), SR_signum); assert_status(status == 0, status, "pthread_kill"); @@ -3572,7 +3572,7 @@ static void do_resume(OSThread* osthread) { os::yield_all(i); } } - osthread->sr.set_suspend_action(SR_NONE); + osthread->sr.set_suspend_action(os::Linux::SuspendResume::SR_NONE); } //////////////////////////////////////////////////////////////////////////////// diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp index 7bbc041ed90..414ccd976fc 100644 --- a/hotspot/src/os/linux/vm/os_linux.hpp +++ b/hotspot/src/os/linux/vm/os_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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 @@ -209,39 +209,27 @@ class Linux { // for LinuxThreads are no longer needed. class SuspendResume { private: - volatile int _suspend_action; - // values for suspend_action: - #define SR_NONE (0x00) - #define SR_SUSPEND (0x01) // suspend request - #define SR_CONTINUE (0x02) // resume request - + volatile int _suspend_action; volatile jint _state; - // values for _state: + SR_NONE - #define SR_SUSPENDED (0x20) public: + // values for suspend_action: + enum { + SR_NONE = 0x00, + SR_SUSPEND = 0x01, // suspend request + SR_CONTINUE = 0x02, // resume request + SR_SUSPENDED = 0x20 // values for _state: + SR_NONE + }; + SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; } int suspend_action() const { return _suspend_action; } void set_suspend_action(int x) { _suspend_action = x; } // atomic updates for _state - void set_suspended() { - jint temp, temp2; - do { - temp = _state; - temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp); - } while (temp2 != temp); - } - void clear_suspended() { - jint temp, temp2; - do { - temp = _state; - temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp); - } while (temp2 != temp); - } + inline void set_suspended(); + inline void clear_suspended(); bool is_suspended() { return _state & SR_SUSPENDED; } - #undef SR_SUSPENDED }; private: diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp index 3a8d8d97d9b..87494dfd96f 100644 --- a/hotspot/src/os/linux/vm/os_linux.inline.hpp +++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp @@ -25,7 +25,6 @@ #ifndef OS_LINUX_VM_OS_LINUX_INLINE_HPP #define OS_LINUX_VM_OS_LINUX_INLINE_HPP -#include "runtime/atomic.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" @@ -288,4 +287,21 @@ inline int os::set_sock_opt(int fd, int level, int optname, const char* optval, socklen_t optlen) { return ::setsockopt(fd, level, optname, optval, optlen); } + +inline void os::Linux::SuspendResume::set_suspended() { + jint temp, temp2; + do { + temp = _state; + temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp); + } while (temp2 != temp); +} + +inline void os::Linux::SuspendResume::clear_suspended() { + jint temp, temp2; + do { + temp = _state; + temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp); + } while (temp2 != temp); +} + #endif // OS_LINUX_VM_OS_LINUX_INLINE_HPP diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp index 61691fd384a..64515d93b91 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp @@ -25,7 +25,6 @@ #ifndef OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP #define OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP -#include "runtime/atomic.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" diff --git a/hotspot/src/os/windows/vm/decoder_windows.cpp b/hotspot/src/os/windows/vm/decoder_windows.cpp index 2b4682728a2..326d3288020 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, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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,6 +24,7 @@ #include "precompiled.hpp" #include "prims/jvm.h" +#include "runtime/arguments.hpp" #include "decoder_windows.hpp" WindowsDecoder::WindowsDecoder() { diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp index 1df8694d9dd..5b1c46dfc59 100644 --- a/hotspot/src/os/windows/vm/os_windows.inline.hpp +++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp @@ -25,7 +25,6 @@ #ifndef OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP #define OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP -#include "runtime/atomic.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" diff --git a/hotspot/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp b/hotspot/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp index aa47196191a..ab7fab3dd13 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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,7 +25,6 @@ #ifndef OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP #define OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP -#include "orderAccess_bsd_x86.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_x86.hpp" diff --git a/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp b/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp index eaecd9cd32f..0ac6d3093f8 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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,8 +25,9 @@ #ifndef OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP #define OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP -#include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" +#include "runtime/os.hpp" #include "vm_version_x86.hpp" // Implementation of class OrderAccess. diff --git a/hotspot/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp b/hotspot/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp index 19027bd150b..4ed2934463b 100644 --- a/hotspot/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp +++ b/hotspot/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,7 +26,6 @@ #ifndef OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP #define OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP -#include "orderAccess_bsd_zero.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_zero.hpp" diff --git a/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp b/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp index a409f27b422..fa31a50c327 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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,7 +25,6 @@ #ifndef OS_CPU_LINUX_SPARC_VM_ATOMIC_LINUX_SPARC_INLINE_HPP #define OS_CPU_LINUX_SPARC_VM_ATOMIC_LINUX_SPARC_INLINE_HPP -#include "orderAccess_linux_sparc.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_sparc.hpp" diff --git a/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp b/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp index 7ec3dace4b1..2d0d5197344 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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,7 +25,6 @@ #ifndef OS_CPU_LINUX_X86_VM_ATOMIC_LINUX_X86_INLINE_HPP #define OS_CPU_LINUX_X86_VM_ATOMIC_LINUX_X86_INLINE_HPP -#include "orderAccess_linux_x86.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_x86.hpp" diff --git a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp index 6f33e12e081..7a9fd1a4413 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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,8 +25,9 @@ #ifndef OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP #define OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP -#include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" +#include "runtime/os.hpp" #include "vm_version_x86.hpp" // Implementation of class OrderAccess. diff --git a/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp b/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp index 9bee2332f87..33ce50dc73f 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,7 +26,6 @@ #ifndef OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_INLINE_HPP #define OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_INLINE_HPP -#include "orderAccess_linux_zero.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_zero.hpp" diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp b/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp index 0d91eb967d5..b91214748c2 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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,7 +25,6 @@ #ifndef OS_CPU_SOLARIS_SPARC_VM_ATOMIC_SOLARIS_SPARC_INLINE_HPP #define OS_CPU_SOLARIS_SPARC_VM_ATOMIC_SOLARIS_SPARC_INLINE_HPP -#include "orderAccess_solaris_sparc.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_sparc.hpp" diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp b/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp index 8f3e781e674..7e633fd95cb 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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,7 @@ #ifndef OS_CPU_SOLARIS_SPARC_VM_ORDERACCESS_SOLARIS_SPARC_INLINE_HPP #define OS_CPU_SOLARIS_SPARC_VM_ORDERACCESS_SOLARIS_SPARC_INLINE_HPP +#include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" #include "vm_version_sparc.hpp" diff --git a/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp b/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp index d91812db9c6..27c0d396b72 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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,7 +25,6 @@ #ifndef OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_INLINE_HPP #define OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_INLINE_HPP -#include "orderAccess_solaris_x86.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_x86.hpp" diff --git a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp index 5b5445da512..c02d98ed991 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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,7 +25,7 @@ #ifndef OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP #define OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP -#include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" #include "vm_version_x86.hpp" diff --git a/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp b/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp index 37d2879662e..7ba00f7aaeb 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, 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,7 +25,6 @@ #ifndef OS_CPU_WINDOWS_X86_VM_ATOMIC_WINDOWS_X86_INLINE_HPP #define OS_CPU_WINDOWS_X86_VM_ATOMIC_WINDOWS_X86_INLINE_HPP -#include "orderAccess_windows_x86.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_x86.hpp" diff --git a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp index 682990dc6b7..639b8ad9d9d 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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,12 +25,11 @@ #ifndef OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP #define OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP -#include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/orderAccess.hpp" +#include "runtime/os.hpp" #include "vm_version_x86.hpp" -#pragma warning(disable: 4035) // Disables warnings reporting missing return statement - // Implementation of class OrderAccess. inline void OrderAccess::loadload() { acquire(); } @@ -214,6 +213,4 @@ inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* #endif // AMD64 } -#pragma warning(default: 4035) // Enables warnings reporting missing return statement - #endif // OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP diff --git a/hotspot/src/share/vm/memory/allocation.inline.hpp b/hotspot/src/share/vm/memory/allocation.inline.hpp index ead6fb12b21..6c236e17b7a 100644 --- a/hotspot/src/share/vm/memory/allocation.inline.hpp +++ b/hotspot/src/share/vm/memory/allocation.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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,7 @@ #ifndef SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP #define SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP +#include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" // Explicit C-heap memory management diff --git a/hotspot/src/share/vm/oops/symbol.cpp b/hotspot/src/share/vm/oops/symbol.cpp index 54601899287..b3c71813bdb 100644 --- a/hotspot/src/share/vm/oops/symbol.cpp +++ b/hotspot/src/share/vm/oops/symbol.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ #include "classfile/altHashing.hpp" #include "classfile/classLoaderData.hpp" #include "oops/symbol.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -210,6 +211,28 @@ unsigned int Symbol::new_hash(jint seed) { return AltHashing::murmur3_32(seed, (const jbyte*)as_C_string(), utf8_length()); } +void Symbol::increment_refcount() { + // Only increment the refcount if positive. If negative either + // overflow has occurred or it is a permanent symbol in a read only + // shared archive. + if (_refcount >= 0) { + Atomic::inc(&_refcount); + NOT_PRODUCT(Atomic::inc(&_total_count);) + } +} + +void Symbol::decrement_refcount() { + if (_refcount >= 0) { + Atomic::dec(&_refcount); +#ifdef ASSERT + if (_refcount < 0) { + print(); + assert(false, "reference count underflow for symbol"); + } +#endif + } +} + void Symbol::print_on(outputStream* st) const { if (this == NULL) { st->print_cr("NULL"); diff --git a/hotspot/src/share/vm/oops/symbol.hpp b/hotspot/src/share/vm/oops/symbol.hpp index 55867d2b007..d06edf052fc 100644 --- a/hotspot/src/share/vm/oops/symbol.hpp +++ b/hotspot/src/share/vm/oops/symbol.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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,7 +27,6 @@ #include "utilities/utf8.hpp" #include "memory/allocation.hpp" -#include "runtime/atomic.hpp" // A Symbol is a canonicalized string. // All Symbols reside in global SymbolTable and are reference counted. @@ -150,8 +149,8 @@ class Symbol : public MetaspaceObj { // Reference counting. See comments above this class for when to use. int refcount() const { return _refcount; } - inline void increment_refcount(); - inline void decrement_refcount(); + void increment_refcount(); + void decrement_refcount(); int byte_at(int index) const { assert(index >=0 && index < _length, "symbol index overflow"); @@ -232,26 +231,4 @@ int Symbol::fast_compare(Symbol* other) const { return (((uintptr_t)this < (uintptr_t)other) ? -1 : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1); } - -inline void Symbol::increment_refcount() { - // Only increment the refcount if positive. If negative either - // overflow has occurred or it is a permanent symbol in a read only - // shared archive. - if (_refcount >= 0) { - Atomic::inc(&_refcount); - NOT_PRODUCT(Atomic::inc(&_total_count);) - } -} - -inline void Symbol::decrement_refcount() { - if (_refcount >= 0) { - Atomic::dec(&_refcount); -#ifdef ASSERT - if (_refcount < 0) { - print(); - assert(false, "reference count underflow for symbol"); - } -#endif - } -} #endif // SHARE_VM_OOPS_SYMBOL_HPP From 13505fc4e5ba8ea0bd3b7a911e96c3bfc9b0d6d9 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Wed, 27 Feb 2013 14:02:26 +0000 Subject: [PATCH 062/102] 8008807: SA: jstack crash when target has mismatched bitness (Linux) Reviewed-by: rbackman, sla, poonam --- .../agent/src/os/linux/LinuxDebuggerLocal.c | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c index 1d3c3bbd027..17f607e0af0 100644 --- a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c +++ b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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,13 @@ #include #include "libproc.h" +#include +#include +#include +#include +#include +#include + #if defined(x86_64) && !defined(amd64) #define amd64 1 #endif @@ -154,6 +161,39 @@ static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_p } } + +/* + * Verify that a named ELF binary file (core or executable) has the same + * bitness as ourselves. + * Throw an exception if there is a mismatch or other problem. + * + * If we proceed using a mismatched debugger/debuggee, the best to hope + * for is a missing symbol, the worst is a crash searching for debug symbols. + */ +void verifyBitness(JNIEnv *env, const char *binaryName) { + int fd = open(binaryName, O_RDONLY); + if (fd < 0) { + THROW_NEW_DEBUGGER_EXCEPTION("cannot open binary file"); + } + unsigned char elf_ident[EI_NIDENT]; + int i = read(fd, &elf_ident, sizeof(elf_ident)); + close(fd); + + if (i < 0) { + THROW_NEW_DEBUGGER_EXCEPTION("cannot read binary file"); + } +#ifndef _LP64 + if (elf_ident[EI_CLASS] == ELFCLASS64) { + THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 64 bit, use 64-bit java for debugger"); + } +#else + if (elf_ident[EI_CLASS] != ELFCLASS64) { + THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 32 bit, use 32 bit java for debugger"); + } +#endif +} + + /* * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal * Method: attach0 @@ -162,6 +202,12 @@ static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_p JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I (JNIEnv *env, jobject this_obj, jint jpid) { + // For bitness checking, locate binary at /proc/jpid/exe + char buf[PATH_MAX]; + snprintf((char *) &buf, PATH_MAX, "/proc/%d/exe", jpid); + verifyBitness(env, (char *) &buf); + CHECK_EXCEPTION; + struct ps_prochandle* ph; if ( (ph = Pgrab(jpid)) == NULL) { THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); @@ -187,6 +233,9 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_at coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy); CHECK_EXCEPTION; + verifyBitness(env, execName_cstr); + CHECK_EXCEPTION; + if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) { (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); From b097b0d23423f887bd5ef2f3a19e28c50fad62dc Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Wed, 27 Feb 2013 19:38:36 +0400 Subject: [PATCH 063/102] 7178079: REGRESSION: Some AWT Drag-n-Drop tests fail since JDK 7u6 b13 Reviewed-by: serb, anthony --- .../classes/sun/lwawt/macosx/CDropTargetContextPeer.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java index 181d0847225..0f32d3178fd 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java @@ -128,6 +128,15 @@ final class CDropTargetContextPeer extends SunDropTargetContextPeer { } } + @Override + protected int postDropTargetEvent(Component component, int x, int y, int dropAction, + int actions, long[] formats, long nativeCtxt, int eventID, + boolean dispatchType) { + // On MacOS X all the DnD events should be synchronous + return super.postDropTargetEvent(component, x, y, dropAction, actions, formats, nativeCtxt, + eventID, SunDropTargetContextPeer.DISPATCH_SYNC); + } + // Signal drop complete: protected void doDropDone(boolean success, int dropAction, boolean isLocal) { long nativeDropTarget = this.getNativeDragContext(); From e19091b0b1943c67c5ac538e05ae0db133a59e5e Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Wed, 27 Feb 2013 20:34:04 +0400 Subject: [PATCH 064/102] 8009158: Incomplete fix for 7178079 Reviewed-by: serb, anthony --- jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java b/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java index 302a6dbc62e..360bb9a63a6 100644 --- a/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java +++ b/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java @@ -498,7 +498,7 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, postDropTargetEvent(component, x, y, dropAction, actions, formats, nativeCtxt, SunDropTargetEvent.MOUSE_DROPPED, - SunDropTargetContextPeer.DISPATCH_SYNC); + !SunDropTargetContextPeer.DISPATCH_SYNC); } /** From 37cdc7b1f81a191d86a3ca8e0a1dc68d11daa85a Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Wed, 27 Feb 2013 22:40:14 +0000 Subject: [PATCH 065/102] 7178741: SA: jstack -m produce UnalignedAddressException in output (Linux) Reviewed-by: poonam, sla --- .../jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java | 7 ++++++- .../sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java index 36977f1aeaa..cf8e073208b 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java @@ -60,8 +60,13 @@ final public class LinuxAMD64CFrame extends BasicCFrame { return null; } + // Check alignment of rbp + if ( dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) { + return null; + } + Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE); - if (nextRBP == null) { + if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) { return null; } Address nextPC = rbp.getAddressAt( 1 * ADDRESS_SIZE); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java index 8d066720ea2..d2370c96319 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java @@ -61,8 +61,13 @@ final public class LinuxX86CFrame extends BasicCFrame { return null; } + // Check alignment of ebp + if ( dbg.getAddressValue(ebp) % ADDRESS_SIZE != 0) { + return null; + } + Address nextEBP = ebp.getAddressAt( 0 * ADDRESS_SIZE); - if (nextEBP == null) { + if (nextEBP == null || nextEBP.lessThanOrEqual(ebp)) { return null; } Address nextPC = ebp.getAddressAt( 1 * ADDRESS_SIZE); From 776841b1bc40eb17991cb82feaedd16373c429ee Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 27 Feb 2013 15:00:30 -0800 Subject: [PATCH 066/102] 8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address Make deadlock detection a little more robust in the case of being unable to find the JavaThread associated with an object lock. Reviewed-by: sla, acorn --- hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 10 ++++- hotspot/src/share/vm/runtime/synchronizer.cpp | 1 + hotspot/src/share/vm/runtime/thread.cpp | 6 ++- .../src/share/vm/services/threadService.cpp | 38 +++++++++++++++++-- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index 56387634179..597d7a164dc 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -997,13 +997,19 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec // move our object at this point. However, our owner value is safe // since it is either the Lock word on a stack or a JavaThread *. owning_thread = Threads::owning_thread_from_monitor_owner(owner, !at_safepoint); - assert(owning_thread != NULL, "sanity check"); - if (owning_thread != NULL) { // robustness + // Cannot assume (owning_thread != NULL) here because this function + // may not have been called at a safepoint and the owning_thread + // might not be suspended. + if (owning_thread != NULL) { // The monitor's owner either has to be the current thread, at safepoint // or it has to be suspended. Any of these conditions will prevent both // contending and waiting threads from modifying the state of // the monitor. if (!at_safepoint && !JvmtiEnv::is_thread_fully_suspended(owning_thread, true, &debug_bits)) { + // Don't worry! This return of JVMTI_ERROR_THREAD_NOT_SUSPENDED + // will not make it back to the JVM/TI agent. The error code will + // get intercepted in JvmtiEnv::GetObjectMonitorUsage() which + // will retry the call via a VM_GetObjectMonitorUsage VM op. return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } HandleMark hm; diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index bdf416275dc..bff39625ed4 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -813,6 +813,7 @@ JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) { } if (owner != NULL) { + // owning_thread_from_monitor_owner() may also return NULL here return Threads::owning_thread_from_monitor_owner(owner, doLock); } diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index e0cf75b03f2..cb883c5d821 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -4285,7 +4285,9 @@ JavaThread *Threads::owning_thread_from_monitor_owner(address owner, bool doLock if (owner == (address)p) return p; } } - assert(UseHeavyMonitors == false, "Did not find owning Java thread with UseHeavyMonitors enabled"); + // Cannot assert on lack of success here since this function may be + // used by code that is trying to report useful problem information + // like deadlock detection. if (UseHeavyMonitors) return NULL; // @@ -4303,7 +4305,7 @@ JavaThread *Threads::owning_thread_from_monitor_owner(address owner, bool doLock } } } - assert(the_owner != NULL, "Did not find owning Java thread for lock word address"); + // cannot assert on lack of success here; see above comment return the_owner; } diff --git a/hotspot/src/share/vm/services/threadService.cpp b/hotspot/src/share/vm/services/threadService.cpp index b1c92c0b110..03289c7e9ac 100644 --- a/hotspot/src/share/vm/services/threadService.cpp +++ b/hotspot/src/share/vm/services/threadService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -327,8 +327,28 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) while (waitingToLockMonitor != NULL || waitingToLockBlocker != NULL) { cycle->add_thread(currentThread); if (waitingToLockMonitor != NULL) { - currentThread = Threads::owning_thread_from_monitor_owner((address)waitingToLockMonitor->owner(), - false /* no locking needed */); + currentThread = Threads::owning_thread_from_monitor_owner( + (address)waitingToLockMonitor->owner(), + false /* no locking needed */); + if (currentThread == NULL) { + // This function is called at a safepoint so the JavaThread + // that owns waitingToLockMonitor should be findable, but + // if it is not findable, then the previous currentThread is + // blocked permanently. We record this as a deadlock. + num_deadlocks++; + + cycle->set_deadlock(true); + + // add this cycle to the deadlocks list + if (deadlocks == NULL) { + deadlocks = cycle; + } else { + last->set_next(cycle); + } + last = cycle; + cycle = new DeadlockCycle(); + break; + } } else { if (concurrent_locks) { if (waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass())) { @@ -841,7 +861,17 @@ void DeadlockCycle::print_on(outputStream* st) const { owner_desc = " (JVMTI raw monitor),\n which is held by"; } currentThread = Threads::owning_thread_from_monitor_owner( - (address)waitingToLockMonitor->owner(), false /* no locking needed */); + (address)waitingToLockMonitor->owner(), + false /* no locking needed */); + if (currentThread == NULL) { + // The deadlock was detected at a safepoint so the JavaThread + // that owns waitingToLockMonitor should be findable, but + // if it is not findable, then the previous currentThread is + // blocked permanently. + st->print("%s UNKNOWN_owner_addr=" PTR_FORMAT, owner_desc, + (address)waitingToLockMonitor->owner()); + continue; + } } else { st->print(" waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)", (address)waitingToLockBlocker, From 093d1163e44b833f8fa43b431e1db6ea9d0035a9 Mon Sep 17 00:00:00 2001 From: Gary Collins Date: Wed, 27 Feb 2013 20:36:14 -0800 Subject: [PATCH 067/102] 7115383: TEST_BUG: some jtreg tests fail because they explicitly specify -server option Small changes to hotspot tests to remove "-server" and replace with ${TESTVMOPTS} Reviewed-by: kvn --- hotspot/test/compiler/6431242/Test.java | 2 +- hotspot/test/compiler/6589834/Test_ia32.java | 2 +- hotspot/test/compiler/6636138/Test1.java | 2 +- hotspot/test/compiler/6636138/Test2.java | 2 +- hotspot/test/compiler/6795161/Test.java | 2 +- hotspot/test/compiler/6946040/TestCharShortByteSwap.java | 2 +- hotspot/test/compiler/7068051/Test7068051.sh | 2 +- hotspot/test/compiler/8000805/Test8000805.java | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hotspot/test/compiler/6431242/Test.java b/hotspot/test/compiler/6431242/Test.java index d5d8155634d..0c23d1ae281 100644 --- a/hotspot/test/compiler/6431242/Test.java +++ b/hotspot/test/compiler/6431242/Test.java @@ -25,7 +25,7 @@ /* * @test * @bug 6431242 - * @run main/othervm -server -XX:+PrintCompilation Test + * @run main Test */ public class Test{ diff --git a/hotspot/test/compiler/6589834/Test_ia32.java b/hotspot/test/compiler/6589834/Test_ia32.java index abc32a12e8d..56a656e0883 100644 --- a/hotspot/test/compiler/6589834/Test_ia32.java +++ b/hotspot/test/compiler/6589834/Test_ia32.java @@ -26,7 +26,7 @@ * @bug 6589834 * @summary deoptimization problem with -XX:+DeoptimizeALot * - * @run main/othervm -server Test_ia32 + * @run main Test_ia32 */ /*************************************************************************************** diff --git a/hotspot/test/compiler/6636138/Test1.java b/hotspot/test/compiler/6636138/Test1.java index e154ec1fd9a..dfc6633930a 100644 --- a/hotspot/test/compiler/6636138/Test1.java +++ b/hotspot/test/compiler/6636138/Test1.java @@ -26,7 +26,7 @@ * @bug 6636138 * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation. * - * @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init Test1 + * @run main/othervm -Xbatch -XX:CompileOnly=Test1.init Test1 */ public class Test1 { diff --git a/hotspot/test/compiler/6636138/Test2.java b/hotspot/test/compiler/6636138/Test2.java index bcc48a919f9..45cb97b85a9 100644 --- a/hotspot/test/compiler/6636138/Test2.java +++ b/hotspot/test/compiler/6636138/Test2.java @@ -26,7 +26,7 @@ * @bug 6636138 * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation. * - * @run main/othervm -server -Xbatch -XX:CompileOnly=Test2.shift Test2 + * @run main/othervm -Xbatch -XX:CompileOnly=Test2.shift Test2 */ public class Test2 { diff --git a/hotspot/test/compiler/6795161/Test.java b/hotspot/test/compiler/6795161/Test.java index f9e8ad88d7d..b2b69ca4070 100644 --- a/hotspot/test/compiler/6795161/Test.java +++ b/hotspot/test/compiler/6795161/Test.java @@ -26,7 +26,7 @@ * @test * @bug 6795161 * @summary Escape analysis leads to data corruption - * @run main/othervm -server -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:CompileOnly=Test -XX:+DoEscapeAnalysis Test + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:CompileOnly=Test -XX:+DoEscapeAnalysis Test */ class Test_Class_1 { diff --git a/hotspot/test/compiler/6946040/TestCharShortByteSwap.java b/hotspot/test/compiler/6946040/TestCharShortByteSwap.java index f6925e76784..cddbbd38491 100644 --- a/hotspot/test/compiler/6946040/TestCharShortByteSwap.java +++ b/hotspot/test/compiler/6946040/TestCharShortByteSwap.java @@ -26,7 +26,7 @@ * @test * @bug 6946040 * @summary Tests Character/Short.reverseBytes and their intrinsics implementation in the server compiler - * @run main/othervm -Xbatch -server -XX:CompileOnly=.testChar,.testShort TestCharShortByteSwap + * @run main/othervm -Xbatch -XX:CompileOnly=.testChar,.testShort TestCharShortByteSwap */ // This test must run without any command line arguments. diff --git a/hotspot/test/compiler/7068051/Test7068051.sh b/hotspot/test/compiler/7068051/Test7068051.sh index ddf3bb9a74c..3fc263b4e04 100644 --- a/hotspot/test/compiler/7068051/Test7068051.sh +++ b/hotspot/test/compiler/7068051/Test7068051.sh @@ -45,5 +45,5 @@ ${TESTJAVA}/bin/jar -uf0 foo.jar Test7068051.java ${TESTJAVA}/bin/javac -d . Test7068051.java -${TESTJAVA}/bin/java -showversion -Xbatch ${TESTVMOPTS} Test7068051 foo.jar +${TESTJAVA}/bin/java ${TESTVMOPTS} -showversion -Xbatch Test7068051 foo.jar diff --git a/hotspot/test/compiler/8000805/Test8000805.java b/hotspot/test/compiler/8000805/Test8000805.java index bd0b7b41cc6..bb8bcd9a0a9 100644 --- a/hotspot/test/compiler/8000805/Test8000805.java +++ b/hotspot/test/compiler/8000805/Test8000805.java @@ -26,7 +26,7 @@ * @bug 8000805 * @summary JMM issue: short loads are non-atomic * - * @run main/othervm -server -XX:-TieredCompilation -Xcomp -XX:+PrintCompilation -XX:CompileOnly=Test8000805.loadS2LmaskFF,Test8000805.loadS2Lmask16,Test8000805.loadS2Lmask13,Test8000805.loadUS_signExt,Test8000805.loadB2L_mask8 Test8000805 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -Xcomp -XX:+PrintCompilation -XX:CompileOnly=Test8000805.loadS2LmaskFF,Test8000805.loadS2Lmask16,Test8000805.loadS2Lmask13,Test8000805.loadUS_signExt,Test8000805.loadB2L_mask8 Test8000805 */ public class Test8000805 { From f5f12c7995f0cca756485456826479f0af899c55 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Thu, 28 Feb 2013 17:04:19 +0400 Subject: [PATCH 068/102] 8008660: Failure in 2D Queue Flusher thread on Mac Reviewed-by: swingler, bae --- .../classes/sun/awt/CGraphicsConfig.java | 2 +- .../classes/sun/awt/CGraphicsDevice.java | 9 +++-- .../sun/java2d/opengl/CGLGraphicsConfig.java | 29 ++++++++-------- .../classes/sun/lwawt/macosx/CRobot.java | 8 ++--- .../classes/sun/lwawt/macosx/LWCToolkit.java | 2 +- jdk/src/macosx/native/sun/awt/CRobot.m | 4 +-- jdk/src/macosx/native/sun/awt/LWCToolkit.h | 2 -- jdk/src/macosx/native/sun/awt/LWCToolkit.m | 33 ------------------- .../sun/java2d/opengl/CGLGraphicsConfig.m | 26 +++------------ 9 files changed, 32 insertions(+), 83 deletions(-) diff --git a/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java b/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java index fb37d01209c..055af2edb22 100644 --- a/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java +++ b/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java @@ -53,7 +53,7 @@ public abstract class CGraphicsConfig extends GraphicsConfiguration @Override public Rectangle getBounds() { - final Rectangle2D nativeBounds = nativeGetBounds(device.getCoreGraphicsScreen()); + final Rectangle2D nativeBounds = nativeGetBounds(device.getCGDisplayID()); return nativeBounds.getBounds(); // does integer rounding } diff --git a/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java b/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java index bcb24ea46f7..c4786eebcce 100644 --- a/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java +++ b/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java @@ -25,11 +25,11 @@ package sun.awt; +import java.awt.AWTPermission; +import java.awt.DisplayMode; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.Window; -import java.awt.AWTPermission; -import java.awt.DisplayMode; import java.util.Objects; import sun.java2d.opengl.CGLGraphicsConfig; @@ -58,9 +58,12 @@ public final class CGraphicsDevice extends GraphicsDevice { } /** + * Returns CGDirectDisplayID, which is the same id as @"NSScreenNumber" in + * NSScreen. + * * @return CoreGraphics display id. */ - public int getCoreGraphicsScreen() { + public int getCGDisplayID() { return displayID; } diff --git a/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java b/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java index 230f7057927..c8539a8e3f6 100644 --- a/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java +++ b/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java @@ -80,10 +80,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig private ContextCapabilities oglCaps; private OGLContext context; private final Object disposerReferent = new Object(); - - public static native int getDefaultPixFmt(int screennum); private static native boolean initCGL(); - private static native long getCGLConfigInfo(int screennum, int visualnum, + private static native long getCGLConfigInfo(int displayID, int visualnum, int swapInterval); private static native int getOGLCapabilities(long configInfo); @@ -137,15 +135,16 @@ public final class CGLGraphicsConfig extends CGraphicsConfig // Java-level context and flush the queue... OGLContext.invalidateCurrentContext(); - cfginfo = getCGLConfigInfo(device.getCoreGraphicsScreen(), pixfmt, + cfginfo = getCGLConfigInfo(device.getCGDisplayID(), pixfmt, kOpenGLSwapInterval); - - OGLContext.setScratchSurface(cfginfo); - rq.flushAndInvokeNow(new Runnable() { - public void run() { - ids[0] = OGLContext.getOGLIdString(); - } - }); + if (cfginfo != 0L) { + OGLContext.setScratchSurface(cfginfo); + rq.flushAndInvokeNow(new Runnable() { + public void run() { + ids[0] = OGLContext.getOGLIdString(); + } + }); + } } finally { rq.unlock(); } @@ -253,8 +252,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig @Override public String toString() { - int screen = getDevice().getCoreGraphicsScreen(); - return ("CGLGraphicsConfig[dev="+screen+",pixfmt="+pixfmt+"]"); + int displayID = getDevice().getCGDisplayID(); + return ("CGLGraphicsConfig[dev="+displayID+",pixfmt="+pixfmt+"]"); } @Override @@ -413,8 +412,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig @Override public void addDeviceEventListener(AccelDeviceEventListener l) { - int screen = getDevice().getCoreGraphicsScreen(); - AccelDeviceEventNotifier.addListener(l, screen); + int displayID = getDevice().getCGDisplayID(); + AccelDeviceEventNotifier.addListener(l, displayID); } @Override diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CRobot.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CRobot.java index e04a45fd579..c74a589a328 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CRobot.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CRobot.java @@ -65,7 +65,7 @@ class CRobot implements RobotPeer { mouseLastX = x; mouseLastY = y; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, mouseButtonsState, true, true); } @@ -79,7 +79,7 @@ class CRobot implements RobotPeer { public void mousePress(int buttons) { mouseButtonsState |= buttons; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, true, false); } @@ -93,7 +93,7 @@ class CRobot implements RobotPeer { public void mouseRelease(int buttons) { mouseButtonsState &= ~buttons; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, false, false); } @@ -163,7 +163,7 @@ class CRobot implements RobotPeer { } private native void initRobot(); - private native void mouseEvent(int screen, int lastX, int lastY, + private native void mouseEvent(int displayID, int lastX, int lastY, int buttonsState, boolean isButtonsDownState, boolean isMouseMove); diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 83bc9f1f700..579468601e2 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -352,7 +352,7 @@ public final class LWCToolkit extends LWToolkit { @Override public Insets getScreenInsets(final GraphicsConfiguration gc) { final CGraphicsConfig cgc = (CGraphicsConfig) gc; - final int displayId = cgc.getDevice().getCoreGraphicsScreen(); + final int displayId = cgc.getDevice().getCGDisplayID(); Rectangle fullScreen, workArea; final long screen = CWrapper.NSScreen.screenByDisplayId(displayId); try { diff --git a/jdk/src/macosx/native/sun/awt/CRobot.m b/jdk/src/macosx/native/sun/awt/CRobot.m index c04d5685a56..056fd19e29f 100644 --- a/jdk/src/macosx/native/sun/awt/CRobot.m +++ b/jdk/src/macosx/native/sun/awt/CRobot.m @@ -135,7 +135,7 @@ Java_sun_lwawt_macosx_CRobot_initRobot JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CRobot_mouseEvent (JNIEnv *env, jobject peer, - jint screenIndex, jint mouseLastX, jint mouseLastY, jint buttonsState, + jint displayID, jint mouseLastX, jint mouseLastY, jint buttonsState, jboolean isButtonsDownState, jboolean isMouseMove) { JNF_COCOA_ENTER(env); @@ -149,8 +149,6 @@ Java_sun_lwawt_macosx_CRobot_mouseEvent CGError err = kCGErrorSuccess; - CGDirectDisplayID displayID = - FindCGDirectDisplayIDForScreenIndex(screenIndex); CGRect globalDeviceBounds = CGDisplayBounds(displayID); // Set unknown mouse location, if needed. diff --git a/jdk/src/macosx/native/sun/awt/LWCToolkit.h b/jdk/src/macosx/native/sun/awt/LWCToolkit.h index c318421c2e1..8df2c553996 100644 --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.h +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.h @@ -44,8 +44,6 @@ extern jint* gButtonDownMasks; + (void) eventCountPlusPlus; @end -CGDirectDisplayID FindCGDirectDisplayIDForScreenIndex(jint screenIndex); - /* * Utility Macros */ diff --git a/jdk/src/macosx/native/sun/awt/LWCToolkit.m b/jdk/src/macosx/native/sun/awt/LWCToolkit.m index ec4870eba69..47c72abbfa5 100644 --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m @@ -177,39 +177,6 @@ Java_sun_lwawt_macosx_LWCToolkit_beep NSBeep(); // produces both sound and visual flash, if configured in System Preferences } -CGDirectDisplayID -FindCGDirectDisplayIDForScreenIndex(jint screenIndex) -{ - // most common case - just one monitor - CGDirectDisplayID screenID = CGMainDisplayID(); - - CGDisplayCount displayCount = 0; - CGGetOnlineDisplayList(0, NULL, &displayCount); - - if ((displayCount > 1) && - (screenIndex >= 0) && - (screenIndex < (jint)displayCount)) - { - if (displayCount < 10) { - // stack allocated optimization for less than 10 monitors - CGDirectDisplayID onlineDisplays[displayCount]; - CGGetOnlineDisplayList(displayCount, onlineDisplays, &displayCount); - screenID = (CGDirectDisplayID)onlineDisplays[screenIndex]; - } else { - CGDirectDisplayID *onlineDisplays = - malloc(displayCount*sizeof(CGDirectDisplayID)); - if (onlineDisplays != NULL) { - CGGetOnlineDisplayList(displayCount, onlineDisplays, - &displayCount); - screenID = (CGDirectDisplayID)onlineDisplays[screenIndex]; - free(onlineDisplays); - } - } - } - - return screenID; -} - /* * Class: sun_lwawt_macosx_LWCToolkit * Method: initIDs diff --git a/jdk/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m b/jdk/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m index 0bc58ec6ad3..a9de285758d 100644 --- a/jdk/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m +++ b/jdk/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m @@ -192,12 +192,12 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_initCGL JNIEXPORT jlong JNICALL Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo (JNIEnv *env, jclass cglgc, - jint screennum, jint pixfmt, jint swapInterval) + jint displayID, jint pixfmt, jint swapInterval) { jlong ret = 0L; JNF_COCOA_ENTER(env); NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:3]; - [retArray addObject: [NSNumber numberWithInt: (int)screennum]]; + [retArray addObject: [NSNumber numberWithInt: (int)displayID]]; [retArray addObject: [NSNumber numberWithInt: (int)pixfmt]]; [retArray addObject: [NSNumber numberWithInt: (int)swapInterval]]; if ([NSThread isMainThread]) { @@ -217,7 +217,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo + (void) _getCGLConfigInfo: (NSMutableArray *)argValue { AWT_ASSERT_APPKIT_THREAD; - jint screennum = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue]; + jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue]; jint pixfmt = (jint)[(NSNumber *)[argValue objectAtIndex: 1] intValue]; jint swapInterval = (jint)[(NSNumber *)[argValue objectAtIndex: 2] intValue]; JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; @@ -230,16 +230,11 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo CGOpenGLDisplayMask glMask = (CGOpenGLDisplayMask)pixfmt; if (sharedContext == NULL) { if (glMask == 0) { - CGDirectDisplayID id = - FindCGDirectDisplayIDForScreenIndex(screennum); - glMask = CGDisplayIDToOpenGLDisplayMask(id); + glMask = CGDisplayIDToOpenGLDisplayMask(displayID); } NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFAClosestPolicy, - NSOpenGLPFANoRecovery, - NSOpenGLPFAAccelerated, - NSOpenGLPFAFullScreen, NSOpenGLPFAWindow, NSOpenGLPFAPixelBuffer, NSOpenGLPFADoubleBuffer, @@ -412,7 +407,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo return; } memset(cglinfo, 0, sizeof(CGLGraphicsConfigInfo)); - cglinfo->screen = screennum; + cglinfo->screen = displayID; cglinfo->pixfmt = sharedPixelFormat; cglinfo->context = oglc; @@ -422,17 +417,6 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo } @end //GraphicsConfigUtil - -JNIEXPORT jint JNICALL -Java_sun_java2d_opengl_CGLGraphicsConfig_getDefaultPixFmt - (JNIEnv *env, jclass cglgc, jint screennum) -{ - J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getDefaultPixFmt"); - - CGDirectDisplayID id = FindCGDirectDisplayIDForScreenIndex(screennum); - return (jint)CGDisplayIDToOpenGLDisplayMask(id); -} - JNIEXPORT jint JNICALL Java_sun_java2d_opengl_CGLGraphicsConfig_getOGLCapabilities (JNIEnv *env, jclass cglgc, jlong configInfo) From 1270c690887e3b58d90b3a4a09a363f782d70dde Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Thu, 28 Feb 2013 20:27:38 +0400 Subject: [PATCH 069/102] 8003169: [macosx] JVM crash after disconnecting from projector Reviewed-by: anthony, alexsch --- .../classes/sun/awt/CGraphicsDevice.java | 20 +++++--- .../classes/sun/lwawt/macosx/LWCToolkit.java | 19 +------- .../macosx/native/sun/awt/CGraphicsDevice.m | 46 ++++++++++++++++++- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java b/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java index c4786eebcce..1a5e22af582 100644 --- a/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java +++ b/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -29,6 +29,7 @@ import java.awt.AWTPermission; import java.awt.DisplayMode; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; +import java.awt.Insets; import java.awt.Window; import java.util.Objects; @@ -110,8 +111,9 @@ public final class CGraphicsDevice extends GraphicsDevice { return nativeGetYResolution(displayID); } - private static native double nativeGetXResolution(int displayID); - private static native double nativeGetYResolution(int displayID); + public Insets getScreenInsets() { + return nativeGetScreenInsets(displayID); + } /** * Enters full-screen mode, or returns to windowed mode. @@ -217,9 +219,15 @@ public final class CGraphicsDevice extends GraphicsDevice { return nativeGetDisplayModes(displayID); } - private native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate); + private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate); - private native DisplayMode nativeGetDisplayMode(int displayID); + private static native DisplayMode nativeGetDisplayMode(int displayID); - private native DisplayMode[] nativeGetDisplayModes(int displayID); + private static native DisplayMode[] nativeGetDisplayModes(int displayID); + + private static native double nativeGetXResolution(int displayID); + + private static native double nativeGetYResolution(int displayID); + + private static native Insets nativeGetScreenInsets(int displayID); } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 579468601e2..a15eb46a1d1 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -351,22 +351,7 @@ public final class LWCToolkit extends LWToolkit { @Override public Insets getScreenInsets(final GraphicsConfiguration gc) { - final CGraphicsConfig cgc = (CGraphicsConfig) gc; - final int displayId = cgc.getDevice().getCGDisplayID(); - Rectangle fullScreen, workArea; - final long screen = CWrapper.NSScreen.screenByDisplayId(displayId); - try { - fullScreen = CWrapper.NSScreen.frame(screen).getBounds(); - workArea = CWrapper.NSScreen.visibleFrame(screen).getBounds(); - } finally { - CWrapper.NSObject.release(screen); - } - // Convert between Cocoa's coordinate system and Java. - int bottom = workArea.y - fullScreen.y; - int top = fullScreen.height - workArea.height - bottom; - int left = workArea.x - fullScreen.x; - int right = fullScreen.width - workArea.width - left; - return new Insets(top, left, bottom, right); + return ((CGraphicsConfig) gc).getDevice().getScreenInsets(); } @Override diff --git a/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m b/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m index 9bc5393d765..1e2df28dd56 100644 --- a/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m +++ b/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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,8 @@ * questions. */ -#include "LWCToolkit.h" +#import "LWCToolkit.h" +#import "ThreadUtilities.h" /* * Convert the mode string to the more convinient bits per pixel value @@ -146,6 +147,47 @@ Java_sun_awt_CGraphicsDevice_nativeGetYResolution return dpi; } +/* + * Class: sun_awt_CGraphicsDevice + * Method: nativeGetScreenInsets + * Signature: (I)D + */ +JNIEXPORT jobject JNICALL +Java_sun_awt_CGraphicsDevice_nativeGetScreenInsets + (JNIEnv *env, jclass class, jint displayID) +{ + jobject ret = NULL; + __block NSRect frame = NSZeroRect; + __block NSRect visibleFrame = NSZeroRect; +JNF_COCOA_ENTER(env); + + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + NSArray *screens = [NSScreen screens]; + for (NSScreen *screen in screens) { + NSDictionary *screenInfo = [screen deviceDescription]; + NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"]; + if ([screenID pointerValue] == displayID){ + frame = [screen frame]; + visibleFrame = [screen visibleFrame]; + break; + } + } + }]; + // Convert between Cocoa's coordinate system and Java. + jint bottom = visibleFrame.origin.y - frame.origin.y; + jint top = frame.size.height - visibleFrame.size.height - bottom; + jint left = visibleFrame.origin.x - frame.origin.x; + jint right = frame.size.width - visibleFrame.size.width - left; + + static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets"); + static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V"); + ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right); + +JNF_COCOA_EXIT(env); + + return ret; +} + /* * Class: sun_awt_CGraphicsDevice * Method: nativeSetDisplayMode From 19bc54290f90b10094a7ab4b82bb50278fbbdcc8 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 1 Mar 2013 14:30:52 +0400 Subject: [PATCH 070/102] 7163696: JCK Swing interactive test JScrollBarTest0013 fails with Nimbus and GTK L&Fs Reviewed-by: alexsch --- .../classes/java/beans/PropertyDescriptor.java | 7 +------ jdk/test/java/beans/Introspector/Test7192955.java | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index c03149c0574..0abdcad972b 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -109,10 +109,6 @@ public class PropertyDescriptor extends FeatureDescriptor { if (writeMethodName != null && getWriteMethod() == null) { throw new IntrospectionException("Method not found: " + writeMethodName); } - boundInitialization(beanClass); - } - - private void boundInitialization(Class beanClass) { // If this class or one of its base classes allow PropertyChangeListener, // then we assume that any properties we discover are "bound". // See Introspector.getTargetPropertyInfo() method. @@ -163,7 +159,6 @@ public class PropertyDescriptor extends FeatureDescriptor { setReadMethod(read); setWriteMethod(write); this.baseName = base; - boundInitialization(bean); } /** diff --git a/jdk/test/java/beans/Introspector/Test7192955.java b/jdk/test/java/beans/Introspector/Test7192955.java index 13e874ba719..afce427bf30 100644 --- a/jdk/test/java/beans/Introspector/Test7192955.java +++ b/jdk/test/java/beans/Introspector/Test7192955.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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,17 +23,20 @@ /* * @test - * @bug 7192955 + * @bug 7192955 8000183 * @summary Tests that all properties are bound * @author Sergey Malenkov */ +import java.beans.IntrospectionException; +import java.beans.Introspector; import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; import java.util.List; public class Test7192955 { - public static void main(String[] args) { + public static void main(String[] args) throws IntrospectionException { if (!BeanUtils.findPropertyDescriptor(MyBean.class, "test").isBound()) { throw new Error("a simple property is not bound"); } @@ -43,6 +46,12 @@ public class Test7192955 { if (!BeanUtils.findPropertyDescriptor(MyBean.class, "readOnly").isBound()) { throw new Error("a read-only property is not bound"); } + PropertyDescriptor[] pds = Introspector.getBeanInfo(MyBean.class, BaseBean.class).getPropertyDescriptors(); + for (PropertyDescriptor pd : pds) { + if (pd.getName().equals("test") && pd.isBound()) { + throw new Error("a simple property is bound without superclass"); + } + } } public static class BaseBean { From b6a841d5a330404bd1e34ff3efdf9797b66ccaba Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 1 Mar 2013 15:31:22 +0400 Subject: [PATCH 071/102] 7194902: [macosx] closed/java/awt/Button/DoubleActionEventTest/DoubleActionEventTest failed since jdk8b49 7181403: Invalid MouseEvent conversion with SwingUtilities.convertMouseEvent Reviewed-by: malenkov, alexsch --- .../macosx/classes/sun/lwawt/LWComponentPeer.java | 13 +++++++++---- .../share/classes/javax/swing/SwingUtilities.java | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java index 301fbb476d8..052b91726b6 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -1227,10 +1227,10 @@ public abstract class LWComponentPeer } protected void sendEventToDelegate(final AWTEvent e) { + if (getDelegate() == null || !isShowing() || !isEnabled()) { + return; + } synchronized (getDelegateLock()) { - if (getDelegate() == null || !isShowing() || !isEnabled()) { - return; - } AWTEvent delegateEvent = createDelegateEvent(e); if (delegateEvent != null) { AWTAccessor.getComponentAccessor() @@ -1244,7 +1244,12 @@ public abstract class LWComponentPeer } } - protected AWTEvent createDelegateEvent(AWTEvent e) { + /** + * Changes the target of the AWTEvent from awt component to appropriate + * swing delegate. + */ + private AWTEvent createDelegateEvent(final AWTEvent e) { + // TODO modifiers should be changed to getModifiers()|getModifiersEx()? AWTEvent delegateEvent = null; if (e instanceof MouseWheelEvent) { MouseWheelEvent me = (MouseWheelEvent) e; diff --git a/jdk/src/share/classes/javax/swing/SwingUtilities.java b/jdk/src/share/classes/javax/swing/SwingUtilities.java index 956bb838be7..6bb308d2f1e 100644 --- a/jdk/src/share/classes/javax/swing/SwingUtilities.java +++ b/jdk/src/share/classes/javax/swing/SwingUtilities.java @@ -356,7 +356,7 @@ public class SwingUtilities implements SwingConstants sourceEvent.getYOnScreen(), sourceEvent.getClickCount(), sourceEvent.isPopupTrigger(), - MouseEvent.NOBUTTON ); + sourceEvent.getButton()); } return newEvent; } From b87df9f9e127378d2fff1601dc5fe7a26173d3d8 Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 1 Mar 2013 04:58:31 -0800 Subject: [PATCH 072/102] 8009226: new hotspot build - hs25-b22 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 bcc1ff8f148..b52c3c52dfb 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013 HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=21 +HS_BUILD_NUMBER=22 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From 916da4ac2cb01f07f1f32d3977310bb917385464 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 1 Mar 2013 21:50:00 +0400 Subject: [PATCH 073/102] 7184945: [macosx] NPE in AquaComboBoxUI since jdk7u6b17, jdk8b47 Reviewed-by: malenkov, alexsch --- .../classes/com/apple/laf/AquaComboBoxUI.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java b/jdk/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java index a4831d29ea9..8e8527f6541 100644 --- a/jdk/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java +++ b/jdk/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -34,7 +34,6 @@ import javax.swing.border.Border; import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*; -import com.apple.laf.ClientPropertyApplicator; import com.apple.laf.ClientPropertyApplicator.Property; import apple.laf.JRSUIConstants.Size; @@ -142,35 +141,46 @@ public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable { return new AquaComboBoxEditor(); } - class AquaComboBoxEditor extends BasicComboBoxEditor implements UIResource, DocumentListener { - protected AquaComboBoxEditor() { + final class AquaComboBoxEditor extends BasicComboBoxEditor + implements UIResource, DocumentListener { + + AquaComboBoxEditor() { super(); editor = new AquaCustomComboTextField(); editor.addFocusListener(this); editor.getDocument().addDocumentListener(this); } + @Override public void focusGained(final FocusEvent e) { - arrowButton.repaint(); + if (arrowButton != null) { + arrowButton.repaint(); + } } + @Override public void focusLost(final FocusEvent e) { - arrowButton.repaint(); + if (arrowButton != null) { + arrowButton.repaint(); + } } + @Override public void changedUpdate(final DocumentEvent e) { editorTextChanged(); } + @Override public void insertUpdate(final DocumentEvent e) { editorTextChanged(); } + @Override public void removeUpdate(final DocumentEvent e) { editorTextChanged(); } - protected void editorTextChanged() { + private void editorTextChanged() { if (!popup.isVisible()) return; final Object text = editor.getText(); From 4dd999e1eef01e0ad4e9d1343a4f01a12522c100 Mon Sep 17 00:00:00 2001 From: Morris Meyer Date: Fri, 1 Mar 2013 14:26:34 -0800 Subject: [PATCH 074/102] 8008327: [parfait] Unitialized variable in hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m Fix unitialized variable and return value. Reviewed-by: kvn --- hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m b/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m index 98ace91a2c6..c14c6b7bc4b 100644 --- a/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m +++ b/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m @@ -160,7 +160,7 @@ Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0( CHECK_EXCEPTION_(0); unsigned long alignedAddress; - unsigned long alignedLength; + unsigned long alignedLength = 0; kern_return_t result; vm_offset_t *pages; int *mapped; @@ -630,7 +630,7 @@ Java_sun_jvm_hotspot_asm_Disassembler_load_1library( /* Couldn't find entry point. error_message should contain some * platform dependent error message. */ - THROW_NEW_DEBUGGER_EXCEPTION(error_message); + THROW_NEW_DEBUGGER_EXCEPTION_(error_message, (jlong)func); } return (jlong)func; } From 37aa83449e4b0f11ba33f359817255f9b1660a7d Mon Sep 17 00:00:00 2001 From: Erik Helin Date: Mon, 4 Mar 2013 13:01:24 +0100 Subject: [PATCH 075/102] 8004172: Update jstat counter names to reflect metaspace changes Reviewed-by: stefank, jmasa --- .../src/share/vm/memory/metaspaceCounters.cpp | 107 ++++++------------ .../src/share/vm/memory/metaspaceCounters.hpp | 2 - 2 files changed, 34 insertions(+), 75 deletions(-) diff --git a/hotspot/src/share/vm/memory/metaspaceCounters.cpp b/hotspot/src/share/vm/memory/metaspaceCounters.cpp index 17b94597b94..dc2f4f733aa 100644 --- a/hotspot/src/share/vm/memory/metaspaceCounters.cpp +++ b/hotspot/src/share/vm/memory/metaspaceCounters.cpp @@ -25,12 +25,14 @@ #include "precompiled.hpp" #include "memory/metaspaceCounters.hpp" #include "memory/resourceArea.hpp" - -#define METASPACE_NAME "perm" +#include "utilities/exceptions.hpp" MetaspaceCounters* MetaspaceCounters::_metaspace_counters = NULL; -MetaspaceCounters::MetaspaceCounters() { +MetaspaceCounters::MetaspaceCounters() : + _capacity(NULL), + _used(NULL), + _max_capacity(NULL) { if (UsePerfData) { size_t min_capacity = MetaspaceAux::min_chunk_size(); size_t max_capacity = MetaspaceAux::reserved_in_bytes(); @@ -41,6 +43,25 @@ MetaspaceCounters::MetaspaceCounters() { } } +static PerfVariable* create_ms_variable(const char *ns, + const char *name, + size_t value, + TRAPS) { + const char *path = PerfDataManager::counter_name(ns, name); + PerfVariable *result = + PerfDataManager::create_variable(SUN_GC, path, PerfData::U_Bytes, value, + CHECK_NULL); + return result; +} + +static void create_ms_constant(const char *ns, + const char *name, + size_t value, + TRAPS) { + const char *path = PerfDataManager::counter_name(ns, name); + PerfDataManager::create_constant(SUN_GC, path, PerfData::U_Bytes, value, CHECK); +} + void MetaspaceCounters::initialize(size_t min_capacity, size_t max_capacity, size_t curr_capacity, @@ -50,93 +71,32 @@ void MetaspaceCounters::initialize(size_t min_capacity, EXCEPTION_MARK; ResourceMark rm; - // Create a name that will be recognized by jstat tools as - // the perm gen. Change this to a Metaspace name when the - // tools are fixed. - // name to recognize "sun.gc.generation.2.*" + const char *ms = "metaspace"; - const char* name = METASPACE_NAME; - const int ordinal = 2; - const int spaces = 1; - - const char* cns = PerfDataManager::name_space("generation", ordinal); - - _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtClass); - strcpy(_name_space, cns); - - const char* cname = PerfDataManager::counter_name(_name_space, "name"); - PerfDataManager::create_string_constant(SUN_GC, cname, name, CHECK); - - // End of perm gen like name creation - - cname = PerfDataManager::counter_name(_name_space, "spaces"); - PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_None, - spaces, CHECK); - - cname = PerfDataManager::counter_name(_name_space, "minCapacity"); - PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, - min_capacity, CHECK); - - cname = PerfDataManager::counter_name(_name_space, "maxCapacity"); - PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, - max_capacity, CHECK); - - cname = PerfDataManager::counter_name(_name_space, "capacity"); - _current_size = - PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, - curr_capacity, CHECK); - - // SpaceCounter like counters - // name to recognize "sun.gc.generation.2.space.0.*" - { - const int space_ordinal = 0; - const char* cns = PerfDataManager::name_space(_name_space, "space", - space_ordinal); - - char* space_name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtClass); - strcpy(space_name_space, cns); - - const char* cname = PerfDataManager::counter_name(space_name_space, "name"); - PerfDataManager::create_string_constant(SUN_GC, cname, name, CHECK); - - cname = PerfDataManager::counter_name(space_name_space, "maxCapacity"); - _max_capacity = PerfDataManager::create_variable(SUN_GC, cname, - PerfData::U_Bytes, - (jlong)max_capacity, CHECK); - - cname = PerfDataManager::counter_name(space_name_space, "capacity"); - _capacity = PerfDataManager::create_variable(SUN_GC, cname, - PerfData::U_Bytes, - curr_capacity, CHECK); - - cname = PerfDataManager::counter_name(space_name_space, "used"); - _used = PerfDataManager::create_variable(SUN_GC, - cname, - PerfData::U_Bytes, - used, - CHECK); - - cname = PerfDataManager::counter_name(space_name_space, "initCapacity"); - PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, - min_capacity, CHECK); - } + create_ms_constant(ms, "minCapacity", min_capacity, CHECK); + _max_capacity = create_ms_variable(ms, "maxCapacity", max_capacity, CHECK); + _capacity = create_ms_variable(ms, "capacity", curr_capacity, CHECK); + _used = create_ms_variable(ms, "used", used, CHECK); } } void MetaspaceCounters::update_capacity() { assert(UsePerfData, "Should not be called unless being used"); + assert(_capacity != NULL, "Should be initialized"); size_t capacity_in_bytes = MetaspaceAux::capacity_in_bytes(); _capacity->set_value(capacity_in_bytes); } void MetaspaceCounters::update_used() { assert(UsePerfData, "Should not be called unless being used"); + assert(_used != NULL, "Should be initialized"); size_t used_in_bytes = MetaspaceAux::used_in_bytes(); _used->set_value(used_in_bytes); } void MetaspaceCounters::update_max_capacity() { assert(UsePerfData, "Should not be called unless being used"); + assert(_max_capacity != NULL, "Should be initialized"); size_t reserved_in_bytes = MetaspaceAux::reserved_in_bytes(); _max_capacity->set_value(reserved_in_bytes); } @@ -146,18 +106,19 @@ void MetaspaceCounters::update_all() { update_used(); update_capacity(); update_max_capacity(); - _current_size->set_value(MetaspaceAux::reserved_in_bytes()); } } void MetaspaceCounters::initialize_performance_counters() { if (UsePerfData) { + assert(_metaspace_counters == NULL, "Should only be initialized once"); _metaspace_counters = new MetaspaceCounters(); } } void MetaspaceCounters::update_performance_counters() { if (UsePerfData) { + assert(_metaspace_counters != NULL, "Should be initialized"); _metaspace_counters->update_all(); } } diff --git a/hotspot/src/share/vm/memory/metaspaceCounters.hpp b/hotspot/src/share/vm/memory/metaspaceCounters.hpp index ab0556fd160..4b6de646b60 100644 --- a/hotspot/src/share/vm/memory/metaspaceCounters.hpp +++ b/hotspot/src/share/vm/memory/metaspaceCounters.hpp @@ -29,11 +29,9 @@ class MetaspaceCounters: public CHeapObj { friend class VMStructs; - PerfVariable* _current_size; PerfVariable* _capacity; PerfVariable* _used; PerfVariable* _max_capacity; - char* _name_space; static MetaspaceCounters* _metaspace_counters; void initialize(size_t min_capacity, size_t max_capacity, From e3e82316299caa4c2211c067752814b6e55da66c Mon Sep 17 00:00:00 2001 From: Erik Helin Date: Mon, 4 Mar 2013 15:40:12 +0100 Subject: [PATCH 076/102] 8009384: Temporarily disable jstat tests to ease complicated push Reviewed-by: mchung --- jdk/test/ProblemList.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 840a9274293..3c4dc859980 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -330,6 +330,23 @@ tools/launcher/I18NJarTest.java macosx-all # 8007410 tools/launcher/FXLauncherTest.java linux-all +# 8004172 +sun/tools/jstat/jstatGcCapacityOutput1.sh generic-all +sun/tools/jstat/jstatGcCauseOutput1.sh generic-all +sun/tools/jstat/jstatGcOldOutput1.sh generic-all +sun/tools/jstat/jstatGcOutput1.sh generic-all +sun/tools/jstat/jstatGcPermCapacityOutput1.sh generic-all +sun/tools/jstat/jstatLineCounts1.sh generic-all +sun/tools/jstat/jstatLineCounts2.sh generic-all +sun/tools/jstat/jstatLineCounts3.sh generic-all +sun/tools/jstat/jstatLineCounts4.sh generic-all +sun/tools/jstat/jstatOptions1.sh generic-all +sun/tools/jstat/jstatTimeStamp1.sh generic-all +sun/tools/jstatd/jstatdExternalRegistry.sh generic-all +sun/tools/jstatd/jstatdDefaults.sh generic-all +sun/tools/jstatd/jstatdPort.sh generic-all +sun/tools/jstatd/jstatdServerName.sh generic-all + ############################################################################ # jdk_jdi From a3a42c48e82d258719fe16b83b2820033fdd0fc8 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Mon, 4 Mar 2013 12:42:14 -0800 Subject: [PATCH 077/102] 8007036: G1: Too many old regions added to last mixed GC Stop adding old regions to collection set when the remaining reclaimable bytes reaches, or goes below, G1HeapWastePercent. Changes were also reviewed by Vitaly Davidovich . Reviewed-by: brutisso --- .../g1/collectionSetChooser.cpp | 37 ------- .../g1/collectionSetChooser.hpp | 11 +-- .../g1/g1CollectorPolicy.cpp | 96 ++++++++++++++++--- .../g1/g1CollectorPolicy.hpp | 12 +++ 4 files changed, 101 insertions(+), 55 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp index f4c6a71439b..ed4b807fb4a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp @@ -146,43 +146,6 @@ void CollectionSetChooser::sort_regions() { verify(); } -uint CollectionSetChooser::calc_min_old_cset_length() { - // The min old CSet region bound is based on the maximum desired - // number of mixed GCs after a cycle. I.e., even if some old regions - // look expensive, we should add them to the CSet anyway to make - // sure we go through the available old regions in no more than the - // maximum desired number of mixed GCs. - // - // The calculation is based on the number of marked regions we added - // to the CSet chooser in the first place, not how many remain, so - // that the result is the same during all mixed GCs that follow a cycle. - - const size_t region_num = (size_t) _length; - const size_t gc_num = (size_t) G1MixedGCCountTarget; - size_t result = region_num / gc_num; - // emulate ceiling - if (result * gc_num < region_num) { - result += 1; - } - return (uint) result; -} - -uint CollectionSetChooser::calc_max_old_cset_length() { - // The max old CSet region bound is based on the threshold expressed - // as a percentage of the heap size. I.e., it should bound the - // number of old regions added to the CSet irrespective of how many - // of them are available. - - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - const size_t region_num = g1h->n_regions(); - const size_t perc = (size_t) G1OldCSetRegionThresholdPercent; - size_t result = region_num * perc / 100; - // emulate ceiling - if (100 * result < region_num * perc) { - result += 1; - } - return (uint) result; -} void CollectionSetChooser::add_region(HeapRegion* hr) { assert(!hr->isHumongous(), diff --git a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp index 1a147b83147..e9f6f8225af 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp @@ -51,6 +51,8 @@ class CollectionSetChooser: public CHeapObj { uint _curr_index; // The number of candidate old regions added to the CSet chooser. + // Note: this is not updated when removing a region using + // remove_and_move_to_next() below. uint _length; // Keeps track of the start of the next array chunk to be claimed by @@ -111,13 +113,8 @@ public: hr->live_bytes() < _region_live_threshold_bytes; } - // Calculate the minimum number of old regions we'll add to the CSet - // during a mixed GC. - uint calc_min_old_cset_length(); - - // Calculate the maximum number of old regions we'll add to the CSet - // during a mixed GC. - uint calc_max_old_cset_length(); + // Returns the number candidate old regions added + uint length() { return _length; } // Serial version. void add_region(HeapRegion *hr); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 4231e95f3b5..87acfec56f9 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -1806,6 +1806,14 @@ void G1CollectorPolicy::print_collection_set(HeapRegion* list_head, outputStream } #endif // !PRODUCT +double G1CollectorPolicy::reclaimable_bytes_perc(size_t reclaimable_bytes) { + // Returns the given amount of reclaimable bytes (that represents + // the amount of reclaimable space still to be collected) as a + // percentage of the current heap capacity. + size_t capacity_bytes = _g1->capacity(); + return (double) reclaimable_bytes * 100.0 / (double) capacity_bytes; +} + bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str, const char* false_action_str) { CollectionSetChooser* cset_chooser = _collectionSetChooser; @@ -1815,19 +1823,21 @@ bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str, ergo_format_reason("candidate old regions not available")); return false; } + + // Is the amount of uncollected reclaimable space above G1HeapWastePercent? size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes(); - size_t capacity_bytes = _g1->capacity(); - double perc = (double) reclaimable_bytes * 100.0 / (double) capacity_bytes; + double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes); double threshold = (double) G1HeapWastePercent; - if (perc < threshold) { + if (reclaimable_perc <= threshold) { ergo_verbose4(ErgoMixedGCs, false_action_str, - ergo_format_reason("reclaimable percentage lower than threshold") + ergo_format_reason("reclaimable percentage not over threshold") ergo_format_region("candidate old regions") ergo_format_byte_perc("reclaimable") ergo_format_perc("threshold"), cset_chooser->remaining_regions(), - reclaimable_bytes, perc, threshold); + reclaimable_bytes, + reclaimable_perc, threshold); return false; } @@ -1838,10 +1848,50 @@ bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str, ergo_format_byte_perc("reclaimable") ergo_format_perc("threshold"), cset_chooser->remaining_regions(), - reclaimable_bytes, perc, threshold); + reclaimable_bytes, + reclaimable_perc, threshold); return true; } +uint G1CollectorPolicy::calc_min_old_cset_length() { + // The min old CSet region bound is based on the maximum desired + // number of mixed GCs after a cycle. I.e., even if some old regions + // look expensive, we should add them to the CSet anyway to make + // sure we go through the available old regions in no more than the + // maximum desired number of mixed GCs. + // + // The calculation is based on the number of marked regions we added + // to the CSet chooser in the first place, not how many remain, so + // that the result is the same during all mixed GCs that follow a cycle. + + const size_t region_num = (size_t) _collectionSetChooser->length(); + const size_t gc_num = (size_t) MAX2(G1MixedGCCountTarget, (uintx) 1); + size_t result = region_num / gc_num; + // emulate ceiling + if (result * gc_num < region_num) { + result += 1; + } + return (uint) result; +} + +uint G1CollectorPolicy::calc_max_old_cset_length() { + // The max old CSet region bound is based on the threshold expressed + // as a percentage of the heap size. I.e., it should bound the + // number of old regions added to the CSet irrespective of how many + // of them are available. + + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + const size_t region_num = g1h->n_regions(); + const size_t perc = (size_t) G1OldCSetRegionThresholdPercent; + size_t result = region_num * perc / 100; + // emulate ceiling + if (100 * result < region_num * perc) { + result += 1; + } + return (uint) result; +} + + void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { double young_start_time_sec = os::elapsedTime(); @@ -1855,7 +1905,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); double predicted_pause_time_ms = base_time_ms; - double time_remaining_ms = target_pause_time_ms - base_time_ms; + double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0); ergo_verbose4(ErgoCSetConstruction | ErgoHigh, "start choosing CSet", @@ -1893,7 +1943,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { _collection_set = _inc_cset_head; _collection_set_bytes_used_before = _inc_cset_bytes_used_before; - time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms; + time_remaining_ms = MAX2(time_remaining_ms - _inc_cset_predicted_elapsed_time_ms, 0.0); predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms; ergo_verbose3(ErgoCSetConstruction | ErgoHigh, @@ -1917,8 +1967,8 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { if (!gcs_are_young()) { CollectionSetChooser* cset_chooser = _collectionSetChooser; cset_chooser->verify(); - const uint min_old_cset_length = cset_chooser->calc_min_old_cset_length(); - const uint max_old_cset_length = cset_chooser->calc_max_old_cset_length(); + const uint min_old_cset_length = calc_min_old_cset_length(); + const uint max_old_cset_length = calc_max_old_cset_length(); uint expensive_region_num = 0; bool check_time_remaining = adaptive_young_list_length(); @@ -1936,6 +1986,30 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { break; } + + // Stop adding regions if the remaining reclaimable space is + // not above G1HeapWastePercent. + size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes(); + double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes); + double threshold = (double) G1HeapWastePercent; + if (reclaimable_perc <= threshold) { + // We've added enough old regions that the amount of uncollected + // reclaimable space is at or below the waste threshold. Stop + // adding old regions to the CSet. + ergo_verbose5(ErgoCSetConstruction, + "finish adding old regions to CSet", + ergo_format_reason("reclaimable percentage not over threshold") + ergo_format_region("old") + ergo_format_region("max") + ergo_format_byte_perc("reclaimable") + ergo_format_perc("threshold"), + old_cset_region_length(), + max_old_cset_length, + reclaimable_bytes, + reclaimable_perc, threshold); + break; + } + double predicted_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young()); if (check_time_remaining) { if (predicted_time_ms > time_remaining_ms) { @@ -1975,7 +2049,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { } // We will add this region to the CSet. - time_remaining_ms -= predicted_time_ms; + time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0); predicted_pause_time_ms += predicted_time_ms; cset_chooser->remove_and_move_to_next(hr); _g1->old_set_remove(hr); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index d32d1e66c10..0c04167c8a4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -619,6 +619,18 @@ private: bool predict_will_fit(uint young_length, double base_time_ms, uint base_free_regions, double target_pause_time_ms); + // Calculate the minimum number of old regions we'll add to the CSet + // during a mixed GC. + uint calc_min_old_cset_length(); + + // Calculate the maximum number of old regions we'll add to the CSet + // during a mixed GC. + uint calc_max_old_cset_length(); + + // Returns the given amount of uncollected reclaimable space + // as a percentage of the current heap capacity. + double reclaimable_bytes_perc(size_t reclaimable_bytes); + public: G1CollectorPolicy(); From 999837eb3045f23c19b28aff4aaa4a136e9c0e36 Mon Sep 17 00:00:00 2001 From: Morris Meyer Date: Mon, 4 Mar 2013 13:15:01 -0800 Subject: [PATCH 078/102] 8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value Safety checks for non-Apple thread time functions Reviewed-by: kvn --- hotspot/src/os/bsd/vm/os_bsd.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 1bc86d13bce..79119a03a00 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -3903,15 +3903,27 @@ bool os::pd_unmap_memory(char* addr, size_t bytes) { jlong os::current_thread_cpu_time() { #ifdef __APPLE__ return os::thread_cpu_time(Thread::current(), true /* user + sys */); +#else + Unimplemented(); + return 0; #endif } jlong os::thread_cpu_time(Thread* thread) { +#ifdef __APPLE__ + return os::thread_cpu_time(thread, true /* user + sys */); +#else + Unimplemented(); + return 0; +#endif } jlong os::current_thread_cpu_time(bool user_sys_cpu_time) { #ifdef __APPLE__ return os::thread_cpu_time(Thread::current(), user_sys_cpu_time); +#else + Unimplemented(); + return 0; #endif } @@ -3935,6 +3947,9 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { } else { return ((jlong)tinfo.user_time.seconds * 1000000000) + ((jlong)tinfo.user_time.microseconds * (jlong)1000); } +#else + Unimplemented(); + return 0; #endif } From f167bb36ab6e0ba843eea0434d6cb0d435c548b6 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 4 Mar 2013 22:39:00 -0800 Subject: [PATCH 079/102] 8008451: Make mac builds on 10.8 work on 10.7 Reviewed-by: jcoomes, ohair --- hotspot/make/bsd/makefiles/gcc.make | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index 2cee1b0034e..6d25e307bab 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -229,6 +229,20 @@ ifeq ($(USE_PRECOMPILED_HEADER),0) CFLAGS += -DDONT_USE_PRECOMPILED_HEADER endif +ifeq ($(OS_VENDOR), Darwin) + # Setting these parameters makes it an error to link to macosx APIs that are + # newer than the given OS version and makes the linked binaries compatible even + # if built on a newer version of the OS. + # The expected format is X.Y.Z + ifeq ($(MACOSX_VERSION_MIN),) + MACOSX_VERSION_MIN=10.7.0 + endif + # The macro takes the version with no dots, ex: 1070 + CFLAGS += -DMAC_OS_X_VERSION_MAX_ALLOWED=$(subst .,,$(MACOSX_VERSION_MIN)) \ + -mmacosx-version-min=$(MACOSX_VERSION_MIN) + LDFLAGS += -mmacosx-version-min=$(MACOSX_VERSION_MIN) +endif + #------------------------------------------------------------------------ # Linker flags From ff36c9800e2d2e60e60776e9856d5743571554fe Mon Sep 17 00:00:00 2001 From: Morris Meyer Date: Tue, 5 Mar 2013 04:24:33 -0800 Subject: [PATCH 080/102] 8008574: [parfait] Null pointer deference in hotspot/src/share/vm/runtime/frame.cpp Fix null pointer Reviewed-by: kvn --- hotspot/src/share/vm/runtime/frame.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index f20fca0154c..e1913829702 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -1070,7 +1070,12 @@ oop frame::retrieve_receiver(RegisterMap* reg_map) { // First consult the ADLC on where it puts parameter 0 for this signature. VMReg reg = SharedRuntime::name_for_receiver(); - oop r = *caller.oopmapreg_to_location(reg, reg_map); + oop* oop_adr = caller.oopmapreg_to_location(reg, reg_map); + if (oop_adr == NULL) { + guarantee(oop_adr != NULL, "bad register save location"); + return NULL; + } + oop r = *oop_adr; assert(Universe::heap()->is_in_or_null(r), err_msg("bad receiver: " INTPTR_FORMAT " (" INTX_FORMAT ")", (intptr_t) r, (intptr_t) r)); return r; } From 4b638cf955826f4617c7adb3eabca04e1c3ff40e Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 5 Mar 2013 04:24:50 -0800 Subject: [PATCH 081/102] 8009120: Fuzz instruction scheduling in HotSpot compilers Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/opto/c2_globals.hpp | 6 ++++ hotspot/src/share/vm/opto/compile.cpp | 35 ++++++++++++++++++++++++ hotspot/src/share/vm/opto/compile.hpp | 3 ++ hotspot/src/share/vm/opto/gcm.cpp | 10 +++++-- hotspot/src/share/vm/opto/lcm.cpp | 14 ++++++---- 5 files changed, 61 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 43895fc6ed2..f01101cd4bb 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -54,6 +54,12 @@ #define C2_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct) \ \ + develop(bool, StressLCM, false, \ + "Randomize instruction scheduling in LCM") \ + \ + develop(bool, StressGCM, false, \ + "Randomize instruction scheduling in GCM") \ + \ notproduct(intx, CompileZapFirst, 0, \ "If +ZapDeadCompiledLocals, " \ "skip this many before compiling in zap calls") \ diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 4b80483865d..2016751788e 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -3669,3 +3669,38 @@ void Compile::add_expensive_node(Node * n) { n->set_req(0, NULL); } } + +// Auxiliary method to support randomized stressing/fuzzing. +// +// This method can be called the arbitrary number of times, with current count +// as the argument. The logic allows selecting a single candidate from the +// running list of candidates as follows: +// int count = 0; +// Cand* selected = null; +// while(cand = cand->next()) { +// if (randomized_select(++count)) { +// selected = cand; +// } +// } +// +// Including count equalizes the chances any candidate is "selected". +// This is useful when we don't have the complete list of candidates to choose +// from uniformly. In this case, we need to adjust the randomicity of the +// selection, or else we will end up biasing the selection towards the latter +// candidates. +// +// Quick back-envelope calculation shows that for the list of n candidates +// the equal probability for the candidate to persist as "best" can be +// achieved by replacing it with "next" k-th candidate with the probability +// of 1/k. It can be easily shown that by the end of the run, the +// probability for any candidate is converged to 1/n, thus giving the +// uniform distribution among all the candidates. +// +// We don't care about the domain size as long as (RANDOMIZED_DOMAIN / count) is large. +#define RANDOMIZED_DOMAIN_POW 29 +#define RANDOMIZED_DOMAIN (1 << RANDOMIZED_DOMAIN_POW) +#define RANDOMIZED_DOMAIN_MASK ((1 << (RANDOMIZED_DOMAIN_POW + 1)) - 1) +bool Compile::randomized_select(int count) { + assert(count > 0, "only positive"); + return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count); +} diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 2cb12fa2e09..5e7de5b7066 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -1086,6 +1086,9 @@ class Compile : public Phase { // Definitions of pd methods static void pd_compiler2_init(); + + // Auxiliary method for randomized fuzzing/stressing + static bool randomized_select(int count); }; #endif // SHARE_VM_OPTO_COMPILE_HPP diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index 4fffeeb80d3..811dc5c6c87 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -1046,6 +1046,8 @@ Block* PhaseCFG::hoist_to_cheaper_block(Block* LCA, Block* early, Node* self) { } #endif + int cand_cnt = 0; // number of candidates tried + // Walk up the dominator tree from LCA (Lowest common ancestor) to // the earliest legal location. Capture the least execution frequency. while (LCA != early) { @@ -1071,8 +1073,11 @@ Block* PhaseCFG::hoist_to_cheaper_block(Block* LCA, Block* early, Node* self) { LCA->_pre_order, LCA->_nodes[0]->_idx, start_lat, end_idx, end_lat, LCA_freq); } #endif + cand_cnt++; if (LCA_freq < least_freq || // Better Frequency - ( !in_latency && // No block containing latency + (StressGCM && Compile::randomized_select(cand_cnt)) || // Should be randomly accepted in stress mode + (!StressGCM && // Otherwise, choose with latency + !in_latency && // No block containing latency LCA_freq < least_freq * delta && // No worse frequency target >= end_lat && // within latency range !self->is_iteratively_computed() ) // But don't hoist IV increments @@ -1210,7 +1215,8 @@ void PhaseCFG::schedule_late(VectorSet &visited, Node_List &stack) { } // If there is no opportunity to hoist, then we're done. - bool try_to_hoist = (LCA != early); + // In stress mode, try to hoist even the single operations. + bool try_to_hoist = StressGCM || (LCA != early); // Must clone guys stay next to use; no hoisting allowed. // Also cannot hoist guys that alter memory or are otherwise not diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 35006ff23b4..ddb55d30e62 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -421,6 +421,7 @@ Node *Block::select(PhaseCFG *cfg, Node_List &worklist, GrowableArray &read uint latency = 0; // Bigger is scheduled first uint score = 0; // Bigger is better int idx = -1; // Index in worklist + int cand_cnt = 0; // Candidate count for( uint i=0; i &read uint n_score = n->req(); // Many inputs get high score to break ties // Keep best latency found - if( choice < n_choice || - ( choice == n_choice && - ( latency < n_latency || - ( latency == n_latency && - ( score < n_score ))))) { + cand_cnt++; + if (choice < n_choice || + (choice == n_choice && + ((StressLCM && Compile::randomized_select(cand_cnt)) || + (!StressLCM && + (latency < n_latency || + (latency == n_latency && + (score < n_score))))))) { choice = n_choice; latency = n_latency; score = n_score; From 7659fe9df29c3325df8020c5a921c5387d2a0ccf Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Tue, 5 Mar 2013 17:18:55 +0400 Subject: [PATCH 082/102] 7152608: [macosx] Crash in liblwawt.dylib in AccelGlyphCache_RemoveCellInfo Reviewed-by: jgodinez, ant --- jdk/src/macosx/classes/sun/font/CStrike.java | 10 ++++++++-- .../classes/sun/font/CStrikeDisposer.java | 2 ++ jdk/src/macosx/native/sun/font/AWTStrike.m | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/jdk/src/macosx/classes/sun/font/CStrike.java b/jdk/src/macosx/classes/sun/font/CStrike.java index 61fe234cb29..9635b85a1de 100644 --- a/jdk/src/macosx/classes/sun/font/CStrike.java +++ b/jdk/src/macosx/classes/sun/font/CStrike.java @@ -500,7 +500,10 @@ public class CStrike extends FontStrike { final Iterator i = generalCache.values().iterator(); while (i.hasNext()) { final long longValue = i.next().longValue(); - if (longValue != -1 && longValue != 0) StrikeCache.freeLongPointer(longValue); + if (longValue != -1 && longValue != 0) { + removeGlyphInfoFromCache(longValue); + StrikeCache.freeLongPointer(longValue); + } } } @@ -512,7 +515,10 @@ public class CStrike extends FontStrike { private static void disposeLongArray(final long[] longArray) { for (int i = 0; i < longArray.length; i++) { final long ptr = longArray[i]; - if (ptr != 0 && ptr != -1) StrikeCache.freeLongPointer(ptr); // free's the native struct pointer + if (ptr != 0 && ptr != -1) { + removeGlyphInfoFromCache(ptr); + StrikeCache.freeLongPointer(ptr); // free's the native struct pointer + } } } diff --git a/jdk/src/macosx/classes/sun/font/CStrikeDisposer.java b/jdk/src/macosx/classes/sun/font/CStrikeDisposer.java index 7357ea6bd42..661bd6a7b42 100644 --- a/jdk/src/macosx/classes/sun/font/CStrikeDisposer.java +++ b/jdk/src/macosx/classes/sun/font/CStrikeDisposer.java @@ -85,4 +85,6 @@ class CStrikeDisposer extends FontStrikeDisposer { } private native void freeNativeScalerContext(long pContext); + + protected static native void removeGlyphInfoFromCache(long glyphInfo); } diff --git a/jdk/src/macosx/native/sun/font/AWTStrike.m b/jdk/src/macosx/native/sun/font/AWTStrike.m index 261bd34ae57..7f04b530ade 100644 --- a/jdk/src/macosx/native/sun/font/AWTStrike.m +++ b/jdk/src/macosx/native/sun/font/AWTStrike.m @@ -27,11 +27,13 @@ #import "java_awt_geom_PathIterator.h" #import "sun_awt_SunHints.h" #import "sun_font_CStrike.h" +#import "sun_font_CStrikeDisposer.h" #import "CGGlyphImages.h" #import "CGGlyphOutlines.h" #import "AWTStrike.h" #import "CoreTextSupport.h" //#import "jni_util.h" +#include "fontscalerdefs.h" /* Use THIS_FILE when it is available. */ #ifndef THIS_FILE @@ -423,3 +425,19 @@ JNF_COCOA_EXIT(env); return metrics; } + +extern void AccelGlyphCache_RemoveAllInfos(GlyphInfo* glyph); +/* + * Class: sun_font_CStrikeDisposer + * Method: removeGlyphInfoFromCache + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_font_CStrikeDisposer_removeGlyphInfoFromCache +(JNIEnv *env, jclass cls, jlong glyphInfo) +{ + JNF_COCOA_ENTER(env); + + AccelGlyphCache_RemoveAllCellInfos((GlyphInfo*)jlong_to_ptr(glyphInfo)); + + JNF_COCOA_EXIT(env); +} From 15108cd14e619d80cda58115c87bab4c1e22fbef Mon Sep 17 00:00:00 2001 From: Morris Meyer Date: Tue, 5 Mar 2013 18:03:36 -0800 Subject: [PATCH 083/102] 8008750: [partfait] Null pointer deference in hotspot/src/share/vm/oops/instanceKlass.hpp Fix null pointer Reviewed-by: kvn, coleenp --- hotspot/src/share/vm/oops/instanceKlass.cpp | 13 +++++++++---- hotspot/src/share/vm/oops/instanceKlass.hpp | 9 +++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index f492b895605..fd66a276c8c 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -2170,7 +2170,11 @@ void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { if (impl != NULL) { if (!impl->is_loader_alive(is_alive)) { // remove this guy - *adr_implementor() = NULL; + Klass** klass = adr_implementor(); + assert(klass != NULL, "null klass"); + if (klass != NULL) { + *klass = NULL; + } } } } @@ -3151,9 +3155,10 @@ void InstanceKlass::verify_on(outputStream* st) { if (protection_domain() != NULL) { guarantee(protection_domain()->is_oop(), "should be oop"); } - if (host_klass() != NULL) { - guarantee(host_klass()->is_metadata(), "should be in metaspace"); - guarantee(host_klass()->is_klass(), "should be klass"); + const Klass* host = host_klass(); + if (host != NULL) { + guarantee(host->is_metadata(), "should be in metaspace"); + guarantee(host->is_klass(), "should be klass"); } if (signers() != NULL) { guarantee(signers()->is_objArray(), "should be obj array"); diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 600cb56465c..ef2f446d14f 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -536,7 +536,9 @@ class InstanceKlass: public Klass { assert(is_anonymous(), "not anonymous"); Klass** addr = (Klass**)adr_host_klass(); assert(addr != NULL, "no reversed space"); - *addr = host; + if (addr != NULL) { + *addr = host; + } } bool is_anonymous() const { return (_misc_flags & _misc_is_anonymous) != 0; @@ -758,7 +760,10 @@ class InstanceKlass: public Klass { void set_implementor(Klass* k) { assert(is_interface(), "not interface"); Klass** addr = adr_implementor(); - *addr = k; + assert(addr != NULL, "null addr"); + if (addr != NULL) { + *addr = k; + } } int nof_implementors() const { From 748083843ac94aa2e7d5c2e229a09b62249d72a4 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 6 Mar 2013 10:28:38 +0100 Subject: [PATCH 084/102] 8009460: C2compiler crash in machnode::in_regmask(unsigned int) 7121140 may not correctly break the Allocate -> MemBarStoreStore link Reviewed-by: kvn --- hotspot/src/share/vm/opto/compile.cpp | 7 +++++++ hotspot/src/share/vm/opto/macro.cpp | 8 +------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 2016751788e..568af91f127 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -2899,6 +2899,13 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { } } break; + case Op_MemBarStoreStore: + // Break the link with AllocateNode: it is no longer useful and + // confuses register allocation. + if (n->req() > MemBarNode::Precedent) { + n->set_req(MemBarNode::Precedent, top()); + } + break; default: assert( !n->is_Call(), "" ); assert( !n->is_Mem(), "" ); diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 2dde491380c..aeb1b6226be 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -1101,12 +1101,6 @@ void PhaseMacroExpand::expand_allocate_common( Node* klass_node = alloc->in(AllocateNode::KlassNode); Node* initial_slow_test = alloc->in(AllocateNode::InitialTest); - Node* storestore = alloc->storestore(); - if (storestore != NULL) { - // Break this link that is no longer useful and confuses register allocation - storestore->set_req(MemBarNode::Precedent, top()); - } - assert(ctrl != NULL, "must have control"); // We need a Region and corresponding Phi's to merge the slow-path and fast-path results. // they will not be used if "always_slow" is set @@ -1324,7 +1318,7 @@ void PhaseMacroExpand::expand_allocate_common( // No InitializeNode or no stores captured by zeroing // elimination. Simply add the MemBarStoreStore after object // initialization. - MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot, fast_oop_rawmem); + MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot); transform_later(mb); mb->init_req(TypeFunc::Memory, fast_oop_rawmem); From ef56e8fdec0712d3ae3b1b6d2b5551e7fab82162 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 6 Mar 2013 10:50:37 +0100 Subject: [PATCH 085/102] 8008073: build-infra: Need --with-dxsdk option? And awt/sound -I option additions? Reviewed-by: tbell --- common/autoconf/generated-configure.sh | 440 ++++++++++++++++++++++++- common/autoconf/spec.gmk.in | 4 + common/autoconf/toolchain.m4 | 1 + common/autoconf/toolchain_windows.m4 | 56 ++++ 4 files changed, 500 insertions(+), 1 deletion(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 31764abe4e0..0787d4bac42 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -725,6 +725,8 @@ BUILD_LD BUILD_CXX BUILD_CC MSVCR_DLL +DXSDK_INCLUDE_PATH +DXSDK_LIB_PATH VS_PATH VS_LIB VS_INCLUDE @@ -985,6 +987,9 @@ with_override_hotspot with_override_jdk with_import_hotspot with_msvcr_dll +with_dxsdk +with_dxsdk_lib +with_dxsdk_include with_extra_cflags with_extra_cxxflags with_extra_ldflags @@ -1736,6 +1741,11 @@ Optional Packages: source --with-msvcr-dll copy this msvcr100.dll into the built JDK (Windows only) [probed] + --with-dxsdk the DirectX SDK (Windows only) [probed] + --with-dxsdk-lib the DirectX SDK lib directory (Windows only) + [probed] + --with-dxsdk-include the DirectX SDK include directory (Windows only) + [probed] --with-extra-cflags extra flags to be used when compiling jdk c-files --with-extra-cxxflags extra flags to be used when compiling jdk c++-files --with-extra-ldflags extra flags to be used when linking jdk @@ -3720,6 +3730,10 @@ fi +# Setup the DXSDK paths + + + @@ -3729,7 +3743,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1362411827 +DATE_WHEN_GENERATED=1362563419 ############################################################################### # @@ -16952,6 +16966,430 @@ $as_echo "$as_me: The path of MSVCR_DLL, which resolves as \"$path\", is invalid fi + + +# Check whether --with-dxsdk was given. +if test "${with_dxsdk+set}" = set; then : + withval=$with_dxsdk; +fi + + +# Check whether --with-dxsdk-lib was given. +if test "${with_dxsdk_lib+set}" = set; then : + withval=$with_dxsdk_lib; +fi + + +# Check whether --with-dxsdk-include was given. +if test "${with_dxsdk_include+set}" = set; then : + withval=$with_dxsdk_include; +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DirectX SDK" >&5 +$as_echo_n "checking for DirectX SDK... " >&6; } + + if test "x$with_dxsdk" != x; then + dxsdk_path="$with_dxsdk" + elif test "x$DXSDK_DIR" != x; then + dxsdk_path="$DXSDK_DIR" + else + as_fn_error $? "Could not find the DirectX SDK" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dxsdk_path" >&5 +$as_echo "$dxsdk_path" >&6; } + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # Input might be given as Windows format, start by converting to + # unix format. + path="$dxsdk_path" + new_path=`$CYGPATH -u "$path"` + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file precense. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of dxsdk_path, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of dxsdk_path, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of dxsdk_path" "$LINENO" 5 + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + + if test "x$path" != "x$new_path"; then + dxsdk_path="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting dxsdk_path to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting dxsdk_path to \"$new_path\"" >&6;} + fi + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + path="$dxsdk_path" + has_colon=`$ECHO $path | $GREP ^.:` + new_path="$path" + if test "x$has_colon" = x; then + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $path` + fi + + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + if test "x$path" != "x$new_path"; then + dxsdk_path="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting dxsdk_path to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting dxsdk_path to \"$new_path\"" >&6;} + fi + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + + else + # We're on a posix platform. Hooray! :) + path="$dxsdk_path" + + if test ! -f "$path" && test ! -d "$path"; then + as_fn_error $? "The path of dxsdk_path, which resolves as \"$path\", is not found." "$LINENO" 5 + fi + + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of dxsdk_path, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of dxsdk_path, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 + fi + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DirectX SDK lib dir" >&5 +$as_echo_n "checking for DirectX SDK lib dir... " >&6; } + if test "x$with_dxsdk_lib" != x; then + DXSDK_LIB_PATH="$with_dxsdk_lib" + elif test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then + DXSDK_LIB_PATH="$dxsdk_path/Lib/x64" + else + DXSDK_LIB_PATH="$dxsdk_path/Lib" + fi + # dsound.lib is linked to in jsoundds + if test ! -f "$DXSDK_LIB_PATH/dsound.lib"; then + as_fn_error $? "Invalid DirectX SDK lib dir" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DXSDK_LIB_PATH" >&5 +$as_echo "$DXSDK_LIB_PATH" >&6; } + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # Input might be given as Windows format, start by converting to + # unix format. + path="$DXSDK_LIB_PATH" + new_path=`$CYGPATH -u "$path"` + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file precense. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of DXSDK_LIB_PATH, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of DXSDK_LIB_PATH, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of DXSDK_LIB_PATH" "$LINENO" 5 + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + + if test "x$path" != "x$new_path"; then + DXSDK_LIB_PATH="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DXSDK_LIB_PATH to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting DXSDK_LIB_PATH to \"$new_path\"" >&6;} + fi + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + path="$DXSDK_LIB_PATH" + has_colon=`$ECHO $path | $GREP ^.:` + new_path="$path" + if test "x$has_colon" = x; then + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $path` + fi + + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + if test "x$path" != "x$new_path"; then + DXSDK_LIB_PATH="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DXSDK_LIB_PATH to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting DXSDK_LIB_PATH to \"$new_path\"" >&6;} + fi + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + + else + # We're on a posix platform. Hooray! :) + path="$DXSDK_LIB_PATH" + + if test ! -f "$path" && test ! -d "$path"; then + as_fn_error $? "The path of DXSDK_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 + fi + + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of DXSDK_LIB_PATH, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of DXSDK_LIB_PATH, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 + fi + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DirectX SDK include dir" >&5 +$as_echo_n "checking for DirectX SDK include dir... " >&6; } + if test "x$with_dxsdk_include" != x; then + DXSDK_INCLUDE_PATH="$with_dxsdk_include" + else + DXSDK_INCLUDE_PATH="$dxsdk_path/Include" + fi + # dsound.h is included in jsoundds + if test ! -f "$DXSDK_INCLUDE_PATH/dsound.h"; then + as_fn_error $? "Invalid DirectX SDK lib dir" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DXSDK_INCLUDE_PATH" >&5 +$as_echo "$DXSDK_INCLUDE_PATH" >&6; } + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # Input might be given as Windows format, start by converting to + # unix format. + path="$DXSDK_INCLUDE_PATH" + new_path=`$CYGPATH -u "$path"` + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file precense. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of DXSDK_INCLUDE_PATH" "$LINENO" 5 + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + + if test "x$path" != "x$new_path"; then + DXSDK_INCLUDE_PATH="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DXSDK_INCLUDE_PATH to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting DXSDK_INCLUDE_PATH to \"$new_path\"" >&6;} + fi + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + path="$DXSDK_INCLUDE_PATH" + has_colon=`$ECHO $path | $GREP ^.:` + new_path="$path" + if test "x$has_colon" = x; then + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $path` + fi + + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + if test "x$path" != "x$new_path"; then + DXSDK_INCLUDE_PATH="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DXSDK_INCLUDE_PATH to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting DXSDK_INCLUDE_PATH to \"$new_path\"" >&6;} + fi + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + + else + # We're on a posix platform. Hooray! :) + path="$DXSDK_INCLUDE_PATH" + + if test ! -f "$path" && test ! -d "$path"; then + as_fn_error $? "The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 + fi + + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 + fi + fi + + + + + LDFLAGS_JDK="$LDFLAGS_JDK -libpath:$DXSDK_LIB_PATH" + fi diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 358ad783833..5753b5f8200 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -285,6 +285,10 @@ X_CFLAGS:=@X_CFLAGS@ X_LIBS:=@X_LIBS@ OPENWIN_HOME:=@OPENWIN_HOME@ +# DirectX SDK +DXSDK_LIB_PATH=@DXSDK_LIB_PATH@ +DXSDK_INCLUDE_PATH=@DXSDK_INCLUDE_PATH@ + # The lowest required version of macosx to enforce compatiblity for MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@ diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 569da99c1c0..9a464aac1ae 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -176,6 +176,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_PATHS], [ if test "x$OPENJDK_TARGET_OS" = "xwindows"; then TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV + TOOLCHAIN_SETUP_DXSDK fi AC_SUBST(MSVCR_DLL) diff --git a/common/autoconf/toolchain_windows.m4 b/common/autoconf/toolchain_windows.m4 index ca325d240e8..dd093fdbc12 100644 --- a/common/autoconf/toolchain_windows.m4 +++ b/common/autoconf/toolchain_windows.m4 @@ -262,3 +262,59 @@ AC_DEFUN([TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV], AC_MSG_RESULT([$MSVCR_DLL]) BASIC_FIXUP_PATH(MSVCR_DLL) ]) + + +# Setup the DXSDK paths +AC_DEFUN([TOOLCHAIN_SETUP_DXSDK], +[ + AC_ARG_WITH(dxsdk, [AS_HELP_STRING([--with-dxsdk], + [the DirectX SDK (Windows only) @<:@probed@:>@])]) + AC_ARG_WITH(dxsdk-lib, [AS_HELP_STRING([--with-dxsdk-lib], + [the DirectX SDK lib directory (Windows only) @<:@probed@:>@])]) + AC_ARG_WITH(dxsdk-include, [AS_HELP_STRING([--with-dxsdk-include], + [the DirectX SDK include directory (Windows only) @<:@probed@:>@])]) + + AC_MSG_CHECKING([for DirectX SDK]) + + if test "x$with_dxsdk" != x; then + dxsdk_path="$with_dxsdk" + elif test "x$DXSDK_DIR" != x; then + dxsdk_path="$DXSDK_DIR" + else + AC_MSG_ERROR([Could not find the DirectX SDK]) + fi + AC_MSG_RESULT([$dxsdk_path]) + BASIC_FIXUP_PATH(dxsdk_path) + + AC_MSG_CHECKING([for DirectX SDK lib dir]) + if test "x$with_dxsdk_lib" != x; then + DXSDK_LIB_PATH="$with_dxsdk_lib" + elif test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then + DXSDK_LIB_PATH="$dxsdk_path/Lib/x64" + else + DXSDK_LIB_PATH="$dxsdk_path/Lib" + fi + # dsound.lib is linked to in jsoundds + if test ! -f "$DXSDK_LIB_PATH/dsound.lib"; then + AC_MSG_ERROR([Invalid DirectX SDK lib dir]) + fi + AC_MSG_RESULT([$DXSDK_LIB_PATH]) + BASIC_FIXUP_PATH(DXSDK_LIB_PATH) + + AC_MSG_CHECKING([for DirectX SDK include dir]) + if test "x$with_dxsdk_include" != x; then + DXSDK_INCLUDE_PATH="$with_dxsdk_include" + else + DXSDK_INCLUDE_PATH="$dxsdk_path/Include" + fi + # dsound.h is included in jsoundds + if test ! -f "$DXSDK_INCLUDE_PATH/dsound.h"; then + AC_MSG_ERROR([Invalid DirectX SDK lib dir]) + fi + AC_MSG_RESULT([$DXSDK_INCLUDE_PATH]) + BASIC_FIXUP_PATH(DXSDK_INCLUDE_PATH) + + AC_SUBST(DXSDK_LIB_PATH) + AC_SUBST(DXSDK_INCLUDE_PATH) + LDFLAGS_JDK="$LDFLAGS_JDK -libpath:$DXSDK_LIB_PATH" +]) From 5b60a94e4f903f644e34b1c9e9903c03b71373ce Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 6 Mar 2013 16:15:16 +0100 Subject: [PATCH 086/102] 8008073: build-infra: Need --with-dxsdk option? And awt/sound -I option additions? Reviewed-by: tbell --- jdk/makefiles/CompileNativeLibraries.gmk | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/jdk/makefiles/CompileNativeLibraries.gmk b/jdk/makefiles/CompileNativeLibraries.gmk index 01dbc2ba417..9b38b5aba79 100644 --- a/jdk/makefiles/CompileNativeLibraries.gmk +++ b/jdk/makefiles/CompileNativeLibraries.gmk @@ -464,12 +464,13 @@ ifeq ($(OPENJDK_TARGET_OS),windows) $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/windows \ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows \ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/d3d + LIBAWT_CFLAGS+=-I$(DXSDK_INCLUDE_PATH) else LIBAWT_DIRS+=\ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/x11 endif -LIBAWT_CFLAGS:=-D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES \ +LIBAWT_CFLAGS+=-D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES \ $(X_CFLAGS) \ $(foreach dir,$(LIBAWT_DIRS),-I$(dir)) @@ -1461,7 +1462,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows) -I$(JDK_TOPDIR)/src/share/native/sun/awt/debug \ -I$(JDK_TOPDIR)/src/share/native/sun/java2d \ -I$(JDK_TOPDIR)/src/share/native/sun/awt/image/cvutils \ - -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows, \ + -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows \ + -I$(DXSDK_INCLUDE_PATH), \ LDFLAGS:=$(LDFLAGS_JDKLIB) $(KERNEL32_LIB) $(LDFLAGS_CXX_JDK) \ advapi32.lib $(WIN_AWT_LIB),\ LDFLAGS_SUFFIX:=$(LDFLAGS_JDKLIB_SUFFIX),\ @@ -2907,7 +2909,8 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJSOUNDDS,\ OPTIMIZATION:=LOW, \ CFLAGS:=$(CFLAGS_JDKLIB) \ $(LIBJSOUND_CFLAGS) \ - -DUSE_DAUDIO=TRUE, \ + -DUSE_DAUDIO=TRUE \ + -I$(DXSDK_INCLUDE_PATH), \ LDFLAGS:=$(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN),\ LDFLAGS_SUFFIX:=$(LDFLAGS_JDKLIB_SUFFIX) dsound.lib winmm.lib user32.lib ole32.lib,\ From a99c6a7fe59941b9c9bf0fcd89830e651f6f0da3 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Wed, 6 Mar 2013 19:42:26 +0400 Subject: [PATCH 087/102] 6877495: JTextField and JTextArea does not support supplementary characters Reviewed-by: serb, alexp --- .../sun/awt/datatransfer/DataTransferer.java | 49 ++++-- .../SuplementaryCharactersTransferTest.java | 165 ++++++++++++++++++ 2 files changed, 199 insertions(+), 15 deletions(-) create mode 100644 jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java diff --git a/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java b/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java index f8dd9dfc380..7465d52c8bf 100644 --- a/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java +++ b/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java @@ -1873,7 +1873,7 @@ search: */ public class ReencodingInputStream extends InputStream { protected BufferedReader wrapped; - protected final char[] in = new char[1]; + protected final char[] in = new char[2]; protected byte[] out; protected CharsetEncoder encoder; @@ -1926,7 +1926,7 @@ search: try { encoder = Charset.forName(targetEncoding).newEncoder(); - out = new byte[(int)(encoder.maxBytesPerChar() + 0.5)]; + out = new byte[(int)(encoder.maxBytesPerChar() * 2 + 0.5)]; inBuf = CharBuffer.wrap(in); outBuf = ByteBuffer.wrap(out); } catch (IllegalCharsetNameException e) { @@ -1950,31 +1950,50 @@ search: } } + private int readChar() throws IOException { + int c = wrapped.read(); + + if (c == -1) { // -1 is EOS + eos = true; + return -1; + } + + // "c == 0" is not quite correct, but good enough on Windows. + if (numTerminators > 0 && c == 0) { + eos = true; + return -1; + } else if (eoln != null && matchCharArray(eoln, c)) { + c = '\n' & 0xFFFF; + } + + return c; + } + public int read() throws IOException { if (eos) { return -1; } if (index >= limit) { - int c = wrapped.read(); - - if (c == -1) { // -1 is EOS - eos = true; + // deal with supplementary characters + int c = readChar(); + if (c == -1) { return -1; } - // "c == 0" is not quite correct, but good enough on Windows. - if (numTerminators > 0 && c == 0) { - eos = true; - return -1; - } else if (eoln != null && matchCharArray(eoln, c)) { - c = '\n' & 0xFFFF; + in[0] = (char) c; + in[1] = 0; + inBuf.limit(1); + if (Character.isHighSurrogate((char) c)) { + c = readChar(); + if (c != -1) { + in[1] = (char) c; + inBuf.limit(2); + } } - in[0] = (char)c; - inBuf.rewind(); - outBuf.rewind(); + outBuf.limit(out.length).rewind(); encoder.encode(inBuf, outBuf, false); outBuf.flip(); limit = outBuf.limit(); diff --git a/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java b/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java new file mode 100644 index 00000000000..75f63496bfa --- /dev/null +++ b/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013, 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 6877495 + @summary JTextField and JTextArea does not support supplementary characters + @author Alexander Scherbatiy + @run main SuplementaryCharactersTransferTest +*/ + + +import java.io.*; +import java.util.*; +import java.awt.*; +import java.awt.datatransfer.*; +import sun.awt.datatransfer.*; +import sun.awt.datatransfer.DataTransferer.ReencodingInputStream; + +public class SuplementaryCharactersTransferTest { + + public static final long TEXT_FORMAT = 13; + + public static void main(String[] args) throws Exception { + + DataTransferer dataTransferer = new TestDataTransferer(); + dataTransferer.registerTextFlavorProperties("UNICODE TEXT", "utf-16le", "\r\n", "2"); + ByteTransferable transferable = new ByteTransferable(); + ReencodingInputStream is = dataTransferer.new ReencodingInputStream(transferable.getByteInputStream(), TEXT_FORMAT, + DataTransferer.getTextCharset(transferable.getDataFlavor()), transferable); + + byte[] bytes = transferable.getBytes(); + byte[] result = new byte[bytes.length]; + + is.read(result); + + for (int i = 0; i < bytes.length; i++) { + if (bytes[i] != result[i]) { + throw new RuntimeException("Characters are not equal!"); + } + } + + } + + static class ByteTransferable implements Transferable, ClipboardOwner { + + private final DataFlavor dataFlavor; + + public ByteTransferable() throws Exception { + dataFlavor = DataFlavor.getTextPlainUnicodeFlavor(); + } + + public DataFlavor getDataFlavor() { + return dataFlavor; + } + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{dataFlavor}; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor.equals(dataFlavor); + } + + public byte[] getBytes() { + return new byte[]{97, 0, 64, -40, 32, -36, 98, 0}; + } + + public InputStream getByteInputStream() { + return new ByteArrayInputStream(getBytes()); + } + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException { + if (flavor.equals(dataFlavor)) { + return getByteInputStream(); + } else { + throw new UnsupportedFlavorException(flavor); + } + } + + public void lostOwnership(Clipboard clipboard, Transferable contents) { + } + } + + static class TestDataTransferer extends DataTransferer { + + @Override + public String getDefaultUnicodeEncoding() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean isLocaleDependentTextFormat(long format) { + return false; + } + + @Override + public boolean isFileFormat(long format) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean isImageFormat(long format) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected Long getFormatForNativeAsLong(String str) { + return TEXT_FORMAT; + } + + @Override + protected String getNativeForFormat(long format) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected ByteArrayOutputStream convertFileListToBytes( + ArrayList fileList) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected String[] dragQueryFile(byte[] bytes) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected Image platformImageBytesOrStreamToImage(InputStream str, + byte[] bytes, long format) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected byte[] imageToPlatformBytes(Image image, long format) + throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() { + throw new UnsupportedOperationException("Not supported yet."); + } + } +} \ No newline at end of file From b1d7c46e1428251f988db984d892a697e258eafb Mon Sep 17 00:00:00 2001 From: Mikhail Cherkasov Date: Wed, 6 Mar 2013 20:10:04 +0400 Subject: [PATCH 088/102] 8007295: Reduce number of warnings in awt classes Reviewed-by: bae, anthony --- .../classes/java/awt/CheckboxMenuItem.java | 2 +- jdk/src/share/classes/java/awt/Cursor.java | 20 +++++++++---------- .../share/classes/java/awt/EventQueue.java | 6 +++--- jdk/src/share/classes/java/awt/Menu.java | 18 ++++++++--------- jdk/src/share/classes/java/awt/MenuBar.java | 12 +++++------ .../share/classes/java/awt/MenuComponent.java | 4 ++-- jdk/src/share/classes/java/awt/MenuItem.java | 2 +- .../classes/java/awt/RenderingHints.java | 9 +++++---- .../java/awt/datatransfer/Clipboard.java | 8 ++++---- .../java/awt/dnd/DragGestureEvent.java | 7 +++---- .../java/awt/dnd/DragGestureRecognizer.java | 2 +- .../classes/java/awt/dnd/DragSource.java | 9 ++++----- .../awt/dnd/InvalidDnDOperationException.java | 2 ++ .../java/awt/geom/AffineTransform.java | 19 ++++++++++++++++++ 14 files changed, 70 insertions(+), 50 deletions(-) diff --git a/jdk/src/share/classes/java/awt/CheckboxMenuItem.java b/jdk/src/share/classes/java/awt/CheckboxMenuItem.java index 635e9b55b89..ad12d4c29a9 100644 --- a/jdk/src/share/classes/java/awt/CheckboxMenuItem.java +++ b/jdk/src/share/classes/java/awt/CheckboxMenuItem.java @@ -277,7 +277,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * @since 1.4 */ public synchronized ItemListener[] getItemListeners() { - return (ItemListener[])(getListeners(ItemListener.class)); + return getListeners(ItemListener.class); } /** diff --git a/jdk/src/share/classes/java/awt/Cursor.java b/jdk/src/share/classes/java/awt/Cursor.java index c340532b20d..d022a647869 100644 --- a/jdk/src/share/classes/java/awt/Cursor.java +++ b/jdk/src/share/classes/java/awt/Cursor.java @@ -163,11 +163,11 @@ public class Cursor implements java.io.Serializable { * hashtable, filesystem dir prefix, filename, and properties for custom cursors support */ - private static final Hashtable systemCustomCursors = new Hashtable(1); + private static final Hashtable systemCustomCursors = new Hashtable<>(1); private static final String systemCustomCursorDirPrefix = initCursorDir(); private static String initCursorDir() { - String jhome = (String) java.security.AccessController.doPrivileged( + String jhome = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("java.home")); return jhome + File.separator + "lib" + File.separator + "images" + @@ -298,7 +298,7 @@ public class Cursor implements java.io.Serializable { static public Cursor getSystemCustomCursor(final String name) throws AWTException, HeadlessException { GraphicsEnvironment.checkHeadless(); - Cursor cursor = (Cursor)systemCustomCursors.get(name); + Cursor cursor = systemCustomCursors.get(name); if (cursor == null) { synchronized(systemCustomCursors) { @@ -319,11 +319,11 @@ public class Cursor implements java.io.Serializable { final String fileName = systemCustomCursorProperties.getProperty(key); - String localized = (String)systemCustomCursorProperties.getProperty(prefix + DotNameSuffix); + String localized = systemCustomCursorProperties.getProperty(prefix + DotNameSuffix); if (localized == null) localized = name; - String hotspot = (String)systemCustomCursorProperties.getProperty(prefix + DotHotspotSuffix); + String hotspot = systemCustomCursorProperties.getProperty(prefix + DotHotspotSuffix); if (hotspot == null) throw new AWTException("no hotspot property defined for cursor: " + name); @@ -348,9 +348,9 @@ public class Cursor implements java.io.Serializable { final int fy = y; final String flocalized = localized; - cursor = (Cursor) java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws Exception { + cursor = java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { + public Cursor run() throws Exception { Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image = toolkit.getImage( systemCustomCursorDirPrefix + fileName); @@ -447,8 +447,8 @@ public class Cursor implements java.io.Serializable { systemCustomCursorProperties = new Properties(); try { - AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { + AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { public Object run() throws Exception { FileInputStream fis = null; try { diff --git a/jdk/src/share/classes/java/awt/EventQueue.java b/jdk/src/share/classes/java/awt/EventQueue.java index 5ba9756a1af..7f84721dd9e 100644 --- a/jdk/src/share/classes/java/awt/EventQueue.java +++ b/jdk/src/share/classes/java/awt/EventQueue.java @@ -171,7 +171,7 @@ public class EventQueue { * The modifiers field of the current event, if the current event is an * InputEvent or ActionEvent. */ - private WeakReference currentEvent; + private WeakReference currentEvent; /* * Non-zero if a thread is waiting in getNextEvent(int) for an event of @@ -809,7 +809,7 @@ public class EventQueue { pushPopLock.lock(); try { return (Thread.currentThread() == dispatchThread) - ? ((AWTEvent)currentEvent.get()) + ? currentEvent.get() : null; } finally { pushPopLock.unlock(); @@ -1167,7 +1167,7 @@ public class EventQueue { return; } - currentEvent = new WeakReference(e); + currentEvent = new WeakReference<>(e); // This series of 'instanceof' checks should be replaced with a // polymorphic type (for example, an interface which declares a diff --git a/jdk/src/share/classes/java/awt/Menu.java b/jdk/src/share/classes/java/awt/Menu.java index e702a9cb8fd..ae5d2fa2f82 100644 --- a/jdk/src/share/classes/java/awt/Menu.java +++ b/jdk/src/share/classes/java/awt/Menu.java @@ -66,7 +66,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { AWTAccessor.setMenuAccessor( new AWTAccessor.MenuAccessor() { - public Vector getItems(Menu menu) { + public Vector getItems(Menu menu) { return menu.items; } }); @@ -78,7 +78,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * @serial * @see #countItems() */ - Vector items = new Vector(); + Vector items = new Vector<>(); /** * This field indicates whether the menu has the @@ -313,7 +313,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { } int nitems = getItemCount(); - Vector tempItems = new Vector(); + Vector tempItems = new Vector<>(); /* Remove the item at index, nitems-index times storing them in a temporary vector in the @@ -330,7 +330,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { already in the correct order in the temp vector. */ for (int i = 0; i < tempItems.size() ; i++) { - add((MenuItem)tempItems.elementAt(i)); + add(tempItems.elementAt(i)); } } } @@ -379,7 +379,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { } int nitems = getItemCount(); - Vector tempItems = new Vector(); + Vector tempItems = new Vector<>(); /* Remove the item at index, nitems-index times storing them in a temporary vector in the @@ -396,7 +396,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { already in the correct order in the temp vector. */ for (int i = 0; i < tempItems.size() ; i++) { - add((MenuItem)tempItems.elementAt(i)); + add(tempItems.elementAt(i)); } } } @@ -475,13 +475,13 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { return null; } - synchronized Enumeration shortcuts() { - Vector shortcuts = new Vector(); + synchronized Enumeration shortcuts() { + Vector shortcuts = new Vector<>(); int nitems = getItemCount(); for (int i = 0 ; i < nitems ; i++) { MenuItem mi = getItem(i); if (mi instanceof Menu) { - Enumeration e = ((Menu)mi).shortcuts(); + Enumeration e = ((Menu)mi).shortcuts(); while (e.hasMoreElements()) { shortcuts.addElement(e.nextElement()); } diff --git a/jdk/src/share/classes/java/awt/MenuBar.java b/jdk/src/share/classes/java/awt/MenuBar.java index 1fd442e1583..bd0a7d890c0 100644 --- a/jdk/src/share/classes/java/awt/MenuBar.java +++ b/jdk/src/share/classes/java/awt/MenuBar.java @@ -81,7 +81,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible return menuBar.helpMenu; } - public Vector getMenus(MenuBar menuBar) { + public Vector getMenus(MenuBar menuBar) { return menuBar.menus; } }); @@ -94,7 +94,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * @serial * @see #countMenus() */ - Vector menus = new Vector(); + Vector menus = new Vector<>(); /** * This menu is a special menu dedicated to @@ -309,7 +309,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * be called on the toolkit thread. */ final Menu getMenuImpl(int i) { - return (Menu)menus.elementAt(i); + return menus.elementAt(i); } /** @@ -321,10 +321,10 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * @since JDK1.1 */ public synchronized Enumeration shortcuts() { - Vector shortcuts = new Vector(); + Vector shortcuts = new Vector<>(); int nmenus = getMenuCount(); for (int i = 0 ; i < nmenus ; i++) { - Enumeration e = getMenu(i).shortcuts(); + Enumeration e = getMenu(i).shortcuts(); while (e.hasMoreElements()) { shortcuts.addElement(e.nextElement()); } @@ -438,7 +438,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible // HeadlessException will be thrown from MenuComponent's readObject s.defaultReadObject(); for (int i = 0; i < menus.size(); i++) { - Menu m = (Menu)menus.elementAt(i); + Menu m = menus.elementAt(i); m.parent = this; } } diff --git a/jdk/src/share/classes/java/awt/MenuComponent.java b/jdk/src/share/classes/java/awt/MenuComponent.java index ebd9c0576ba..4895fdc9548 100644 --- a/jdk/src/share/classes/java/awt/MenuComponent.java +++ b/jdk/src/share/classes/java/awt/MenuComponent.java @@ -290,7 +290,7 @@ public abstract class MenuComponent implements java.io.Serializable { public void setFont(Font f) { font = f; //Fixed 6312943: NullPointerException in method MenuComponent.setFont(Font) - MenuComponentPeer peer = (MenuComponentPeer)this.peer; + MenuComponentPeer peer = this.peer; if (peer != null) { peer.setFont(f); } @@ -303,7 +303,7 @@ public abstract class MenuComponent implements java.io.Serializable { */ public void removeNotify() { synchronized (getTreeLock()) { - MenuComponentPeer p = (MenuComponentPeer)this.peer; + MenuComponentPeer p = this.peer; if (p != null) { Toolkit.getEventQueue().removeSourceEvents(this, true); this.peer = null; diff --git a/jdk/src/share/classes/java/awt/MenuItem.java b/jdk/src/share/classes/java/awt/MenuItem.java index 3b8b2cffa0e..4838d187a89 100644 --- a/jdk/src/share/classes/java/awt/MenuItem.java +++ b/jdk/src/share/classes/java/awt/MenuItem.java @@ -564,7 +564,7 @@ public class MenuItem extends MenuComponent implements Accessible { * @since 1.4 */ public synchronized ActionListener[] getActionListeners() { - return (ActionListener[])(getListeners(ActionListener.class)); + return getListeners(ActionListener.class); } /** diff --git a/jdk/src/share/classes/java/awt/RenderingHints.java b/jdk/src/share/classes/java/awt/RenderingHints.java index 5b8daa9e519..48cf9e11d32 100644 --- a/jdk/src/share/classes/java/awt/RenderingHints.java +++ b/jdk/src/share/classes/java/awt/RenderingHints.java @@ -92,7 +92,7 @@ public class RenderingHints * {@code equals()} method. */ public abstract static class Key { - private static HashMap identitymap = new HashMap(17); + private static HashMap identitymap = new HashMap<>(17); private String getIdentity() { // Note that the identity string is dependent on 3 variables: @@ -138,7 +138,7 @@ public class RenderingHints } // Note: Use a weak reference to avoid holding on to extra // objects and classes after they should be unloaded. - identitymap.put(identity, new WeakReference(k)); + identitymap.put(identity, new WeakReference(k)); } private int privatekey; @@ -195,7 +195,7 @@ public class RenderingHints } } - HashMap hintmap = new HashMap(7); + HashMap hintmap = new HashMap<>(7); /** * Antialiasing hint key. @@ -1267,12 +1267,13 @@ public class RenderingHints * object. * @return a clone of this instance. */ + @SuppressWarnings("unchecked") public Object clone() { RenderingHints rh; try { rh = (RenderingHints) super.clone(); if (hintmap != null) { - rh.hintmap = (HashMap) hintmap.clone(); + rh.hintmap = (HashMap) hintmap.clone(); } } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable diff --git a/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java b/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java index d58bd92f3e0..cce9c74c192 100644 --- a/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java +++ b/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java @@ -71,7 +71,7 @@ public class Clipboard { * * @since 1.5 */ - private Set currentDataFlavors; + private Set currentDataFlavors; /** * Creates a clipboard object. @@ -313,7 +313,7 @@ public class Clipboard { if (flavorListeners == null) { return; } - Set prevDataFlavors = currentDataFlavors; + Set prevDataFlavors = currentDataFlavors; currentDataFlavors = getAvailableDataFlavorSet(); if (prevDataFlavors.equals(currentDataFlavors)) { return; @@ -339,8 +339,8 @@ public class Clipboard { * * @since 1.5 */ - private Set getAvailableDataFlavorSet() { - Set set = new HashSet(); + private Set getAvailableDataFlavorSet() { + Set set = new HashSet<>(); Transferable contents = getContents(null); if (contents != null) { DataFlavor[] flavors = contents.getTransferDataFlavors(); diff --git a/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java b/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java index 298436fc50f..3b72ed9afda 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java +++ b/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java @@ -165,7 +165,7 @@ public class DragGestureEvent extends EventObject { *

    * @return an Iterator for the events comprising the gesture */ - + @SuppressWarnings("unchecked") public Iterator iterator() { return events.iterator(); } /** @@ -184,7 +184,7 @@ public class DragGestureEvent extends EventObject { *

    * @return an array of the events comprising the gesture */ - + @SuppressWarnings("unchecked") public Object[] toArray(Object[] array) { return events.toArray(array); } /** @@ -333,7 +333,6 @@ public class DragGestureEvent extends EventObject { component = (Component)f.get("component", null); origin = (Point)f.get("origin", null); action = f.get("action", 0); - // Pre-1.4 support. 'events' was previously non-transient try { events = (List)f.get("events", null); @@ -351,7 +350,7 @@ public class DragGestureEvent extends EventObject { /* * fields */ - + @SuppressWarnings("rawtypes") private transient List events; /** diff --git a/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java b/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java index 4b433264701..1f1b9a3f488 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java +++ b/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java @@ -297,7 +297,7 @@ public abstract class DragGestureRecognizer implements Serializable { * @return the initial event that triggered the drag gesture */ - public InputEvent getTriggerEvent() { return events.isEmpty() ? null : (InputEvent)events.get(0); } + public InputEvent getTriggerEvent() { return events.isEmpty() ? null : events.get(0); } /** * Reset the Recognizer, if its currently recognizing a gesture, ignore diff --git a/jdk/src/share/classes/java/awt/dnd/DragSource.java b/jdk/src/share/classes/java/awt/dnd/DragSource.java index 2311ccc6283..bceedda646b 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragSource.java +++ b/jdk/src/share/classes/java/awt/dnd/DragSource.java @@ -600,7 +600,7 @@ public class DragSource implements Serializable { * @since 1.4 */ public DragSourceListener[] getDragSourceListeners() { - return (DragSourceListener[])getListeners(DragSourceListener.class); + return getListeners(DragSourceListener.class); } /** @@ -660,8 +660,7 @@ public class DragSource implements Serializable { * @since 1.4 */ public DragSourceMotionListener[] getDragSourceMotionListeners() { - return (DragSourceMotionListener[]) - getListeners(DragSourceMotionListener.class); + return getListeners(DragSourceMotionListener.class); } /** @@ -896,8 +895,8 @@ public class DragSource implements Serializable { * @since 1.5 */ public static int getDragThreshold() { - int ts = ((Integer)AccessController.doPrivileged( - new GetIntegerAction("awt.dnd.drag.threshold", 0))).intValue(); + int ts = AccessController.doPrivileged( + new GetIntegerAction("awt.dnd.drag.threshold", 0)).intValue(); if (ts > 0) { return ts; } else { diff --git a/jdk/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java b/jdk/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java index 4ea863c981b..ed94ceefcf7 100644 --- a/jdk/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java +++ b/jdk/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java @@ -36,6 +36,8 @@ package java.awt.dnd; public class InvalidDnDOperationException extends IllegalStateException { + private static final long serialVersionUID = 5156676500247816278L; + static private String dft_msg = "The operation requested cannot be performed by the DnD system since it is not in the appropriate state"; /** diff --git a/jdk/src/share/classes/java/awt/geom/AffineTransform.java b/jdk/src/share/classes/java/awt/geom/AffineTransform.java index 2fa1dc2137a..751deac2497 100644 --- a/jdk/src/share/classes/java/awt/geom/AffineTransform.java +++ b/jdk/src/share/classes/java/awt/geom/AffineTransform.java @@ -876,6 +876,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * they have not been cached. * @see #getType */ + @SuppressWarnings("fallthrough") private void calculateType() { int ret = TYPE_IDENTITY; boolean sgn0, sgn1; @@ -1038,6 +1039,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * @see #TYPE_UNIFORM_SCALE * @since 1.2 */ + @SuppressWarnings("fallthrough") public double getDeterminant() { switch (state) { default: @@ -1250,6 +1252,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): m02 = tx * m00 + ty * m01 + m02; m12 = tx * m10 + ty * m11 + m12; @@ -1631,6 +1634,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * Y axis direction * @since 1.2 */ + @SuppressWarnings("fallthrough") public void scale(double sx, double sy) { int state = this.state; switch (state) { @@ -1705,6 +1709,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SHEAR | APPLY_SCALE): double M0, M1; @@ -2224,6 +2229,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * @see #preConcatenate * @since 1.2 */ + @SuppressWarnings("fallthrough") public void concatenate(AffineTransform Tx) { double M0, M1; double T00, T01, T10, T11; @@ -2432,6 +2438,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * @see #concatenate * @since 1.2 */ + @SuppressWarnings("fallthrough") public void preConcatenate(AffineTransform Tx) { double M0, M1; double T00, T01, T10, T11; @@ -2655,6 +2662,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return null; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): det = m00 * m11 - m01 * m10; if (Math.abs(det) <= Double.MIN_VALUE) { @@ -2751,6 +2759,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -2885,6 +2894,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return null; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): ptDst.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); @@ -2968,6 +2978,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): dst.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); @@ -3043,6 +3054,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3157,6 +3169,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3252,6 +3265,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3347,6 +3361,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3436,6 +3451,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * inverted. * @since 1.2 */ + @SuppressWarnings("fallthrough") public Point2D inverseTransform(Point2D ptSrc, Point2D ptDst) throws NoninvertibleTransformException { @@ -3547,6 +3563,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3679,6 +3696,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return null; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SHEAR | APPLY_SCALE): ptDst.setLocation(x * m00 + y * m01, x * m10 + y * m11); @@ -3754,6 +3772,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SHEAR | APPLY_SCALE): M00 = m00; M01 = m01; From 010f64006925865ac06489881431bf1dd75f6005 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 6 Mar 2013 12:25:57 -0800 Subject: [PATCH 089/102] 8009472: Print additional information for 8004640 failure Dump nodes and types in 8004640 case. Reviewed-by: roland --- hotspot/src/share/vm/opto/compile.hpp | 1 + hotspot/src/share/vm/opto/memnode.cpp | 36 +++++++++++++++++++++------ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 5e7de5b7066..d951fbf5f94 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -678,6 +678,7 @@ class Compile : public Phase { void record_dead_node(uint idx) { if (_dead_node_list.test_set(idx)) return; _dead_node_count++; } + bool is_dead_node(uint idx) { return _dead_node_list.test(idx) != 0; } uint dead_node_count() { return _dead_node_count; } void reset_dead_node_list() { _dead_node_list.Reset(); _dead_node_count = 0; diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 8030d7c4d2e..a4dcdb7c9a8 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -238,7 +238,7 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) { return this; ctl = in(MemNode::Control); // Don't bother trying to transform a dead node - if( ctl && ctl->is_top() ) return NodeSentinel; + if (ctl && ctl->is_top()) return NodeSentinel; PhaseIterGVN *igvn = phase->is_IterGVN(); // Wait if control on the worklist. @@ -262,8 +262,8 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) { } // Ignore if memory is dead, or self-loop Node *mem = in(MemNode::Memory); - if( phase->type( mem ) == Type::TOP ) return NodeSentinel; // caller will return NULL - assert( mem != this, "dead loop in MemNode::Ideal" ); + if (phase->type( mem ) == Type::TOP) return NodeSentinel; // caller will return NULL + assert(mem != this, "dead loop in MemNode::Ideal"); if (can_reshape && igvn != NULL && igvn->_worklist.member(mem)) { // This memory slice may be dead. @@ -273,12 +273,12 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) { } Node *address = in(MemNode::Address); - const Type *t_adr = phase->type( address ); - if( t_adr == Type::TOP ) return NodeSentinel; // caller will return NULL + const Type *t_adr = phase->type(address); + if (t_adr == Type::TOP) return NodeSentinel; // caller will return NULL - if( can_reshape && igvn != NULL && + if (can_reshape && igvn != NULL && (igvn->_worklist.member(address) || - igvn->_worklist.size() > 0 && (phase->type(address) != adr_type())) ) { + igvn->_worklist.size() > 0 && (t_adr != adr_type())) ) { // The address's base and type may change when the address is processed. // Delay this mem node transformation until the address is processed. phase->is_IterGVN()->_worklist.push(this); @@ -288,7 +288,7 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) { // Do NOT remove or optimize the next lines: ensure a new alias index // is allocated for an oop pointer type before Escape Analysis. // Note: C++ will not remove it since the call has side effect. - if ( t_adr->isa_oopptr() ) { + if (t_adr->isa_oopptr()) { int alias_idx = phase->C->get_alias_index(t_adr->is_ptr()); } @@ -296,6 +296,26 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) { Node* base = NULL; if (address->is_AddP()) base = address->in(AddPNode::Base); + if (base != NULL && phase->type(base)->higher_equal(TypePtr::NULL_PTR) && + !t_adr->isa_rawptr()) { + // Note: raw address has TOP base and top->higher_equal(TypePtr::NULL_PTR) is true. + Compile* C = phase->C; + tty->cr(); + tty->print_cr("===== NULL+offs not RAW address ====="); + if (C->is_dead_node(this->_idx)) tty->print_cr("'this' is dead"); + if ((ctl != NULL) && C->is_dead_node(ctl->_idx)) tty->print_cr("'ctl' is dead"); + if (C->is_dead_node(mem->_idx)) tty->print_cr("'mem' is dead"); + if (C->is_dead_node(address->_idx)) tty->print_cr("'address' is dead"); + if (C->is_dead_node(base->_idx)) tty->print_cr("'base' is dead"); + tty->cr(); + base->dump(1); + tty->cr(); + this->dump(2); + tty->print("this->adr_type(): "); adr_type()->dump(); tty->cr(); + tty->print("phase->type(address): "); t_adr->dump(); tty->cr(); + tty->print("phase->type(base): "); phase->type(address)->dump(); tty->cr(); + tty->cr(); + } assert(base == NULL || t_adr->isa_rawptr() || !phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?"); #endif From 6c0e4804276fd48c5ffab5c1330be3b234360727 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Thu, 7 Mar 2013 14:05:21 +0400 Subject: [PATCH 090/102] 8005530: [lcms] Improve performance of ColorConverOp for default destinations Reviewed-by: prr, jgodinez --- jdk/make/sun/cmm/lcms/Makefile | 3 + jdk/make/sun/cmm/lcms/mapfile-vers | 9 +- jdk/makefiles/CompileNativeLibraries.gmk | 2 +- jdk/makefiles/mapfiles/liblcms/mapfile-vers | 9 +- .../classes/sun/java2d/cmm/lcms/LCMS.java | 137 +++++++- .../sun/java2d/cmm/lcms/LCMSImageLayout.java | 295 ++++++++++++------ .../sun/java2d/cmm/lcms/LCMSTransform.java | 25 +- jdk/src/share/demo/java2d/J2DBench/build.xml | 12 +- .../resources/cmm_images/img_icc_large.jpg | Bin 0 -> 430301 bytes .../resources/cmm_images/img_icc_medium.jpg | Bin 0 -> 148164 bytes .../resources/cmm_images/img_icc_small.jpg | Bin 0 -> 16258 bytes .../tests/cmm/ColorConversionTests.java | 1 + .../tests/cmm/EmbeddedProfileTests.java | 166 ++++++++++ .../share/native/sun/java2d/cmm/lcms/LCMS.c | 95 +++--- 14 files changed, 572 insertions(+), 182 deletions(-) create mode 100644 jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_large.jpg create mode 100644 jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_medium.jpg create mode 100644 jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_small.jpg create mode 100644 jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java diff --git a/jdk/make/sun/cmm/lcms/Makefile b/jdk/make/sun/cmm/lcms/Makefile index 24fde37fba0..85b02e4960e 100644 --- a/jdk/make/sun/cmm/lcms/Makefile +++ b/jdk/make/sun/cmm/lcms/Makefile @@ -28,6 +28,9 @@ PACKAGE = sun.java2d.cmm.lcms LIBRARY = lcms PRODUCT = sun +# Use highest level of optimization on this library +OPTIMIZATION_LEVEL = HIGHEST + include $(BUILDDIR)/common/Defs.gmk # diff --git a/jdk/make/sun/cmm/lcms/mapfile-vers b/jdk/make/sun/cmm/lcms/mapfile-vers index ac4e7458b37..3d9074f746d 100644 --- a/jdk/make/sun/cmm/lcms/mapfile-vers +++ b/jdk/make/sun/cmm/lcms/mapfile-vers @@ -27,13 +27,12 @@ SUNWprivate_1.1 { global: - Java_sun_java2d_cmm_lcms_LCMS_loadProfile; - Java_sun_java2d_cmm_lcms_LCMS_freeProfile; + Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; + Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; Java_sun_java2d_cmm_lcms_LCMS_getProfileData; - Java_sun_java2d_cmm_lcms_LCMS_getTagSize; - Java_sun_java2d_cmm_lcms_LCMS_getTagData; - Java_sun_java2d_cmm_lcms_LCMS_setTagData; + Java_sun_java2d_cmm_lcms_LCMS_getTagNative; + Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_colorConvert; Java_sun_java2d_cmm_lcms_LCMS_getProfileID; Java_sun_java2d_cmm_lcms_LCMS_initLCMS; diff --git a/jdk/makefiles/CompileNativeLibraries.gmk b/jdk/makefiles/CompileNativeLibraries.gmk index 01dbc2ba417..46f1778a5fc 100644 --- a/jdk/makefiles/CompileNativeLibraries.gmk +++ b/jdk/makefiles/CompileNativeLibraries.gmk @@ -1218,7 +1218,7 @@ ifdef OPENJDK OUTPUT_DIR:=$(INSTALL_LIBRARIES_HERE),\ SRC:=$(JDK_TOPDIR)/src/share/native/sun/java2d/cmm/lcms,\ LANG:=C,\ - OPTIMIZATION:=LOW, \ + OPTIMIZATION:=HIGHEST, \ CFLAGS:=$(filter-out -xc99=%none,$(CFLAGS_JDKLIB)) \ $(SHARED_LIBRARY_FLAGS) \ -I$(JDK_TOPDIR)/src/share/native/sun/java2d \ diff --git a/jdk/makefiles/mapfiles/liblcms/mapfile-vers b/jdk/makefiles/mapfiles/liblcms/mapfile-vers index 04703dffc5a..024511423d3 100644 --- a/jdk/makefiles/mapfiles/liblcms/mapfile-vers +++ b/jdk/makefiles/mapfiles/liblcms/mapfile-vers @@ -27,13 +27,12 @@ SUNWprivate_1.1 { global: - Java_sun_java2d_cmm_lcms_LCMS_loadProfile; - Java_sun_java2d_cmm_lcms_LCMS_freeProfile; + Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; + Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; Java_sun_java2d_cmm_lcms_LCMS_getProfileData; - Java_sun_java2d_cmm_lcms_LCMS_getTagSize; - Java_sun_java2d_cmm_lcms_LCMS_getTagData; - Java_sun_java2d_cmm_lcms_LCMS_setTagData; + Java_sun_java2d_cmm_lcms_LCMS_getTagNative; + Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_colorConvert; Java_sun_java2d_cmm_lcms_LCMS_getProfileID; Java_sun_java2d_cmm_lcms_LCMS_initLCMS; diff --git a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java index 5cfda3cdb74..c6eae65a73a 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java +++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java @@ -25,29 +25,91 @@ package sun.java2d.cmm.lcms; -import java.awt.color.ColorSpace; import java.awt.color.ICC_Profile; -import java.awt.color.CMMException; +import java.util.Arrays; +import java.util.HashMap; import sun.java2d.cmm.ColorTransform; import sun.java2d.cmm.PCMM; -import sun.java2d.cmm.lcms.LCMS; -import sun.java2d.cmm.lcms.LCMSTransform; public class LCMS implements PCMM { /* methods invoked from ICC_Profile */ - public native long loadProfile(byte[] data); + @Override + public long loadProfile(byte[] data) { + long id = loadProfileNative(data); - public native void freeProfile(long profileID); + if (id != 0L) { + if (profiles == null) { + profiles = new HashMap<>(); + } + profiles.put(id, new TagCache(id)); + } + return id; + } + + private native long loadProfileNative(byte[] data); + + @Override + public void freeProfile(long profileID) { + TagCache c = profiles.remove(profileID); + if (c != null) { + c.clear(); + } + if (profiles.isEmpty()) { + profiles = null; + } + freeProfileNative(profileID); + } + + private native void freeProfileNative(long profileID); public native synchronized int getProfileSize(long profileID); public native synchronized void getProfileData(long profileID, byte[] data); - public native synchronized int getTagSize(long profileID, int tagSignature); - public native synchronized void getTagData(long profileID, int tagSignature, - byte[] data); - public native synchronized void setTagData(long profileID, int tagSignature, + @Override + public synchronized int getTagSize(long profileID, int tagSignature) { + TagCache cache = profiles.get(profileID); + + if (cache == null) { + cache = new TagCache(profileID); + profiles.put(profileID, cache); + } + + TagData t = cache.getTag(tagSignature); + return t == null ? 0 : t.getSize(); + } + + private static native byte[] getTagNative(long profileID, int signature); + + @Override + public synchronized void getTagData(long profileID, int tagSignature, + byte[] data) + { + TagCache cache = profiles.get(profileID); + + if (cache == null) { + cache = new TagCache(profileID); + profiles.put(profileID, cache); + } + + TagData t = cache.getTag(tagSignature); + if (t != null) { + t.copyDataTo(data); + } + } + + @Override + public synchronized void setTagData(long profileID, int tagSignature, byte[] data) { + TagCache cache = profiles.get(profileID); + + if (cache != null) { + cache.clear(); + } + setTagDataNative(profileID, tagSignature, data); + } + + private native synchronized void setTagDataNative(long profileID, int tagSignature, byte[] data); public static native long getProfileID(ICC_Profile profile); @@ -103,4 +165,59 @@ public class LCMS implements PCMM { initLCMS(LCMSTransform.class, LCMSImageLayout.class, ICC_Profile.class); } + + private static class TagData { + private int signature; + private byte[] data; + + TagData(int sig, byte[] data) { + this.signature = sig; + this.data = data; + } + + int getSize() { + return data.length; + } + + byte[] getData() { + return Arrays.copyOf(data, data.length); + } + + void copyDataTo(byte[] dst) { + System.arraycopy(data, 0, dst, 0, data.length); + } + + int getSignature() { + return signature; + } + } + + private static class TagCache { + private long profileID; + private HashMap tags; + + TagCache(long id) { + profileID = id; + + tags = new HashMap<>(); + } + + TagData getTag(int sig) { + TagData t = tags.get(sig); + if (t == null) { + byte[] tagData = getTagNative(profileID, sig); + if (tagData != null) { + t = new TagData(sig, tagData); + tags.put(sig, t); + } + } + return t; + } + + void clear() { + tags.clear(); + } + } + + private static HashMap profiles; } diff --git a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java index 3695a163211..b53bd9a45d3 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java +++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java @@ -22,26 +22,19 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package sun.java2d.cmm.lcms; -import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.awt.image.ComponentColorModel; -import java.awt.image.Raster; -import java.awt.image.WritableRaster; -import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.DataBufferUShort; -import java.awt.image.DataBufferInt; import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.awt.image.SampleModel; import sun.awt.image.ByteComponentRaster; import sun.awt.image.ShortComponentRaster; import sun.awt.image.IntegerComponentRaster; - class LCMSImageLayout { public static int BYTES_SH(int x) { @@ -49,47 +42,34 @@ class LCMSImageLayout { } public static int EXTRA_SH(int x) { - return x<<7; + return x << 7; } public static int CHANNELS_SH(int x) { - return x<<3; + return x << 3; } - - public static final int SWAPFIRST = 1<<14; - - public static final int DOSWAP = 1<<10; - + public static final int SWAPFIRST = 1 << 14; + public static final int DOSWAP = 1 << 10; public static final int PT_RGB_8 = - CHANNELS_SH(3) | BYTES_SH(1); - + CHANNELS_SH(3) | BYTES_SH(1); public static final int PT_GRAY_8 = - CHANNELS_SH(1) | BYTES_SH(1); - + CHANNELS_SH(1) | BYTES_SH(1); public static final int PT_GRAY_16 = - CHANNELS_SH(1) | BYTES_SH(2); - + CHANNELS_SH(1) | BYTES_SH(2); public static final int PT_RGBA_8 = - EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); - + EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); public static final int PT_ARGB_8 = - EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1) | SWAPFIRST; - + EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1) | SWAPFIRST; public static final int PT_BGR_8 = - DOSWAP | CHANNELS_SH(3) | BYTES_SH(1); - + DOSWAP | CHANNELS_SH(3) | BYTES_SH(1); public static final int PT_ABGR_8 = - DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); - - public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3) | - BYTES_SH(1) | DOSWAP | SWAPFIRST; - - public static final int DT_BYTE = 0; - public static final int DT_SHORT = 1; - public static final int DT_INT = 2; - public static final int DT_DOUBLE = 3; - - + DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); + public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3) + | BYTES_SH(1) | DOSWAP | SWAPFIRST; + public static final int DT_BYTE = 0; + public static final int DT_SHORT = 1; + public static final int DT_INT = 2; + public static final int DT_DOUBLE = 3; boolean isIntPacked = false; int pixelType; int dataType; @@ -98,25 +78,30 @@ class LCMSImageLayout { int nextRowOffset; int offset; + /* This flag indicates whether the image can be processed + * at once by doTransfrom() native call. Otherwise, the + * image is processed scan by scan. + */ + private boolean imageAtOnce = false; Object dataArray; + private LCMSImageLayout(int np, int pixelType, int pixelSize) { this.pixelType = pixelType; width = np; height = 1; - nextRowOffset = np*pixelSize; + nextRowOffset = np * pixelSize; offset = 0; } private LCMSImageLayout(int width, int height, int pixelType, - int pixelSize) { + int pixelSize) { this.pixelType = pixelType; this.width = width; this.height = height; - nextRowOffset = width*pixelSize; + nextRowOffset = width * pixelSize; offset = 0; } - public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) { this(np, pixelType, pixelSize); dataType = DT_BYTE; @@ -135,102 +120,218 @@ class LCMSImageLayout { dataArray = data; } - public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) - { + public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) { this(np, pixelType, pixelSize); dataType = DT_DOUBLE; dataArray = data; } - public LCMSImageLayout(BufferedImage image) { - ShortComponentRaster shortRaster; - IntegerComponentRaster intRaster; - ByteComponentRaster byteRaster; + private LCMSImageLayout() { + } + + /* This method creates a layout object for given image. + * Returns null if the image is not supported by current implementation. + */ + public static LCMSImageLayout createImageLayout(BufferedImage image) { + LCMSImageLayout l = new LCMSImageLayout(); + switch (image.getType()) { case BufferedImage.TYPE_INT_RGB: - pixelType = PT_ARGB_8; - isIntPacked = true; + l.pixelType = PT_ARGB_8; + l.isIntPacked = true; break; case BufferedImage.TYPE_INT_ARGB: - pixelType = PT_ARGB_8; - isIntPacked = true; + l.pixelType = PT_ARGB_8; + l.isIntPacked = true; break; case BufferedImage.TYPE_INT_BGR: - pixelType = PT_ABGR_8; - isIntPacked = true; + l.pixelType = PT_ABGR_8; + l.isIntPacked = true; break; case BufferedImage.TYPE_3BYTE_BGR: - pixelType = PT_BGR_8; + l.pixelType = PT_BGR_8; break; case BufferedImage.TYPE_4BYTE_ABGR: - pixelType = PT_ABGR_8; + l.pixelType = PT_ABGR_8; break; case BufferedImage.TYPE_BYTE_GRAY: - pixelType = PT_GRAY_8; + l.pixelType = PT_GRAY_8; break; case BufferedImage.TYPE_USHORT_GRAY: - pixelType = PT_GRAY_16; + l.pixelType = PT_GRAY_16; break; default: - // TODO: Add support for some images having - // SinglePixelPackedModel and ComponentSampleModel - throw new IllegalArgumentException( - "CMMImageLayout - bad image type passed to constructor"); + /* ColorConvertOp creates component images as + * default destination, so this kind of images + * has to be supported. + */ + ColorModel cm = image.getColorModel(); + if (cm instanceof ComponentColorModel) { + ComponentColorModel ccm = (ComponentColorModel) cm; + + // verify whether the component size is fine + int[] cs = ccm.getComponentSize(); + for (int s : cs) { + if (s != 8) { + return null; + } + } + + return createImageLayout(image.getRaster()); + + } + return null; } - width = image.getWidth(); - height = image.getHeight(); + l.width = image.getWidth(); + l.height = image.getHeight(); switch (image.getType()) { case BufferedImage.TYPE_INT_RGB: case BufferedImage.TYPE_INT_ARGB: case BufferedImage.TYPE_INT_BGR: - intRaster = (IntegerComponentRaster)image.getRaster(); - nextRowOffset = intRaster.getScanlineStride()*4; - offset = intRaster.getDataOffset(0)*4; - dataArray = intRaster.getDataStorage(); - dataType = DT_INT; + do { + IntegerComponentRaster intRaster = (IntegerComponentRaster) + image.getRaster(); + l.nextRowOffset = intRaster.getScanlineStride() * 4; + l.offset = intRaster.getDataOffset(0) * 4; + l.dataArray = intRaster.getDataStorage(); + l.dataType = DT_INT; + + if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) { + l.imageAtOnce = true; + } + } while (false); break; case BufferedImage.TYPE_3BYTE_BGR: case BufferedImage.TYPE_4BYTE_ABGR: - byteRaster = (ByteComponentRaster)image.getRaster(); - nextRowOffset = byteRaster.getScanlineStride(); - int firstBand = image.getSampleModel().getNumBands() - 1; - offset = byteRaster.getDataOffset(firstBand); - dataArray = byteRaster.getDataStorage(); - dataType = DT_BYTE; + do { + ByteComponentRaster byteRaster = (ByteComponentRaster) + image.getRaster(); + l.nextRowOffset = byteRaster.getScanlineStride(); + int firstBand = image.getSampleModel().getNumBands() - 1; + l.offset = byteRaster.getDataOffset(firstBand); + l.dataArray = byteRaster.getDataStorage(); + l.dataType = DT_BYTE; + if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) { + l.imageAtOnce = true; + } + } while (false); break; case BufferedImage.TYPE_BYTE_GRAY: - byteRaster = (ByteComponentRaster)image.getRaster(); - nextRowOffset = byteRaster.getScanlineStride(); - offset = byteRaster.getDataOffset(0); - dataArray = byteRaster.getDataStorage(); - dataType = DT_BYTE; + do { + ByteComponentRaster byteRaster = (ByteComponentRaster) + image.getRaster(); + l.nextRowOffset = byteRaster.getScanlineStride(); + l.offset = byteRaster.getDataOffset(0); + l.dataArray = byteRaster.getDataStorage(); + l.dataType = DT_BYTE; + + if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) { + l.imageAtOnce = true; + } + } while (false); break; case BufferedImage.TYPE_USHORT_GRAY: - shortRaster = (ShortComponentRaster)image.getRaster(); - nextRowOffset = shortRaster.getScanlineStride()*2; - offset = shortRaster.getDataOffset(0) * 2; - dataArray = shortRaster.getDataStorage(); - dataType = DT_SHORT; + do { + ShortComponentRaster shortRaster = (ShortComponentRaster) + image.getRaster(); + l.nextRowOffset = shortRaster.getScanlineStride() * 2; + l.offset = shortRaster.getDataOffset(0) * 2; + l.dataArray = shortRaster.getDataStorage(); + l.dataType = DT_SHORT; + + if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) { + l.imageAtOnce = true; + } + } while (false); break; + default: + return null; + } + return l; + } + + private static enum BandOrder { + DIRECT, + INVERTED, + ARBITRARY, + UNKNOWN; + + public static BandOrder getBandOrder(int[] bandOffsets) { + BandOrder order = UNKNOWN; + + int numBands = bandOffsets.length; + + for (int i = 0; (order != ARBITRARY) && (i < bandOffsets.length); i++) { + switch (order) { + case UNKNOWN: + if (bandOffsets[i] == i) { + order = DIRECT; + } else if (bandOffsets[i] == (numBands - 1 - i)) { + order = INVERTED; + } else { + order = ARBITRARY; + } + break; + case DIRECT: + if (bandOffsets[i] != i) { + order = ARBITRARY; + } + break; + case INVERTED: + if (bandOffsets[i] != (numBands - 1 - i)) { + order = ARBITRARY; + } + break; + } + } + return order; } } - public static boolean isSupported(BufferedImage image) { - switch (image.getType()) { - case BufferedImage.TYPE_INT_RGB: - case BufferedImage.TYPE_INT_ARGB: - case BufferedImage.TYPE_INT_BGR: - case BufferedImage.TYPE_3BYTE_BGR: - case BufferedImage.TYPE_4BYTE_ABGR: - case BufferedImage.TYPE_BYTE_GRAY: - case BufferedImage.TYPE_USHORT_GRAY: - return true; + public static LCMSImageLayout createImageLayout(Raster r) { + LCMSImageLayout l = new LCMSImageLayout(); + if (r instanceof ByteComponentRaster) { + ByteComponentRaster br = (ByteComponentRaster)r; + + ComponentSampleModel csm = (ComponentSampleModel)r.getSampleModel(); + + l.pixelType = CHANNELS_SH(br.getNumBands()) | BYTES_SH(1); + + int[] bandOffsets = csm.getBandOffsets(); + BandOrder order = BandOrder.getBandOrder(bandOffsets); + + int firstBand = 0; + switch (order) { + case INVERTED: + l.pixelType |= DOSWAP; + firstBand = csm.getNumBands() - 1; + break; + case DIRECT: + // do nothing + break; + default: + // unable to create the image layout; + return null; + } + + l.nextRowOffset = br.getScanlineStride(); + l.offset = br.getDataOffset(firstBand); + l.dataArray = br.getDataStorage(); + l.dataType = DT_BYTE; + + l.width = br.getWidth(); + l.height = br.getHeight(); + + if (l.nextRowOffset == l.width * br.getPixelStride()) { + l.imageAtOnce = true; + } + return l; } - return false; + return null; } } diff --git a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java index aa9d0bf054f..de8a77c75f3 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java +++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java @@ -161,13 +161,18 @@ public class LCMSTransform implements ColorTransform { } public void colorConvert(BufferedImage src, BufferedImage dst) { - if (LCMSImageLayout.isSupported(src) && - LCMSImageLayout.isSupported(dst)) - { - doTransform(new LCMSImageLayout(src), new LCMSImageLayout(dst)); - return; - } LCMSImageLayout srcIL, dstIL; + + dstIL = LCMSImageLayout.createImageLayout(dst); + + if (dstIL != null) { + srcIL = LCMSImageLayout.createImageLayout(src); + if (srcIL != null) { + doTransform(srcIL, dstIL); + return; + } + } + Raster srcRas = src.getRaster(); WritableRaster dstRas = dst.getRaster(); ColorModel srcCM = src.getColorModel(); @@ -439,6 +444,14 @@ public class LCMSTransform implements ColorTransform { public void colorConvert(Raster src, WritableRaster dst) { LCMSImageLayout srcIL, dstIL; + dstIL = LCMSImageLayout.createImageLayout(dst); + if (dstIL != null) { + srcIL = LCMSImageLayout.createImageLayout(src); + if (srcIL != null) { + doTransform(srcIL, dstIL); + return; + } + } // Can't pass src and dst directly to CMM, so process per scanline SampleModel srcSM = src.getSampleModel(); SampleModel dstSM = dst.getSampleModel(); diff --git a/jdk/src/share/demo/java2d/J2DBench/build.xml b/jdk/src/share/demo/java2d/J2DBench/build.xml index a36aca8cec7..c29611d0f7a 100644 --- a/jdk/src/share/demo/java2d/J2DBench/build.xml +++ b/jdk/src/share/demo/java2d/J2DBench/build.xml @@ -52,7 +52,7 @@ - - + + + + - - diff --git a/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_large.jpg b/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_large.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6d61c9f120fd60e556ee88419c641f5253249774 GIT binary patch literal 430301 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

  • 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 literal 0 HcmV?d00001 diff --git a/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_medium.jpg b/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_medium.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6b4ef3f38d14d03a7f990e4d50e25af75e1d3a8b GIT binary patch literal 148164 zcmb@v4RloZmE|i5O9t6xFcieD@dv_^S_PH|n}RTeP9#LxQV9{MMAM-0n&!hORT$EA zFm96ROoRa0lu0avESm!Iq;g3hhvb1N_q5;YS&gxAY^T*Nm1M_e`t>rNHXYOM_3R`) zZ|s#x-fy4(t&;3y=6$T^tVpF>_ui@!cb~KOKKp<5o40@SZo#a`{SEgQ6c!d1)bqcB z-~77Z&TTulY@dkkp%^XKijc&=kB7#1qD05{>V3?53HKMVPo6;>)$SzR&ZOvO$E0URBYb5dsl69 z^O}O+{*U7e`2T->OJ55L#;bL%-`?$ix@E>g+jehdkB|6&`_^6Gc!X1K;IZ#dAK9hH zF&_KB!JFdopXu?}+~aON-r^poZJ%|~I`;Vs9?$xkd;FRnZ*h;`)?@Frcvx`bj`-KN zZT`mm-F#;K{Qv8Jk8In^doL*X`X7INo4)IJs_z8_zgS_vtHOE5C%66a(**^~|Br%# zX-`gW+wyEd!GHX2LBTD5H@U6+L_xvK{RIVo{+C<#eB)7fKKn;3_`m!4H~+byuAq3@ zb=O@tt(Y&x#lmfy2F37|BnCH|NZ7d!OhdB7fdghR=A*` z=;p#{Hy8fqm4Z9@hb!hn*0r4bTt(Ba<6TalQF;SAyfCYvsBqe}BHlkAfW5z6STwER zx|@q*=g~ji`^|6dKX9$C9aM(}P2&P7go#{Q1lafBql;;>G{%;>)jGdiBSzz5YgaeB#Zwe){%1 zm#@6{U;g3!tN-}353YUu^I!b(U;gX=`QJYIRG+Jm&zbwreK6kl)X#M@pR0&}mg}z9 z=PE4vQ~p2g=Ie^f?k$;J+j9NpKbf=OzJ1gEtBwquduhg9OQIjm-SUmG(s|{fD-|E> zquD3>fA+yT|37`Q{0E!-T$c-OoL0y`-n5$wzEW^)cz2Wkg-@S)^8LPpr=~TPBvxm> z-1m%cMfYQ+Z9A(MY`9ij;Xkl4(6Yw=ZhZQ#!J+I#&*;1Hc&0yF`SQW)P&BdXHsA8V zwyMyfv!Av!mGq_ShV^8{_x#s34VE0aYdBsw=s&PLn%K5H(9?E%c>dtl(L`RD&s^{K# zT`IA#?UpDTL(|!*udBk}(mYzs^A{q)xUa6RG}7j)EA*bqJmo9kEH`ehkH;5o-~<(Q z1)SiP(cWk>($(S98Mm}FHZ)%d2IC8FxtORry-6p0wZfly>c*m;zC_o(?yW@hba!@a zTp6Jeh1>^l-KULGxNr`t+fY6jEMQhv2m-{m#Fh+20zjE(@)AIy4%O&)NK5 zA{OGh-%~ZzdcOYn4at@!F6NbiHZJB>XRkCi4VI*j-&E3fJmOn4n`?Y$b=gh+D{FM! ze-KZBg@e`0dZU#u?>p5RtW7uG5sasL1AUdt18qA2%+}NC!Qoh~uKl6_7jI*YF1u=7 zvDG(nnFtIId~4w?y1GYa)N-|VM5;pT?&bFrz2N)3Z?#3by8JES#zH>ka4dhdbrrfZ zR;30GgNcQKTUx>;gB`ssVR!MrA_RbHV3kAEEf;(GdImalS#1e$Tt`SWN$;2*+E$+f6c;L2ao1vZnTG(AyW)L(z~exWr~1cg&%7<* z-+QnO90&s0^*g{^&-tyTRq4~b8vF9zL5IEf^dMNckTsxaYrw93_s-d&{Z)4@QpQ^2 z6Hly4==$WU*OlF_tM#qEBPlMa(tr2MCsvK~(RF2}{V!BL-VzDw;+xmU%#{@@UeO&*7=Bvn$8?3d z>ps!fR@zov)jw8T#ifxc>I0sAoqdVmyn};$R-L`Jv7wJ2xUyrwB6TEQFxW2;2weI^ zLeRl}aHXS*7j$Pby{V(sH|SMu*F+dp_og~~=5e_Bpk`b)~Q9ZLJ;jpILO%V9D{uXwzf+8`qTd23Fls zHI&_7fBYtY=JJEtSs%sYySG< z0gk|tn@Ucu@zXE{Cb*Pm>Dn*oN>mNUROvTx={LVx($lv;stb%BV1=Gy8nW(iqbtsh z4bfNm4X(3|cT>>AbwEjdfeV}#!j)e)o8Mkn7pF?}6*b2U8nM%x%F=_WfqtvztJDWL z&5(7Tk^zcw)~-$9pflXkYd_ON+Ap}5Rbx>R7LL5e0=5<{D`cacspq^d;&t~P3YR2Q z+&SN&u%E^d_8STo-eUXfqa42_0AO4Pc=bR!l<5)*Qs+16a~QbnRrJ!`Z|&F=4>q~C zG4kC!gbYpVcWmKbn1B3O+aAhcj8e?SNO6n@-@JRQfD8WGnz0*d`kRA+vWZM5SAal} z0vW9bmz`Ll3)*V}RoZL?eS6caR9|=N!CWb?U8^h9u+$Q5o9BQ+lll8TuEksn(ZRvk z;M__;QBhqy5UwujUB~6VFA@x>Ua#SWUDYnyM_T}2>7NL*5#YczoOzKzz6ec5B=$HP7n2u$HU(l_`RS1%VW`T>ju4n*kHQ;T3alXIq>7s z=6L3X^0#+|GF<1=cZE`_{-uy1uIANjz6KdOu#zLImX>FhN5|t-{@a3K8o{h9YyEG4 zjnPlrz8(+PJBHN;e`*b0$d-HL3OIG1@GWSYClF8$RrMon3)@uXPsfV1bqn1B7Q|)a zGk%mQh^6+^A}FSz#az*Yc17#pp25RGU-ewyjgEj+r3O{n>zYR?Ydr&pt3oaC4N)Hf zYxET;nLy+SQOu(`hMbN_TX4}b>iNQ3W`w!gYutq`hNJ4-egQ63c6uvSUpsJ(i`F=J zxK;otDAC^4Okvl@IrH|#p5E*_M~p&csr}v_yd^I0SN$y_Jfc0i_H}jxL`feA(CKq6 zBcXR@-GNWB@!WvW>3(+aB(ZBKv1@o6m*6BKj#}{t3yyjG#L*M`X+?U>7(y!75ZWSb zYckbU{Br0HRbIz{PK;XlWt*;AI26BA3hI>x{a~-O*=pAfN~=VSJR0QB7#Y&O^=-xe%oCJyQJ+TM z1uv>rk^8DM+)%@@+vX1z?Q5)!RdH53Pd3Qe1i3Z<6D$jhV3ij{$0AjLhf}1VyaSE{ zB)<0ZkFKmOITi_)zWhNr6lkFb43;E){xkJlwH@R8(u;2L0|%boH#pR~Z@BzXQwnn* zYlk8Q=WM<(e(*l}$8Euh%PrBy+k9Rh89_(vudh1~I$G+Fyw?i_t9OUY9{ngDz7IG& zPzv>$Tb_Y?ZGxQkRa-YGQ}zB=VXw$H*7#{5RC=h%C|q7WgsU7dv^GSw0r*(`7jSOW zWxs)cvP2iGiqmj$Iov?*MO`L4gD&boA!JCLgs$?6&MI=`#DW1Ra7#4snM>bZdVuS8 zE|)qNs9I|5sQp63H+6665*;HoLPHWDWA03K0=GT1iodXNk|-e|AVW?Va0zfxFR{x| zUF3>-O3G?|SU@^edUQ1cp`{^N78i9NnWak<3e*PJ_B6yG9hvXuwpmNLZD$s}fhnzq(|aC7Zox}Q$5H;RPG6tQ`^* zE>#VU)gPZ((o1KU=vmRH!}pykHJSY}T&jQKakY#6^+(>#ju)e>ABZMsQH^z%suu@# zEv=qCngI$m{w}qTo&KR7gto5l(&=1^T^0U-iRdvHQklsLPbL`m5>FD4T*Gnlm|s?3 z2iKCX4w^2F>cmBp8bOX5aV_hrbuA$P*mSX*h_C*WlWw1wvJ#OqWR%v;!H?qNnixH$HCfP?c5(OG0wE{+#v*$N%Ge_fM%pCMDN*n z@4aR1AdGGrl`3lj?zqxi+De!L>_I;0#XrrfPzK^NE^Zj7wX}9~@=` zHeRcU1Cb|oguc4#+*CulBRUpdfb^FX7vYLZkT@A%r3PY%$dm^C-5J+*_~#7XagVPm zbQx_u|2y}5Z_xjD+3eZm?FN$aJyjuoocq|c#wJ9?@zR%v;Yh}yGGh^6*-c#hAY#Yz z0OGtkzTx=H!J++)(Xxwu$CGM2db$>Y0eTSX7smGumF`*!EgKx-H_mn*2$rOeTs+}h9N4pwQc#lr*uZScB@YW(29 zA^HzI%!v#PB*Tt`t`8B9{FdVs$VpfU4{Imzf+s*u#SmvzdT(?ZjDaUWmp@|SgF0>qB$i0ae_ zBw!Y&r9bpRcr8!x?03Y9j^e8>JM#?8sY5_>k{D#EUB8{L}xEFN>W!fKGoeiZ0?iS3lfke$Drsi5#%%Aa%~9TG+&MMtgQC;b@e{~sFRHBDV zoU)!RL}2u1xacDb=_tYAMcgJ4BV>`F=}+x5ZWZOS_pB#LlKwQG4-X5uG@rvedz*uC ze>c9F*-=s^`amLRfHhhJ1#4~tiC9s01RI-1s=t%^y`TTH)VDu+?ye8Q6mxN^7l&F8 zmO-_Sxh~S)8(3fYG7eMkx}%#fWUnGX@SQSajrDzxO@p5`CV6`J;xqh9%@nsX%XT+r zRX2hLL4PQ=H}oQXrgcjjmQ;T>vED>{f3|$DshRpS%ccL*b#*VDD%}*K+3bbp1tna9 z{o~KIsdpM0q)NDsJM?px6hTOrl6xvp5b8p==Tu1uY^i8FP~bmRmka20r1d}e>I=8Ma5rFWU@ z1Y=VFqMPh^8xe&!Th*VE|3s^qFg{hvwJwpZBhj%{)_7#)`lF+w zXx1ydi=5ZsQf`Pj56a=RQfj348t!XqUxb#%^^G7G0g@s&NEj(o{}6Mc&&Z{v({i~N zo%DDb$eCSA zyY7;Il+Mtk#=<4fwM^|F+>FnJ6%{(uSoe$Y{80OmWw!+{9*g+uAIswLW)8)6A^U3w z2RCo{c2(#?90MzW+9eSYpXLWqlrzScejT(PxRv3yoN(>u`Va+ z4Y^8>Y4m|y>1MW~9)nm%qm1IdKEZ)7vFyCwW>5uc_{!C9<`$=<9fc+FxljZI*Fo4| zPDO*hcCrh?Nze8-8|+Xk{(hYeL3Bw%jX!hf&WJcv(}B@z&GC+`=7!j0APKK4 z6ipln2?;g{sfD+3RLO~8Z~sI$&RFeW$x+vFCVChx;xyaIut2IMdC)VfzsGAZTvfzyed|pV@yT3jwAXspeBKCF^&&-kR)|r!P`$l#`A(z={=P{Ym6G7kwqkt z(pY=i%w_>aW`Mdtmz2{;ry0ZU1+B1$bUL*>I2JH9Xqm@5Y3KUd@dw1ALKx;$r%9qrW~aSSr2=P=OkNY0F5J6xpTGniZeA~c83Mq4b9hVv^*|9CNayxtX42SB5#Yc3JCW;%L zyPeL$$gUb6$fz6^lCibOt{ibPXX;ex{f~Q11;rb@=+QhnlTg_RcG{3UkSm69{wGZR zr0H6wdcswh&r85s%4}V1g4u$>+zMk+{$r_CW4h{5BzkG{)@ASeh3WB6+=wGE}TrtKUJ?TXv5rnJ6TV@{fj<7ONYt*tTh z*mO;~|1aom{v%gHGyx_gU--(?cds}+9-lZgPttt-Z9bX5>*vbRy$3b&&Z%}Y1R4kAU^$DsIV)gK!(BR_*^5I`<0`{O-ZDeJ z2k^;akzl>Ug2605G*MFla6Zp2gVMDC7PS^%fqVc*?yRdo|BRHmHiTO%Of6d0MXz&Q z4KvEPBEVrYg;s8uCrQ{K>X*|cG$!E-Hpk@*$`C5g%wS)$nyt?`7g`SyL5DC@meO2M z`N9Zazgx`q#j|WysAlHFD(e;C1jM8HnIim6O6Pf}bPl-I)|JQuD2heKFpyb_3I26e zr%Gd(kB)zBOx+fIK+@w)E~nz?H4lLnnubiF@0btlX_qTe+R#4v5RxLABqB)YFJ_8~<7JM; zZ)lW@$9yr3wRgxF6>avu!f6aBJ<{Sj)dzuK%Gf$caG1Ql6Lr^gy?d-ubpkaN~_Tc#L#y|Smn@_%f?n0J_NzF_$ zms=c)4x=?po8W#8j&Q}VIx91+B(c66UIuPvP|hSpR;by$upnk^4f1E*sBP7qk)V9& zCP}D~>V{=^HYTBAHo?EzccfaatK{jW8dCJW#|h#r__?CXkcjOQJ;BxdR$PFpM8Go ztTAJ9Ai{rrObnK14|LLfJIe&|N2{z*P)K14==ly0S|(QzS#Yitn2k_u5+A@ zVsO+(K(8LqNMFtXW^)||-s^`W@(SLbp{CIO1`Lil41GlYl#w*&449kTw_TU4n?su5 zXJEfJysH@uS9&yAbe^L zG?!{L6E<43?32NfCE#N=nXcUy@xqlGjrkAdy9(BIBsd*k;2C0Gt1|>+G`guXFI#>B z=0kAyC{v+leD`c`0ENOVV(Q&EWbf_1#}cTh7t@*#G1Y83wDnR|=#5?J*JHaR+UR0? zPqp&fw`hU?U4Gspcdb*7*656eh^Kr4T%r9FPQF;{Q2R+bpV~%|cx^f3!Fq{jc%OF@ zAoCe)GHSE_Gnb`x0#H5Kb54|4D{}1&)q&KXW(QhZUR7nn&UUhl+fD0$u- z2fdze?ujn{_}cW+qlH{PRcGF*NAh$^v{bJ+z82PmHN|B=((FtD3;=9}=QciPn`I)>}?=oVDB2pXE#_{2dWdtON)-jmZ*i+%HsJROADyq>i&V|5m z;5otPAks^i;?$D;o*RMHj9gFA8FRTXd&_9}{i{3s&zAuKNvp#*$IRty|Vc0pW z7PM(Fy=W#oCwBq3cLx1$>q)fjW)f+c;=Fy$xaLTF~*i0{4=APROU()df^F6vkyF8TTeFEbk2A6dBi$7FE?n6n?#;Z9A% z`NOBcuz~k!2hITGls0RuJB=lGK!T=gauj6k36e%7_a^>?WrAs9WRn{_#YBr!e5UHm zWpgF^8Jn1O?QC)SQ<1kJx_)PYi`H;~$F?-X-2_}cmh?F*_w2ZxNwzZ-4&LUq9l+Hp zcbeCN)Y;H9NKVo-62$WE9iRcpg$Tj;9*^~pZFE^0vCPWF>74Ctc7u^c^)?Q(T^Fxv zj(I>k8c+|UV_73BLRTb4dUI17f9o*#2@J$9<|aE_m&cy7%?mfC=ACRh6>UE)^ei{K zfQ$0zQaKZYdG^P@FR*kr#Wf9pgtVoAD%Y{Z=Ax*7m!`SWkeu&1aVf4~umv`bSS~Y# zTVR>S7&$LT0(l_`BrG+|Hn|n_#QB3M0yGDOh5HY2QDb<^vnihG*1d=~PL`q37#TA^KqS^xv$r0;ZBXYCV z&*Y&q2ZeB%A`+YHeru90tAr&2qk1)26P{FJch7I2y&-}YE%W+}wJLO* zH|tUOjke-#73S1;@+O3^Bvek1(Sr`x)eeSeX4?B1Ie$0{#^^?STZB`8V9~Pa3LdDD zaaQvn)@*S?Ec(6P-qiUZfe^>w{>hOptUBk|2}IT}R%9t#+dap7fJPOyDG;NfgOwfu zWY*(Ul%8hqoWFf~kIX>N6hsgiUCc^|q2RX*HbAi)Mu@vCX(VPT83gRx4;8T4qB@-8 zg~~%WM2e+{XhT>C8l|4vGMFrf#BnIFlDptkTRH8o4XB-pwss8Dmom^+XEs3ny#AC3 z*2u(D@LH}m`Jqltg1{u*j?fw0&OAD)v+jNRc;IhdWWss%ud+)%d1#j#>TC{~5f{~fbyW7lFNo?eKwVF4Gw~p?{g(zul)@3k zW4i$)xLYIB_Gf~-qm@v$ugjl+5i%U*G&zGJ(Y6Ug{7IlfvcEg&Mo0J!fn7tT&D(d- zx-b!=6$9^P6Wf*t)*O*j5#6s7Hph>ln^API#1%szkX}Vkb(jX+jTKK?dz|R`aiV3- zsc8*bV{l=-@YJ*@GbkOkeBHT_vOl3K4XI+;;Dx@56(}Z!)hrg;JnBOI9)zH2;8HVL z4~8~wbrQ<5|5bDh@PqV{(o$Ojf3g)v48CR>Zp>I{0N!acVcHx|*2kOX97NEsJ4by&WQTP?%Mp_*gog76R9w9vW^oDcCtJ7ZsWshXyj{0WrvmR*+uE9zp<)}HJa3|bxdYo3yWd~B;#b`)0YoILNb4#%cvENiNZb_XLg{8iJ#NS(SP zMvXKwulgiJsaitHl5eBFMJT2W-DiW^ zQqp(p@LY(VI3z9xA)s_6!b#(#2TYE26Nx}Kwa~<}``3(AHyr@MTG8ybByll|H3;^=A__ zzL!p|d*t2i8<*V?4BvN>7vH~j?kzy>HBu9rs5N4H@aFLcUEFRu?_{Y%m8E{bjGRH& z%AA>Q2a7mn%8>`8}IE`uY0B#k@pZO zbMxNoxQs$c3Rz{;EfTv?yt=vFnw}kFL8w?Tst)k+5=u-SWV{i zE-rJH7PN7d+fN`eYD^I;mYpWXWRGWvPiR;3<@?oL&{H^s^GWewawrojU02JTwmEan zK@560nC$mo!&E<}5S>NuFvKU$(|im)rsD)Of9J_)tXr&1jfsBx+{Tnr4e62Dg;)%L z#fHV271ge#F$#9s_Cp?A=w$Flx$B@#gcTK~Y#>MJRUIYFlR*z+mx=&MbrC(&K~zAj zF@s|ijPVZM<4wDlkXp&Nd{t?yh4`Z zWUu051RflZt7#326CPL00e5`XwdVMXNHR@?eR37#0^SqfP8&d z4hGb_)aL-!kJTQVpvSxaOItgj@w z=i!e^(vh8bzKwMgC4Gabuve5OxSfr|F#YSpTqgkHP=UK$Q5izDeI>Lyk!b9b%SKxMKTDSoZY~i%<5y zwMNVOc(OY?N*Y4^R!~(}l(%B@Uf@U^WIcN#&kE9^p>7=&rUM=b8QUZRe&!!S{%bo| zoDbsQUEX6@kw1?>lTYuQ3>e=l2C0QjTkyEyfl$i`jZf`Rr~_E)bY7L|F39^}P#1TM zv@9m5NdoqohvUP?3|>Q+>30c3;YFpd^tJ;w{10^9Zd)a! zX)(jF{WWCoBCim1?WcK#&X`leS_v`EtIq^$2RCcl%Q6W7;)y+j-wE0$%PQzVO^422 zBmL(>;jlphOY-@n*|TT9d@{KylyVL|IP4kyn6*hK@oH#sv}J?b>6hqcYID+e(Q`Ij zX7Q9fd5gmEMa0!VJFbA z)aRE;0qm44%}t$Ulo&CDFos-^Nuw_|E5n4(Vk*n%WxFj+qNM?+u8ulh0^=SvxPFJR z(cD>_%OO{vMU)rq+ci-;0SKFikhzben8N2PEsUs5Sx15k`5EYp^>T zHrCtM#is5qxXpAwpH0;^IFF?s=O(*8dR-CDM``D13M~?S_-0l*2o^S11|7~?MCc{? zwb9%#PcF(9A+-v_liow3v0H20Hrr|pTokNG+a3R*GJf+#wY$cp_0BNiX(tzjC+K6} z_HN;gh=+(HJyf`}hC82DD6>PP*R?x!Ps13PKd3H7+(OsBk;74mFpasuq0U4*lj5^T z2Apy`TiYUg#0KpE8kXEcZ^#wPb-!V`@QREVS63{jJ+@E;Oy>bPrrVk=<9l{yON)yP zn5;BXLo6+r0zJ2_ql!J^#TEW+ELheQ8f^+CQ%@d8c?|-=d4iz1`G){T{KXWDvNa@@ zrqf(YeD7x^Zut>lbbWD;@xuQQlW9`sc%su}OqmaYJP2mh@VR9S%EVriw>KtZp%mDD zH+~T$z)ZEsPgcE|_#Id)=r(%RMRePjKr$1%ReCqQ{ebMf-oVc42FEd%2bfMzSmVMe zQLvq*iVjcE`TCZV0yi)=kxtP~A;xp`E&JhU zsI3pI!&dRMAd51rgF0WvG+LSYpZ#yy+1S;5l4q0|8R_U103nvHt*OImT4wx|?J5$U zLxRezbL$07>+tk#x zSAG$vnNTOx7Qtv7YPyfrP#>m3i9+pMr;wbup0f6pv79MFP{i@klV8U zOj{gG33cnXobZ9Qm96{eo~1f`{NUn%jrf z&9O5NIa>Qtf!Uqww+&q6dTyzI>#oPNFbZtEMq?Wj#BNwSH2&PiGvQOM;T3L(;I&DB zYh*Q&BdHgUoC!M@)j2IvgTV3Pk>?cNm`J|DDS?-?XOZC5qD8R{&xypscbnDbkfPRy zkE9gFx)R-vESyj5%epE=nxuR$qYOjl#iJqmT9G(ukygr@t7*A-IgYLYXKV^V(D70ThP8r%}N!?!|g)XX9{bWgxk=UP8UG1Ws(I*if}75Eb9XpT*@y@tB< z?mV$2o=kEd-eeJe?H;q|c$wjIzL^SO47g5M;g@`b8Y*twuf&!vX*#P3%FdiR>>_Al zSrqI~`X`t+P8x9d1EU)G#lQ{uN5@rd4X@*>Ob7)}o!D8TuiLm|WZ;Ve+j72^TVcrRA*?!Ry-?G<08KPQeW%axTp)>Rm=# zv2f;Af@ZPNw-$_>X|u&f4bhP;PFyxFecZ%PltU zx+{IV+A6?Ps^%aI7?nh+>UXH4$wF+ek$XAhnygr^Ho8kjQbZD%hxC~@2ZSZ%`sc-WC-J5eaRrYko)8pqF?);*9UEg12pSbfU z^X|MKeu$$(dn7=waRLzC9l2=MNB5a(nicU#5GzZxUl@)`JZkRV%YBC=9zS8$_;g65 zc#YhiBkFj7@8D*hpiMR`yFJ@snUAS4%kzZ;S39y+rOsEoYY@$70J6w^f ziTPPZV4a;M$J3&`-qRuG`@EHQIX?LmjL`Ygp#QJO0hyL;1~{HhID4A%(Y6+onLdw( zV_hXm`sI4n_s2QAZn@^+8@^nDy|DajIG~KGyIdW^Y{}kR@_PFkQv8_y6GQ52K zwj6GuwJutgGLOgjt3)Wcv?o4@?!4Jls>Y0lU!KtSqsvygn*+3;a~6_AtVSIP{~kBh z@J5ag-yGI$T_i+p*^LA#c%#i~CNj5jSZG{f{Z+I2XrT&&mwcgKD3^&@!_pM{&^RSXY-j5sATPwu}W-yaSB32H`Y-Syo=*S(m*e6~f?kWy!+!ZD4`K~}* z$~7-zZ)^##z#wvN4}MqV{iz&y4vje(?@!h>`MU%0(46{sZ+Bp4Np~{+ME#7RBJaZ z7poU0EG6o7R+MY(2^us(0s&Z)7Z1n{nXurCB34W0_;b);ge;NnVfAz1il#I;gUDbY zjekVrb%b~q`-vZ0Sm0v!9y^W^h@_}mFi*1_M?cBL!ca1smwq~!!+aQw0#$+90TIP4 zCf#Z3*3C{Bq@aJXk_I*JP&9y=#4t0_46AlY8)Cgil(mCKDK>cQM_vCXw!mhQG5oNUI*?&lCeA}Z3-oWGlq^d6o$I?+rD4^`bc#S!;79A zsa_nlPAr!PWHD;P)#tTrNu8Lv$`TR? zZ~q6^6#?xXKB9P8;&iUt?pdVRf@x#aG6PRJz-qFDc4(t^fKYxx$y5;d?1*K#Kem}n zC4Q7mQ71BE>Q>Fl zwhk-(qm%(;G}4vet8}eyPw3gZg06_R`mfC`)e%kI_Kum3bsf9vO!5}ym)_Xr@+~Ka z8OOLyulF-i(Z0&Y9j&t;LN)`f?CLa_Ux&#Tc%$A{!16Ub_X)vszYwdYYy|uv=A{g3 zn(?XXHk?%{aVmCOnUxP?%_82+Q~!CxYn$t-BDY#w&LP?-8vl?7>8=Nz7qv0-K&ft} z*0}8Pl-G-ft(3JF+bHH#;529#Bi*5?|zqlgjfYsE!2{fRgUY+(gy zX*&~NbBOlCoaaf|R(2!zWio+v_?pdhZxv^_FyQxy(c(7bRbJ7j)rN>%}t>< zH>9l+j5mO8!F)z~>3aMsWU3@F6V!iy0}I2Eyk|d(Nq*W=KSrgxUmFdV?bc5eXfe^YSlw&y;hF2)Nz!M5jHtMNL$}qDK0vab&2zsJ&b=k$z4o zC%c>%aay~_>JdG?-ZzQzh!%uM^wRN*O)ZO5=Up!4kbtkb%%7#tG)qITDOX&RPgO$EnGL*D!U3Yjt*59u7#OvyviWQORr0B8^`Wa_qDcc zU(HX-sbjfiucw4yrE8tF#bGpRvJW;!0{P%HDL<^|dG*?C;8i!zu}IX$`?Q*A>+c}c zLT+e%RFU$Et!4X^odDqeOxL;YQ8KZKS5+Un--3ikB$&%|8ppf08t;A}vg`D=SN4d2 z(|qaP>Y_X4Hw&m<*9P-foXwS!)W^eSMO!rxe;#(yczHCB@mxpV=~u`0yll?Nj&|;4 z3C&ISxFN3?wwcfnZ=2bY_H(O+`IvJUv;WX$~#7+TX9-;2^K0m;}DEH(9bYYzp7(UTA@dZkIT6@XwE5)0Ic! zg=v9$+$c9x+Yl@ZYn4C^yw%Lr!-ov|ZL5x|2>AXWQSU1Q@_|Q%{86fc1AIxcsRcPr z7agfu`sHz9{G`@XDe*f7m z%$MF}f09Ydp4RM^-u{vj6Oe1yZoc)NSJ0e~(bkVp2 zELd>|Xfx0~&Rtf;#Yb!|>^3Q*bU`y?wd4<-!_7*OX%KHFRUgGKKIYXjk(aLv)ve0j z>}+jsmA(9ENOR5`v%!s8xghTvIuN!%A;a5(9H&Q6s}Ud9+={kqF_OaUy^v1!} zb!qUD;e%$dp^9<4HIF*jka5dYhLkWK z|2Y&p@HRyaq;azULiwrUyA&`i>Mdo0#G6473>S#e%jB|`q{U}%((3+IiDs4~%Hy`g zW2~FAGDL!?YhKM}m-6VaaNth}yGzDf7~YD7ZWqS`~oS*(b zr{NE5r*vg^@(1LjSOA=v_D3Jw`>P)^)=g}adj7@zYTi81qAwBgYr)KmFz4lgM+H{W z@(LP02s0-cWnlV{hC1>k(i<*;fnv{GF7%kS9ijZ9PQ6c9^9zs$a|rsQV6;$uU)rCh zjNZ1~mA&3Bs>D@%H8cb9jJM4gGpVl>2C@OYtmaR8i+3rs)ANn=BQ2m1xt$tZ!H^oy zG$b`*lV(>~gCay6#DSc(VKin(_Zw`CJt+;R^)Ok4tKy@S2m^(Z=22-#^ z7lp&C441_3qkN9iuE*!u(lj4Hq&3@PO=qx69b1G4=@3l91}#vgAUSy06^ zOGB&6cOA6GPc8UBvU}b6y&eN#;(Q{QIL5=Oyx{+uL!KU zT;=)j_J9~b@{*(T4K(eG@C@ZSZ1D9wt(#Lcd3>E|mTJOL6${qcQC^s}E9D)PAM>^1IRtG>+w8a%i&W$$LO=nRClP=O=M?lhRGhPV-V}DpFQNT zT{Uyt(j&fQ9q|on^`s<^zyVm+X=@DJ12u3Pb7A$V(n#Vn@5UonaZvidG0GTQ>V5pY zMIX)0n*_8u0S<;cm|R<{<{s;UE=vBObLl)`o_pE^ym

    DPyu&*CFVJ>^84%;3*8t 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 E4}Ybyp8x;= literal 0 HcmV?d00001 diff --git a/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_small.jpg b/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_small.jpg new file mode 100644 index 0000000000000000000000000000000000000000..41fb2eaccbafed7d86598d7e7642e197192f402e GIT binary patch literal 16258 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 literal 0 HcmV?d00001 diff --git a/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java index e71b18857f1..4916929c32f 100644 --- a/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java +++ b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java @@ -51,6 +51,7 @@ public class ColorConversionTests extends CMMTests { DataConversionTests.init(); ColorConvertOpTests.init(); + EmbeddedProfileTests.init(); } protected ColorConversionTests(Group parent, String nodeName, String description) { diff --git a/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java new file mode 100644 index 00000000000..3af6313eff1 --- /dev/null +++ b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This source code is provided to illustrate the usage of a given feature + * or technique and has been deliberately simplified. Additional steps + * required for a production-quality application, such as security checks, + * input validation and proper error handling, might not be present in + * this sample code. + */ + +package j2dbench.tests.cmm; + +import j2dbench.Group; +import j2dbench.Option; +import j2dbench.Result; +import j2dbench.TestEnvironment; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URL; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; + +/* This benchmark verifies how changes in cmm library affects image decoding */ +public class EmbeddedProfileTests extends ColorConversionTests { + + protected static Group grpRoot; + protected static Group grpOptionsRoot; + + protected static Option inputImages; + + public static void init() { + grpRoot = new Group(colorConvRoot, "embed", "Embedded Profile Tests"); + + grpOptionsRoot = new Group(grpRoot, "embedOptions", "Options"); + + inputImages = createImageList(); + + new ReadImageTest(); + } + + private static enum IccImageResource { + SMALL("images/img_icc_small.jpg", "512x512", "Small: 512x512"), + MEDIUM("images/img_icc_medium.jpg", "2048x2048", "Medium: 2048x2048"), + LARGE("images/img_icc_large.jpg", "4096x4096", "Large: 4096x4096"); + + private IccImageResource(String file, String name, String description) { + this.url = CMMTests.class.getResource(file); + this.abbrev = name; + this.description = description; + } + + public final URL url; + public final String abbrev; + public final String description; + } + + private static Option createImageList() { + IccImageResource[] images = IccImageResource.values(); + + int num = images.length; + + String[] names = new String[num]; + String[] abbrev = new String[num]; + String[] descr = new String[num]; + + for (int i = 0; i < num; i++) { + names[i] = images[i].toString(); + abbrev[i] = images[i].abbrev; + descr[i] = images[i].description; + } + + Option list = new Option.ObjectList(grpOptionsRoot, + "Images", "Input Images", + names, images, abbrev, descr, 1); + + return list; + } + + public EmbeddedProfileTests(Group parent, String nodeName, String description) { + super(parent, nodeName, description); + addDependencies(grpOptionsRoot, true); + } + + private static class Context { + URL input; + + public Context(TestEnvironment env, Result res) { + + IccImageResource icc_input = (IccImageResource) + env.getModifier(inputImages); + + input = icc_input.url; + } + } + + public Object initTest(TestEnvironment env, Result res) { + return new Context(env, res); + } + + public void cleanupTest(TestEnvironment env, Object o) { + Context ctx = (Context)o; + ctx.input = null; + } + + private static class ReadImageTest extends EmbeddedProfileTests { + public ReadImageTest() { + super(grpRoot, "embd_img_read", "ImageReader.read()"); + } + + public void runTest(Object octx, int numReps) { + final Context ctx = (Context)octx; + final URL url = ctx.input; + ImageInputStream iis = null; + ImageReader reader = null; + + try { + iis = ImageIO.createImageInputStream(url.openStream()); + reader = ImageIO.getImageReaders(iis).next(); + } catch (IOException e) { + throw new RuntimeException("Unable to run the becnhmark", e); + } + + do { + try { + reader.setInput(iis); + BufferedImage img = reader.read(0); + reader.reset(); + + iis = ImageIO.createImageInputStream(url.openStream()); + } catch (Exception e) { + e.printStackTrace(); + } + } while (--numReps >= 0); + } + } +} diff --git a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c index 7da0370baad..1340c82a822 100644 --- a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c @@ -117,6 +117,7 @@ static jfieldID IL_offset_fID; static jfieldID IL_nextRowOffset_fID; static jfieldID IL_width_fID; static jfieldID IL_height_fID; +static jfieldID IL_imageAtOnce_fID; static jfieldID PF_ID_fID; JavaVM *javaVM; @@ -237,7 +238,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform * Method: loadProfile * Signature: ([B)J */ -JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile +JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative (JNIEnv *env, jobject obj, jbyteArray data) { jbyte* dataArray; @@ -284,7 +285,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile * Method: freeProfile * Signature: (J)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfile +JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative (JNIEnv *env, jobject obj, jlong id) { storeID_t sProf; @@ -369,48 +370,22 @@ static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size); -/* - * Class: sun_java2d_cmm_lcms_LCMS - * Method: getTagSize - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagSize - (JNIEnv *env, jobject obj, jlong id, jint tagSig) -{ - storeID_t sProf; - TagSignature_t sig; - jint result = -1; - - sProf.j = id; - sig.j = tagSig; - - if (tagSig == SigHead) { - result = sizeof(cmsICCHeader); - } else { - if (cmsIsTag(sProf.pf, sig.cms)) { - result = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0); - } else { - JNU_ThrowByName(env, "java/awt/color/CMMException", - "ICC profile tag not found"); - } - } - - return result; -} /* * Class: sun_java2d_cmm_lcms_LCMS * Method: getTagData * Signature: (JI[B)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData - (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data) +JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative + (JNIEnv *env, jobject obj, jlong id, jint tagSig) { storeID_t sProf; TagSignature_t sig; cmsInt32Number tagSize; - jbyte* dataArray; + jbyte* dataArray = NULL; + jbyteArray data = NULL; + jint bufSize; sProf.j = id; @@ -419,12 +394,14 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (tagSig == SigHead) { cmsBool status; - bufSize =(*env)->GetArrayLength(env, data); + // allocate java array + bufSize = sizeof(cmsICCHeader); + data = (*env)->NewByteArray(env, bufSize); - if (bufSize < sizeof(cmsICCHeader)) { - JNU_ThrowByName(env, "java/awt/color/CMMException", - "Insufficient buffer capacity"); - return; + if (data == NULL) { + JNU_ThrowByName(env, "java/awt/color/CMMException", + "Unable to allocate buffer"); + return NULL; } dataArray = (*env)->GetByteArrayElements (env, data, 0); @@ -432,7 +409,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (dataArray == NULL) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Unable to get buffer"); - return; + return NULL; } status = _getHeaderInfo(sProf.pf, dataArray, bufSize); @@ -442,9 +419,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (!status) { JNU_ThrowByName(env, "java/awt/color/CMMException", "ICC Profile header not found"); + return NULL; } - return; + return data; } if (cmsIsTag(sProf.pf, sig.cms)) { @@ -452,16 +430,15 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData } else { JNU_ThrowByName(env, "java/awt/color/CMMException", "ICC profile tag not found"); - return; + return NULL; } - // verify data buffer capacity - bufSize = (*env)->GetArrayLength(env, data); - - if (tagSize < 0 || 0 > bufSize || tagSize > bufSize) { + // allocate java array + data = (*env)->NewByteArray(env, tagSize); + if (data == NULL) { JNU_ThrowByName(env, "java/awt/color/CMMException", - "Insufficient buffer capacity."); - return; + "Unable to allocate buffer"); + return NULL; } dataArray = (*env)->GetByteArrayElements (env, data, 0); @@ -469,7 +446,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (dataArray == NULL) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Unable to get buffer"); - return; + return NULL; } bufSize = cmsReadRawTag(sProf.pf, sig.cms, dataArray, tagSize); @@ -479,8 +456,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (bufSize != tagSize) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Can not get tag data."); + return NULL; } - return; + return data; } /* @@ -488,7 +466,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData * Method: setTagData * Signature: (JI[B)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagData +JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data) { storeID_t sProf; @@ -586,6 +564,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert char* inputRow; char* outputRow; jobject srcData, dstData; + jboolean srcAtOnce = JNI_FALSE, dstAtOnce = JNI_FALSE; srcOffset = (*env)->GetIntField (env, src, IL_offset_fID); srcNextRowOffset = (*env)->GetIntField (env, src, IL_nextRowOffset_fID); @@ -594,6 +573,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert width = (*env)->GetIntField (env, src, IL_width_fID); height = (*env)->GetIntField (env, src, IL_height_fID); + srcAtOnce = (*env)->GetBooleanField(env, src, IL_imageAtOnce_fID); + dstAtOnce = (*env)->GetBooleanField(env, dst, IL_imageAtOnce_fID); + sTrans.j = (*env)->GetLongField (env, trans, Trans_ID_fID); if (sTrans.xf == NULL) { @@ -625,10 +607,14 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert inputRow = (char*)inputBuffer + srcOffset; outputRow = (char*)outputBuffer + dstOffset; - for (i = 0; i < height; i++) { - cmsDoTransform(sTrans.xf, inputRow, outputRow, width); - inputRow += srcNextRowOffset; - outputRow += dstNextRowOffset; + if (srcAtOnce && dstAtOnce) { + cmsDoTransform(sTrans.xf, inputRow, outputRow, width * height); + } else { + for (i = 0; i < height; i++) { + cmsDoTransform(sTrans.xf, inputRow, outputRow, width); + inputRow += srcNextRowOffset; + outputRow += dstNextRowOffset; + } } releaseILData(env, inputBuffer, srcDType, srcData); @@ -670,6 +656,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS IL_width_fID = (*env)->GetFieldID (env, IL, "width", "I"); IL_height_fID = (*env)->GetFieldID (env, IL, "height", "I"); IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I"); + IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z"); IL_nextRowOffset_fID = (*env)->GetFieldID (env, IL, "nextRowOffset", "I"); PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J"); From 2f0d1e1f6eb14f5addaff2b26787afab63c55ed7 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Mar 2013 11:17:28 -0800 Subject: [PATCH 091/102] Added tag jdk8-b80 for changeset 3a8903868eb2 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 5dad9a69090..e869333243b 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -201,3 +201,4 @@ b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74 3933eebc659d58c597aa8cb4b3e58f2250ce3e1a jdk8-b77 fd1a5574cf68af24bfd52decc37ac6361afb278a jdk8-b78 91d35211e74464dca5edf9b66ab01d0d0d8cded7 jdk8-b79 +907a926d3c96472f357617b48b6b968ea855c23c jdk8-b80 From 6190b6e12ee4be47586e2a88e2b6ca8bf6d793c0 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Mar 2013 11:17:32 -0800 Subject: [PATCH 092/102] Added tag jdk8-b80 for changeset 18835185e71e --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index c1ece0dcce9..7e7b0160fc2 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -201,3 +201,4 @@ d4e68ce17795601017ac2f952baad7272942c36e jdk8-b75 35684a40c5845782324dbcc9ac8969528020ff61 jdk8-b77 27d6368ae8ba570c31c2f0e696d39c99fa2f4538 jdk8-b78 e41fb1aa0329767b2737303c994e38bede1baa07 jdk8-b79 +5f3d4a6bdd027a1631d97e2dfff63fd5e46987a4 jdk8-b80 From 6a85dd0d01bf56b6ac27a9f030c09752dd26b336 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Mar 2013 11:17:36 -0800 Subject: [PATCH 093/102] Added tag jdk8-b80 for changeset 8a6e09ace0d3 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index f4baba41cfc..06c16c3e00c 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -320,3 +320,4 @@ d5e12e7d2f719144d84903d9151455661c47b476 jdk8-b78 555ec35a250783110aa070dbc8a8603f6cabe41f hs25-b20 6691814929b606fe0e7954fd6e485dd876505c83 jdk8-b79 df5396524152118535c36da5801d828b560d19a2 hs25-b21 +4a198b201f3ce84433fa94a3ca65d061473e7c4c jdk8-b80 From b67e4eeabf8b47d9d7489b7643047ace7c51b7de Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Mar 2013 11:17:45 -0800 Subject: [PATCH 094/102] Added tag jdk8-b80 for changeset 81737a0a6546 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 6e644a9188e..fa256974249 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -201,3 +201,4 @@ ff0b73a6b3f6cea644d37d56d746a37743419fa7 jdk8-b75 573e789c187a69a3ae00bffd26eb35c0f4a60636 jdk8-b77 00958c5a7070bd578aa8b70773cb3f204a9c1be1 jdk8-b78 58fa065dd5d663d62f85402461388fb7a92656fa jdk8-b79 +4873a0499bc3bd263b7dd3b551a2b4e275ab5a0b jdk8-b80 From 2849834a458847bb4c32d8697600e27de5f3d55f Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Mar 2013 11:17:47 -0800 Subject: [PATCH 095/102] Added tag jdk8-b80 for changeset 55eb22e60638 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index ab1f5737219..06142f221c5 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -201,3 +201,4 @@ c4853f3f0e89ac60aa5b517f5f224f0f60e08577 jdk8-b76 64dfba1bad16433f609f17a42c3c5990367c5c0b jdk8-b77 391de4c992d1960a09cdd340362ff936bac69323 jdk8-b78 70d8658d2a3063bc13127f3452af017d838f1362 jdk8-b79 +b0224010e2f0c2474055ac592c8d3f37b9264690 jdk8-b80 From 83ceccf920a2a06f3db02d87b338350b2f9001f3 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Mar 2013 11:17:56 -0800 Subject: [PATCH 096/102] Added tag jdk8-b80 for changeset 72415be10117 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 93a4114bab9..fbd3f71e449 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -201,3 +201,4 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70 b2fc8e31cecc35b76188e821d4c5dc0e0b74ac24 jdk8-b77 00b7535d743f83eda763c10b3c9ea19ba4b67f55 jdk8-b78 c933505d75c2a0a671f06d6dac5d2237a9228d2d jdk8-b79 +dfb40f066c6ce129822f0f5dc2ac89173808781a jdk8-b80 From e0a29cc0f13d9284d7c7982532be564d22d48acb Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Mar 2013 11:18:06 -0800 Subject: [PATCH 097/102] Added tag jdk8-b80 for changeset dec13271b739 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 9a749432884..0d946930fa4 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -201,3 +201,4 @@ e81839b3233792415daaab051698edc6067f1a16 jdk8-b76 89c66415168925dffe492356ff893ff248bb5603 jdk8-b77 af8417e590f4e76e0dfed09e71239fb102ef0d43 jdk8-b78 56dfafbb9e1ad7548a4415316dc003296fb498cb jdk8-b79 +a8227c61768499dac847ea718af6719027c949f2 jdk8-b80 From ebdab667c36797c776051d3ab575063de72305ea Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 8 Mar 2013 08:10:01 -0800 Subject: [PATCH 098/102] Added tag hs25-b22 for changeset f06b74113bc2 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 06c16c3e00c..5bf8e9848bb 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -321,3 +321,4 @@ d5e12e7d2f719144d84903d9151455661c47b476 jdk8-b78 6691814929b606fe0e7954fd6e485dd876505c83 jdk8-b79 df5396524152118535c36da5801d828b560d19a2 hs25-b21 4a198b201f3ce84433fa94a3ca65d061473e7c4c jdk8-b80 +dd6350b4abc4a6c19c89dd982cc0e4f3d119885c hs25-b22 From b44696200eb94fed601daa2e3626890782fd094a Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Tue, 12 Mar 2013 15:17:19 +0100 Subject: [PATCH 099/102] 8009695: embedded/GP/RI: This intermittent error happens too often, makes the build unstable, and waste machine Reviewed-by: dholmes, tbell --- jdk/make/common/shared/Defs-utils.gmk | 36 +++++++++++++-------------- jdk/makefiles/Images.gmk | 12 +++++---- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/jdk/make/common/shared/Defs-utils.gmk b/jdk/make/common/shared/Defs-utils.gmk index a210de015b7..a14a08d1198 100644 --- a/jdk/make/common/shared/Defs-utils.gmk +++ b/jdk/make/common/shared/Defs-utils.gmk @@ -74,24 +74,24 @@ ifeq ($(PLATFORM),macosx) UTILS_DEVTOOL_PATH=$(DEVTOOLS_PATH) endif -# Utilities -ifdef CROSS_COMPILE_ARCH - AR = $(COMPILER_PATH)ar - AS = $(COMPILER_PATH)as - LD = $(COMPILER_PATH)ld - MCS = $(COMPILER_PATH)mcs - NM = $(COMPILER_PATH)nm - STRIP = $(COMPILER_PATH)strip -endif - -ifeq ($(PLATFORM),solaris) - AR = $(UTILS_CCS_BIN_PATH)ar - AS = $(UTILS_CCS_BIN_PATH)as - LD = $(UTILS_CCS_BIN_PATH)ld - MCS = $(UTILS_CCS_BIN_PATH)mcs - NM = $(UTILS_CCS_BIN_PATH)nm - STRIP = $(UTILS_CCS_BIN_PATH)strip -endif +ifndef CONFIGURE_BUILD + # Utilities + ifdef CROSS_COMPILE_ARCH + AR = $(COMPILER_PATH)ar + AS = $(COMPILER_PATH)as + LD = $(COMPILER_PATH)ld + MCS = $(COMPILER_PATH)mcs + NM = $(COMPILER_PATH)nm + STRIP = $(COMPILER_PATH)strip + else + AR = $(UTILS_CCS_BIN_PATH)ar + AS = $(UTILS_CCS_BIN_PATH)as + LD = $(UTILS_CCS_BIN_PATH)ld + MCS = $(UTILS_CCS_BIN_PATH)mcs + NM = $(UTILS_CCS_BIN_PATH)nm + STRIP = $(UTILS_CCS_BIN_PATH)strip + endif +endif # CONFIGURE_BUILD ADB = $(UTILS_COMMAND_PATH)adb BASENAME = $(UTILS_COMMAND_PATH)basename diff --git a/jdk/makefiles/Images.gmk b/jdk/makefiles/Images.gmk index bb737f88878..8dedfaec3d0 100644 --- a/jdk/makefiles/Images.gmk +++ b/jdk/makefiles/Images.gmk @@ -264,6 +264,13 @@ $(foreach f,$(filter $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_ISADIR)/%,$(JDK_JD $(foreach f,$(filter $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_ISADIR)/%,$(JDKJRE_JDKOUT_LIB_LIST)),\ $(eval $(call AddFileToCopy,$(JDK_OUTPUTDIR),$(JDK_OVERLAY_IMAGE_DIR)/jre,$f,JDKJRE_OVERLAY_LIB_TARGETS))) +ifneq ($(PROFILE),) +# Files in lib$(PROFILE) are excluded from the generic copying routines so +# we have to add them back in here +$(foreach f,$(CUSTOM_PROFILE_JARS),\ + $(eval $(call AddFileToCopy,$(IMAGES_OUTPUTDIR)/lib$(PROFILE),$(JRE_IMAGE_DIR)/lib,$f,JRE_LIB_TARGETS))) +endif + # CTE plugin security change require new empty directory lib/applet $(JRE_IMAGE_DIR)/lib/applet: $(ECHO) $(LOG_INFO) Creating $(patsubst $(OUTPUT_ROOT)/%,%,$@) @@ -738,11 +745,6 @@ jdk-overlay-image: $(JDK_OVERLAY_BIN_TARGETS) $(JDKJRE_OVERLAY_BIN_TARGETS) \ $(JDKJRE_OVERLAY_STRIP_LIST) $(JDK_OVERLAY_BIN_STRIP_LIST) ifneq ($(PROFILE),) -# Files in lib$(PROFILE) are excluded from the generic copying routines so -# we have to add them back in here -$(foreach f,$(CUSTOM_PROFILE_JARS),\ - $(eval $(call AddFileToCopy,$(IMAGES_OUTPUTDIR)/lib$(PROFILE),$(JRE_IMAGE_DIR)/lib,$f,JRE_LIB_TARGETS))) - PROFILE_IMAGE_JARS := $(filter %.jar, $(JRE_LIB_TARGETS)) PROFILE_IMAGE_JARS_CHECKED := $(IMAGES_OUTPUTDIR)/lib$(PROFILE)/_jars_checked From 4d75d57692b5f8e02a62bcbd7aeaa161434ab620 Mon Sep 17 00:00:00 2001 From: Tim Bell Date: Tue, 12 Mar 2013 22:08:13 -0700 Subject: [PATCH 100/102] 8009819: build-infra: RE jdk8 build forest fails for windows since addition of --with-dxsdk Reviewed-by: katleman --- common/autoconf/generated-configure.sh | 479 +++++++++++++------------ common/autoconf/toolchain_windows.m4 | 2 + 2 files changed, 254 insertions(+), 227 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 0787d4bac42..132eccc50a1 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67 for OpenJDK jdk8. +# Generated by GNU Autoconf 2.68 for OpenJDK jdk8. # # Report bugs to . # @@ -91,6 +91,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -216,11 +217,18 @@ IFS=$as_save_IFS # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : @@ -1440,7 +1448,7 @@ Try \`$0 --help' for more information" $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac @@ -1872,7 +1880,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF OpenJDK configure jdk8 -generated by GNU Autoconf 2.67 +generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation @@ -1918,7 +1926,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile @@ -1956,7 +1964,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile @@ -1994,7 +2002,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_objc_try_compile @@ -2031,7 +2039,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp @@ -2068,7 +2076,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp @@ -2081,10 +2089,10 @@ fi ac_fn_cxx_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval "test \"\${$3+set}\"" = set; then : + if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 @@ -2151,7 +2159,7 @@ $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" @@ -2160,7 +2168,7 @@ eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_mongrel @@ -2201,7 +2209,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_run @@ -2215,7 +2223,7 @@ ac_fn_cxx_check_header_compile () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2233,7 +2241,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_compile @@ -2410,7 +2418,7 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ rm -f conftest.val fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_compute_int @@ -2456,7 +2464,7 @@ fi # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link @@ -2469,7 +2477,7 @@ ac_fn_cxx_check_func () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2524,7 +2532,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_func @@ -2537,7 +2545,7 @@ ac_fn_c_check_header_compile () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2555,7 +2563,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile cat >config.log <<_ACEOF @@ -2563,7 +2571,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by OpenJDK $as_me jdk8, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2821,7 +2829,7 @@ $as_echo "$as_me: loading site script $ac_site_file" >&6;} || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi done @@ -3743,7 +3751,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1362563419 +DATE_WHEN_GENERATED=1363150186 ############################################################################### # @@ -3781,7 +3789,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_BASENAME+set}" = set; then : +if ${ac_cv_path_BASENAME+:} false; then : $as_echo_n "(cached) " >&6 else case $BASENAME in @@ -3840,7 +3848,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_BASH+set}" = set; then : +if ${ac_cv_path_BASH+:} false; then : $as_echo_n "(cached) " >&6 else case $BASH in @@ -3899,7 +3907,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CAT+set}" = set; then : +if ${ac_cv_path_CAT+:} false; then : $as_echo_n "(cached) " >&6 else case $CAT in @@ -3958,7 +3966,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CHMOD+set}" = set; then : +if ${ac_cv_path_CHMOD+:} false; then : $as_echo_n "(cached) " >&6 else case $CHMOD in @@ -4017,7 +4025,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CMP+set}" = set; then : +if ${ac_cv_path_CMP+:} false; then : $as_echo_n "(cached) " >&6 else case $CMP in @@ -4076,7 +4084,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_COMM+set}" = set; then : +if ${ac_cv_path_COMM+:} false; then : $as_echo_n "(cached) " >&6 else case $COMM in @@ -4135,7 +4143,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CP+set}" = set; then : +if ${ac_cv_path_CP+:} false; then : $as_echo_n "(cached) " >&6 else case $CP in @@ -4194,7 +4202,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CPIO+set}" = set; then : +if ${ac_cv_path_CPIO+:} false; then : $as_echo_n "(cached) " >&6 else case $CPIO in @@ -4253,7 +4261,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CUT+set}" = set; then : +if ${ac_cv_path_CUT+:} false; then : $as_echo_n "(cached) " >&6 else case $CUT in @@ -4312,7 +4320,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_DATE+set}" = set; then : +if ${ac_cv_path_DATE+:} false; then : $as_echo_n "(cached) " >&6 else case $DATE in @@ -4371,7 +4379,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_DIFF+set}" = set; then : +if ${ac_cv_path_DIFF+:} false; then : $as_echo_n "(cached) " >&6 else case $DIFF in @@ -4430,7 +4438,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_DIRNAME+set}" = set; then : +if ${ac_cv_path_DIRNAME+:} false; then : $as_echo_n "(cached) " >&6 else case $DIRNAME in @@ -4489,7 +4497,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ECHO+set}" = set; then : +if ${ac_cv_path_ECHO+:} false; then : $as_echo_n "(cached) " >&6 else case $ECHO in @@ -4548,7 +4556,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_EXPR+set}" = set; then : +if ${ac_cv_path_EXPR+:} false; then : $as_echo_n "(cached) " >&6 else case $EXPR in @@ -4607,7 +4615,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_FILE+set}" = set; then : +if ${ac_cv_path_FILE+:} false; then : $as_echo_n "(cached) " >&6 else case $FILE in @@ -4666,7 +4674,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_FIND+set}" = set; then : +if ${ac_cv_path_FIND+:} false; then : $as_echo_n "(cached) " >&6 else case $FIND in @@ -4725,7 +4733,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_HEAD+set}" = set; then : +if ${ac_cv_path_HEAD+:} false; then : $as_echo_n "(cached) " >&6 else case $HEAD in @@ -4784,7 +4792,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_LN+set}" = set; then : +if ${ac_cv_path_LN+:} false; then : $as_echo_n "(cached) " >&6 else case $LN in @@ -4843,7 +4851,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_LS+set}" = set; then : +if ${ac_cv_path_LS+:} false; then : $as_echo_n "(cached) " >&6 else case $LS in @@ -4902,7 +4910,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_MKDIR+set}" = set; then : +if ${ac_cv_path_MKDIR+:} false; then : $as_echo_n "(cached) " >&6 else case $MKDIR in @@ -4961,7 +4969,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_MKTEMP+set}" = set; then : +if ${ac_cv_path_MKTEMP+:} false; then : $as_echo_n "(cached) " >&6 else case $MKTEMP in @@ -5020,7 +5028,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_MV+set}" = set; then : +if ${ac_cv_path_MV+:} false; then : $as_echo_n "(cached) " >&6 else case $MV in @@ -5079,7 +5087,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_PRINTF+set}" = set; then : +if ${ac_cv_path_PRINTF+:} false; then : $as_echo_n "(cached) " >&6 else case $PRINTF in @@ -5138,7 +5146,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_THEPWDCMD+set}" = set; then : +if ${ac_cv_path_THEPWDCMD+:} false; then : $as_echo_n "(cached) " >&6 else case $THEPWDCMD in @@ -5197,7 +5205,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_RM+set}" = set; then : +if ${ac_cv_path_RM+:} false; then : $as_echo_n "(cached) " >&6 else case $RM in @@ -5256,7 +5264,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_SH+set}" = set; then : +if ${ac_cv_path_SH+:} false; then : $as_echo_n "(cached) " >&6 else case $SH in @@ -5315,7 +5323,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_SORT+set}" = set; then : +if ${ac_cv_path_SORT+:} false; then : $as_echo_n "(cached) " >&6 else case $SORT in @@ -5374,7 +5382,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_TAIL+set}" = set; then : +if ${ac_cv_path_TAIL+:} false; then : $as_echo_n "(cached) " >&6 else case $TAIL in @@ -5433,7 +5441,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_TAR+set}" = set; then : +if ${ac_cv_path_TAR+:} false; then : $as_echo_n "(cached) " >&6 else case $TAR in @@ -5492,7 +5500,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_TEE+set}" = set; then : +if ${ac_cv_path_TEE+:} false; then : $as_echo_n "(cached) " >&6 else case $TEE in @@ -5551,7 +5559,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_TOUCH+set}" = set; then : +if ${ac_cv_path_TOUCH+:} false; then : $as_echo_n "(cached) " >&6 else case $TOUCH in @@ -5610,7 +5618,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_TR+set}" = set; then : +if ${ac_cv_path_TR+:} false; then : $as_echo_n "(cached) " >&6 else case $TR in @@ -5669,7 +5677,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_UNAME+set}" = set; then : +if ${ac_cv_path_UNAME+:} false; then : $as_echo_n "(cached) " >&6 else case $UNAME in @@ -5728,7 +5736,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_UNIQ+set}" = set; then : +if ${ac_cv_path_UNIQ+:} false; then : $as_echo_n "(cached) " >&6 else case $UNIQ in @@ -5787,7 +5795,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_WC+set}" = set; then : +if ${ac_cv_path_WC+:} false; then : $as_echo_n "(cached) " >&6 else case $WC in @@ -5846,7 +5854,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_WHICH+set}" = set; then : +if ${ac_cv_path_WHICH+:} false; then : $as_echo_n "(cached) " >&6 else case $WHICH in @@ -5905,7 +5913,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_XARGS+set}" = set; then : +if ${ac_cv_path_XARGS+:} false; then : $as_echo_n "(cached) " >&6 else case $XARGS in @@ -5965,7 +5973,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AWK+set}" = set; then : +if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then @@ -6015,7 +6023,7 @@ $as_echo "$as_me: Could not find $PROG_NAME!" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if test "${ac_cv_path_GREP+set}" = set; then : +if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then @@ -6090,7 +6098,7 @@ $as_echo "$as_me: Could not find $PROG_NAME!" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then : +if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 @@ -6169,7 +6177,7 @@ $as_echo "$as_me: Could not find $PROG_NAME!" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } -if test "${ac_cv_path_FGREP+set}" = set; then : +if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 @@ -6248,7 +6256,7 @@ $as_echo "$as_me: Could not find $PROG_NAME!" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } -if test "${ac_cv_path_SED+set}" = set; then : +if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ @@ -6334,7 +6342,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_NAWK+set}" = set; then : +if ${ac_cv_path_NAWK+:} false; then : $as_echo_n "(cached) " >&6 else case $NAWK in @@ -6394,7 +6402,7 @@ RM="$RM -f" set dummy cygpath; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CYGPATH+set}" = set; then : +if ${ac_cv_path_CYGPATH+:} false; then : $as_echo_n "(cached) " >&6 else case $CYGPATH in @@ -6434,7 +6442,7 @@ fi set dummy readlink; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_READLINK+set}" = set; then : +if ${ac_cv_path_READLINK+:} false; then : $as_echo_n "(cached) " >&6 else case $READLINK in @@ -6474,7 +6482,7 @@ fi set dummy df; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_DF+set}" = set; then : +if ${ac_cv_path_DF+:} false; then : $as_echo_n "(cached) " >&6 else case $DF in @@ -6514,7 +6522,7 @@ fi set dummy SetFile; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_SETFILE+set}" = set; then : +if ${ac_cv_path_SETFILE+:} false; then : $as_echo_n "(cached) " >&6 else case $SETFILE in @@ -6560,7 +6568,7 @@ $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } -if test "${ac_cv_build+set}" = set; then : +if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias @@ -6576,7 +6584,7 @@ fi $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' @@ -6594,7 +6602,7 @@ case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } -if test "${ac_cv_host+set}" = set; then : +if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then @@ -6609,7 +6617,7 @@ fi $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' @@ -6627,7 +6635,7 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } -if test "${ac_cv_target+set}" = set; then : +if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then @@ -6642,7 +6650,7 @@ fi $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; -*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5 ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' @@ -8108,7 +8116,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_PKGHANDLER+set}" = set; then : +if ${ac_cv_prog_PKGHANDLER+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PKGHANDLER"; then @@ -8473,7 +8481,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CHECK_GMAKE+set}" = set; then : +if ${ac_cv_path_CHECK_GMAKE+:} false; then : $as_echo_n "(cached) " >&6 else case $CHECK_GMAKE in @@ -8827,7 +8835,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CHECK_MAKE+set}" = set; then : +if ${ac_cv_path_CHECK_MAKE+:} false; then : $as_echo_n "(cached) " >&6 else case $CHECK_MAKE in @@ -9186,7 +9194,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CHECK_TOOLSDIR_GMAKE+set}" = set; then : +if ${ac_cv_path_CHECK_TOOLSDIR_GMAKE+:} false; then : $as_echo_n "(cached) " >&6 else case $CHECK_TOOLSDIR_GMAKE in @@ -9539,7 +9547,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CHECK_TOOLSDIR_MAKE+set}" = set; then : +if ${ac_cv_path_CHECK_TOOLSDIR_MAKE+:} false; then : $as_echo_n "(cached) " >&6 else case $CHECK_TOOLSDIR_MAKE in @@ -9935,7 +9943,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_UNZIP+set}" = set; then : +if ${ac_cv_path_UNZIP+:} false; then : $as_echo_n "(cached) " >&6 else case $UNZIP in @@ -9994,7 +10002,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ZIP+set}" = set; then : +if ${ac_cv_path_ZIP+:} false; then : $as_echo_n "(cached) " >&6 else case $ZIP in @@ -10053,7 +10061,7 @@ $as_echo "$as_me: Could not find $PROG_NAME!" >&6;} set dummy ldd; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_LDD+set}" = set; then : +if ${ac_cv_path_LDD+:} false; then : $as_echo_n "(cached) " >&6 else case $LDD in @@ -10099,7 +10107,7 @@ fi set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_OTOOL+set}" = set; then : +if ${ac_cv_path_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else case $OTOOL in @@ -10144,7 +10152,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_READELF+set}" = set; then : +if ${ac_cv_path_READELF+:} false; then : $as_echo_n "(cached) " >&6 else case $READELF in @@ -10187,7 +10195,7 @@ done set dummy hg; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_HG+set}" = set; then : +if ${ac_cv_path_HG+:} false; then : $as_echo_n "(cached) " >&6 else case $HG in @@ -10227,7 +10235,7 @@ fi set dummy stat; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_STAT+set}" = set; then : +if ${ac_cv_path_STAT+:} false; then : $as_echo_n "(cached) " >&6 else case $STAT in @@ -10267,7 +10275,7 @@ fi set dummy time; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_TIME+set}" = set; then : +if ${ac_cv_path_TIME+:} false; then : $as_echo_n "(cached) " >&6 else case $TIME in @@ -10312,7 +10320,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_COMM+set}" = set; then : +if ${ac_cv_path_COMM+:} false; then : $as_echo_n "(cached) " >&6 else case $COMM in @@ -10376,7 +10384,7 @@ if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_PKG_CONFIG+set}" = set; then : +if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in @@ -10419,7 +10427,7 @@ if test -z "$ac_cv_path_PKG_CONFIG"; then set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then : +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in @@ -10592,7 +10600,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_BDEPS_UNZIP+set}" = set; then : +if ${ac_cv_prog_BDEPS_UNZIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$BDEPS_UNZIP"; then @@ -10638,7 +10646,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_BDEPS_FTP+set}" = set; then : +if ${ac_cv_prog_BDEPS_FTP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$BDEPS_FTP"; then @@ -11905,7 +11913,7 @@ $as_echo "$BOOT_JDK_VERSION" >&6; } set dummy javac; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_JAVAC_CHECK+set}" = set; then : +if ${ac_cv_path_JAVAC_CHECK+:} false; then : $as_echo_n "(cached) " >&6 else case $JAVAC_CHECK in @@ -11945,7 +11953,7 @@ fi set dummy java; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_JAVA_CHECK+set}" = set; then : +if ${ac_cv_path_JAVA_CHECK+:} false; then : $as_echo_n "(cached) " >&6 else case $JAVA_CHECK in @@ -16004,7 +16012,7 @@ if test "x$OPENJDK_TARGET_OS" = "xwindows"; then set dummy link; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CYGWIN_LINK+set}" = set; then : +if ${ac_cv_path_CYGWIN_LINK+:} false; then : $as_echo_n "(cached) " >&6 else case $CYGWIN_LINK in @@ -16993,6 +17001,8 @@ $as_echo_n "checking for DirectX SDK... " >&6; } dxsdk_path="$with_dxsdk" elif test "x$DXSDK_DIR" != x; then dxsdk_path="$DXSDK_DIR" + elif test -d "C:/DXSDK"; then + dxsdk_path="C:/DXSDK" else as_fn_error $? "Could not find the DirectX SDK" "$LINENO" 5 fi @@ -17417,7 +17427,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_BUILD_CC+set}" = set; then : +if ${ac_cv_path_BUILD_CC+:} false; then : $as_echo_n "(cached) " >&6 else case $BUILD_CC in @@ -17728,7 +17738,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_BUILD_CXX+set}" = set; then : +if ${ac_cv_path_BUILD_CXX+:} false; then : $as_echo_n "(cached) " >&6 else case $BUILD_CXX in @@ -18037,7 +18047,7 @@ $as_echo "$as_me: Rewriting BUILD_CXX to \"$new_complete\"" >&6;} set dummy ld; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_BUILD_LD+set}" = set; then : +if ${ac_cv_path_BUILD_LD+:} false; then : $as_echo_n "(cached) " >&6 else case $BUILD_LD in @@ -18549,7 +18559,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_TOOLS_DIR_CC+set}" = set; then : +if ${ac_cv_path_TOOLS_DIR_CC+:} false; then : $as_echo_n "(cached) " >&6 else case $TOOLS_DIR_CC in @@ -18601,7 +18611,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_POTENTIAL_CC+set}" = set; then : +if ${ac_cv_path_POTENTIAL_CC+:} false; then : $as_echo_n "(cached) " >&6 else case $POTENTIAL_CC in @@ -19014,7 +19024,7 @@ $as_echo "yes, trying to find proper $COMPILER_NAME compiler" >&6; } set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_PROPER_COMPILER_CC+set}" = set; then : +if ${ac_cv_prog_PROPER_COMPILER_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PROPER_COMPILER_CC"; then @@ -19058,7 +19068,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_PROPER_COMPILER_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_PROPER_COMPILER_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_PROPER_COMPILER_CC"; then @@ -19508,7 +19518,7 @@ if test -n "$ac_tool_prefix"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -19552,7 +19562,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -19605,7 +19615,7 @@ fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -19720,7 +19730,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -19763,7 +19773,7 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -19822,7 +19832,7 @@ $as_echo "$ac_try_echo"; } >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi fi fi @@ -19833,7 +19843,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : +if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -19874,7 +19884,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -19884,7 +19894,7 @@ OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : +if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -19921,7 +19931,7 @@ ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : +if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag @@ -19999,7 +20009,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no @@ -20118,7 +20128,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_TOOLS_DIR_CXX+set}" = set; then : +if ${ac_cv_path_TOOLS_DIR_CXX+:} false; then : $as_echo_n "(cached) " >&6 else case $TOOLS_DIR_CXX in @@ -20170,7 +20180,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_POTENTIAL_CXX+set}" = set; then : +if ${ac_cv_path_POTENTIAL_CXX+:} false; then : $as_echo_n "(cached) " >&6 else case $POTENTIAL_CXX in @@ -20583,7 +20593,7 @@ $as_echo "yes, trying to find proper $COMPILER_NAME compiler" >&6; } set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_PROPER_COMPILER_CXX+set}" = set; then : +if ${ac_cv_prog_PROPER_COMPILER_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PROPER_COMPILER_CXX"; then @@ -20627,7 +20637,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_PROPER_COMPILER_CXX+set}" = set; then : +if ${ac_cv_prog_ac_ct_PROPER_COMPILER_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_PROPER_COMPILER_CXX"; then @@ -21081,7 +21091,7 @@ if test -z "$CXX"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CXX+set}" = set; then : +if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then @@ -21125,7 +21135,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then : +if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then @@ -21203,7 +21213,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } -if test "${ac_cv_cxx_compiler_gnu+set}" = set; then : +if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -21240,7 +21250,7 @@ ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } -if test "${ac_cv_prog_cxx_g+set}" = set; then : +if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag @@ -21338,7 +21348,7 @@ if test -n "$ac_tool_prefix"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OBJC+set}" = set; then : +if ${ac_cv_prog_OBJC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJC"; then @@ -21382,7 +21392,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OBJC+set}" = set; then : +if ${ac_cv_prog_ac_ct_OBJC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJC"; then @@ -21458,7 +21468,7 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Objective C compiler" >&5 $as_echo_n "checking whether we are using the GNU Objective C compiler... " >&6; } -if test "${ac_cv_objc_compiler_gnu+set}" = set; then : +if ${ac_cv_objc_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -21495,7 +21505,7 @@ ac_test_OBJCFLAGS=${OBJCFLAGS+set} ac_save_OBJCFLAGS=$OBJCFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $OBJC accepts -g" >&5 $as_echo_n "checking whether $OBJC accepts -g... " >&6; } -if test "${ac_cv_prog_objc_g+set}" = set; then : +if ${ac_cv_prog_objc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_objc_werror_flag=$ac_objc_werror_flag @@ -21871,7 +21881,7 @@ if test "x$OPENJDK_TARGET_OS" != xwindows; then set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AR+set}" = set; then : +if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then @@ -21911,7 +21921,7 @@ if test -z "$ac_cv_prog_AR"; then set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : +if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then @@ -22253,7 +22263,7 @@ if test "x$OPENJDK_TARGET_OS" = xwindows; then : set dummy link; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_WINLD+set}" = set; then : +if ${ac_cv_prog_WINLD+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$WINLD"; then @@ -22592,7 +22602,7 @@ $as_echo "yes" >&6; } set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_MT+set}" = set; then : +if ${ac_cv_prog_MT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MT"; then @@ -22913,7 +22923,7 @@ $as_echo "$as_me: Rewriting MT to \"$new_complete\"" >&6;} set dummy rc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_RC+set}" = set; then : +if ${ac_cv_prog_RC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RC"; then @@ -23304,7 +23314,7 @@ fi set dummy lib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_WINAR+set}" = set; then : +if ${ac_cv_prog_WINAR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$WINAR"; then @@ -23610,7 +23620,7 @@ $as_echo "$as_me: Rewriting WINAR to \"$new_complete\"" >&6;} set dummy dumpbin; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_DUMPBIN+set}" = set; then : +if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then @@ -23929,7 +23939,7 @@ if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then : + if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded @@ -24045,7 +24055,7 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=cpp @@ -24329,7 +24339,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then - if test "${ac_cv_prog_CXXCPP+set}" = set; then : + if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded @@ -24445,7 +24455,7 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=cpp @@ -24747,7 +24757,7 @@ if test "x$OPENJDK_TARGET_OS" = xsolaris; then set dummy as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_AS+set}" = set; then : +if ${ac_cv_path_AS+:} false; then : $as_echo_n "(cached) " >&6 else case $AS in @@ -25061,7 +25071,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_NM+set}" = set; then : +if ${ac_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else case $NM in @@ -25370,7 +25380,7 @@ $as_echo "$as_me: Rewriting NM to \"$new_complete\"" >&6;} set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_STRIP+set}" = set; then : +if ${ac_cv_path_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else case $STRIP in @@ -25676,7 +25686,7 @@ $as_echo "$as_me: Rewriting STRIP to \"$new_complete\"" >&6;} set dummy mcs; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_MCS+set}" = set; then : +if ${ac_cv_path_MCS+:} false; then : $as_echo_n "(cached) " >&6 else case $MCS in @@ -25984,7 +25994,7 @@ elif test "x$OPENJDK_TARGET_OS" != xwindows; then set dummy ${ac_tool_prefix}nm; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_NM+set}" = set; then : +if ${ac_cv_prog_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then @@ -26024,7 +26034,7 @@ if test -z "$ac_cv_prog_NM"; then set dummy nm; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_NM+set}" = set; then : +if ${ac_cv_prog_ac_ct_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NM"; then @@ -26342,7 +26352,7 @@ $as_echo "$as_me: Rewriting NM to \"$new_complete\"" >&6;} set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then : +if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then @@ -26382,7 +26392,7 @@ if test -z "$ac_cv_prog_STRIP"; then set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then @@ -26707,7 +26717,7 @@ if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OBJCOPY+set}" = set; then : +if ${ac_cv_prog_OBJCOPY+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJCOPY"; then @@ -26751,7 +26761,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OBJCOPY+set}" = set; then : +if ${ac_cv_prog_ac_ct_OBJCOPY+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJCOPY"; then @@ -27078,7 +27088,7 @@ if test -n "$ac_tool_prefix"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OBJDUMP+set}" = set; then : +if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then @@ -27122,7 +27132,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then : +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then @@ -27446,7 +27456,7 @@ if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_LIPO+set}" = set; then : +if ${ac_cv_path_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else case $LIPO in @@ -27761,7 +27771,7 @@ PATH="$OLD_PATH" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : +if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -27937,7 +27947,7 @@ fi for ac_header in stdio.h do : ac_fn_cxx_check_header_mongrel "$LINENO" "stdio.h" "ac_cv_header_stdio_h" "$ac_includes_default" -if test "x$ac_cv_header_stdio_h" = x""yes; then : +if test "x$ac_cv_header_stdio_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDIO_H 1 _ACEOF @@ -27966,7 +27976,7 @@ done # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int *" >&5 $as_echo_n "checking size of int *... " >&6; } -if test "${ac_cv_sizeof_int_p+set}" = set; then : +if ${ac_cv_sizeof_int_p+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (int *))" "ac_cv_sizeof_int_p" "$ac_includes_default"; then : @@ -27976,7 +27986,7 @@ else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (int *) -See \`config.log' for more details" "$LINENO" 5 ; } +See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_int_p=0 fi @@ -28023,7 +28033,7 @@ $as_echo "$OPENJDK_TARGET_CPU_BITS bits" >&6; } # { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } -if test "${ac_cv_c_bigendian+set}" = set; then : +if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown @@ -29034,8 +29044,8 @@ if test "x$with_x" = xno; then have_x=disabled else case $x_includes,$x_libraries in #( - *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5 ;; #( - *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then : + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : $as_echo_n "(cached) " >&6 else # One or both of the vars are not set, and there is no cached value. @@ -29312,7 +29322,7 @@ if ac_fn_cxx_try_link "$LINENO"; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } -if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then : +if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -29346,14 +29356,14 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } -if test "x$ac_cv_lib_dnet_dnet_ntoa" = x""yes; then : +if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } -if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then : +if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -29387,7 +29397,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } -if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = x""yes; then : +if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi @@ -29406,14 +29416,14 @@ rm -f core conftest.err conftest.$ac_objext \ # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. ac_fn_cxx_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" -if test "x$ac_cv_func_gethostbyname" = x""yes; then : +if test "x$ac_cv_func_gethostbyname" = xyes; then : fi if test $ac_cv_func_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; } -if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then : +if ${ac_cv_lib_nsl_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -29447,14 +29457,14 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 $as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } -if test "x$ac_cv_lib_nsl_gethostbyname" = x""yes; then : +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 $as_echo_n "checking for gethostbyname in -lbsd... " >&6; } -if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then : +if ${ac_cv_lib_bsd_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -29488,7 +29498,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 $as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } -if test "x$ac_cv_lib_bsd_gethostbyname" = x""yes; then : +if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi @@ -29503,14 +29513,14 @@ fi # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. ac_fn_cxx_check_func "$LINENO" "connect" "ac_cv_func_connect" -if test "x$ac_cv_func_connect" = x""yes; then : +if test "x$ac_cv_func_connect" = xyes; then : fi if test $ac_cv_func_connect = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 $as_echo_n "checking for connect in -lsocket... " >&6; } -if test "${ac_cv_lib_socket_connect+set}" = set; then : +if ${ac_cv_lib_socket_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -29544,7 +29554,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 $as_echo "$ac_cv_lib_socket_connect" >&6; } -if test "x$ac_cv_lib_socket_connect" = x""yes; then : +if test "x$ac_cv_lib_socket_connect" = xyes; then : X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi @@ -29552,14 +29562,14 @@ fi # Guillermo Gomez says -lposix is necessary on A/UX. ac_fn_cxx_check_func "$LINENO" "remove" "ac_cv_func_remove" -if test "x$ac_cv_func_remove" = x""yes; then : +if test "x$ac_cv_func_remove" = xyes; then : fi if test $ac_cv_func_remove = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 $as_echo_n "checking for remove in -lposix... " >&6; } -if test "${ac_cv_lib_posix_remove+set}" = set; then : +if ${ac_cv_lib_posix_remove+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -29593,7 +29603,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 $as_echo "$ac_cv_lib_posix_remove" >&6; } -if test "x$ac_cv_lib_posix_remove" = x""yes; then : +if test "x$ac_cv_lib_posix_remove" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi @@ -29601,14 +29611,14 @@ fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. ac_fn_cxx_check_func "$LINENO" "shmat" "ac_cv_func_shmat" -if test "x$ac_cv_func_shmat" = x""yes; then : +if test "x$ac_cv_func_shmat" = xyes; then : fi if test $ac_cv_func_shmat = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 $as_echo_n "checking for shmat in -lipc... " >&6; } -if test "${ac_cv_lib_ipc_shmat+set}" = set; then : +if ${ac_cv_lib_ipc_shmat+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -29642,7 +29652,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 $as_echo "$ac_cv_lib_ipc_shmat" >&6; } -if test "x$ac_cv_lib_ipc_shmat" = x""yes; then : +if test "x$ac_cv_lib_ipc_shmat" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi @@ -29660,7 +29670,7 @@ fi # John Interrante, Karl Berry { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 $as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } -if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then : +if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -29694,7 +29704,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 $as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } -if test "x$ac_cv_lib_ICE_IceConnectionNumber" = x""yes; then : +if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then : X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi @@ -30707,7 +30717,7 @@ $as_echo "$FREETYPE2_FOUND" >&6; } LDFLAGS="$FREETYPE2_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FT_Init_FreeType in -lfreetype" >&5 $as_echo_n "checking for FT_Init_FreeType in -lfreetype... " >&6; } -if test "${ac_cv_lib_freetype_FT_Init_FreeType+set}" = set; then : +if ${ac_cv_lib_freetype_FT_Init_FreeType+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -30741,7 +30751,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_freetype_FT_Init_FreeType" >&5 $as_echo "$ac_cv_lib_freetype_FT_Init_FreeType" >&6; } -if test "x$ac_cv_lib_freetype_FT_Init_FreeType" = x""yes; then : +if test "x$ac_cv_lib_freetype_FT_Init_FreeType" = xyes; then : FREETYPE2_FOUND=true else as_fn_error $? "Could not find freetype2! $HELP_MSG " "$LINENO" 5 @@ -31029,7 +31039,7 @@ fi for ac_header in alsa/asoundlib.h do : ac_fn_cxx_check_header_mongrel "$LINENO" "alsa/asoundlib.h" "ac_cv_header_alsa_asoundlib_h" "$ac_includes_default" -if test "x$ac_cv_header_alsa_asoundlib_h" = x""yes; then : +if test "x$ac_cv_header_alsa_asoundlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ALSA_ASOUNDLIB_H 1 _ACEOF @@ -31088,7 +31098,7 @@ fi USE_EXTERNAL_LIBJPEG=true { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ljpeg" >&5 $as_echo_n "checking for main in -ljpeg... " >&6; } -if test "${ac_cv_lib_jpeg_main+set}" = set; then : +if ${ac_cv_lib_jpeg_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -31116,7 +31126,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_main" >&5 $as_echo "$ac_cv_lib_jpeg_main" >&6; } -if test "x$ac_cv_lib_jpeg_main" = x""yes; then : +if test "x$ac_cv_lib_jpeg_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBJPEG 1 _ACEOF @@ -31140,7 +31150,7 @@ fi USE_EXTERNAL_LIBJPEG=true { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lgif" >&5 $as_echo_n "checking for main in -lgif... " >&6; } -if test "${ac_cv_lib_gif_main+set}" = set; then : +if ${ac_cv_lib_gif_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -31168,7 +31178,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gif_main" >&5 $as_echo "$ac_cv_lib_gif_main" >&6; } -if test "x$ac_cv_lib_gif_main" = x""yes; then : +if test "x$ac_cv_lib_gif_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBGIF 1 _ACEOF @@ -31198,7 +31208,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compress in -lz" >&5 $as_echo_n "checking for compress in -lz... " >&6; } -if test "${ac_cv_lib_z_compress+set}" = set; then : +if ${ac_cv_lib_z_compress+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -31232,7 +31242,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress" >&5 $as_echo "$ac_cv_lib_z_compress" >&6; } -if test "x$ac_cv_lib_z_compress" = x""yes; then : +if test "x$ac_cv_lib_z_compress" = xyes; then : ZLIB_FOUND=yes else ZLIB_FOUND=no @@ -31325,7 +31335,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 $as_echo_n "checking for cos in -lm... " >&6; } -if test "${ac_cv_lib_m_cos+set}" = set; then : +if ${ac_cv_lib_m_cos+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -31359,7 +31369,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 $as_echo "$ac_cv_lib_m_cos" >&6; } -if test "x$ac_cv_lib_m_cos" = x""yes; then : +if test "x$ac_cv_lib_m_cos" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF @@ -31383,7 +31393,7 @@ save_LIBS="$LIBS" LIBS="" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then : +if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -31417,7 +31427,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDL 1 _ACEOF @@ -32091,7 +32101,7 @@ fi set dummy ccache; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_CCACHE+set}" = set; then : +if ${ac_cv_path_CCACHE+:} false; then : $as_echo_n "(cached) " >&6 else case $CCACHE in @@ -32352,10 +32362,21 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && + if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} @@ -32387,7 +32408,7 @@ LTLIBOBJS=$ac_ltlibobjs -: ${CONFIG_STATUS=./config.status} +: "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" @@ -32488,6 +32509,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -32795,7 +32817,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # values after options handling. ac_log=" This file was extended by OpenJDK $as_me jdk8, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -32858,7 +32880,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ OpenJDK config.status jdk8 -configured by $0, generated by GNU Autoconf 2.67, +configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. @@ -32987,7 +33009,7 @@ do "$OUTPUT_ROOT/spec.sh") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/spec.sh:$AUTOCONF_DIR/spec.sh.in" ;; "$OUTPUT_ROOT/Makefile") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/Makefile:$AUTOCONF_DIR/Makefile.in" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -33009,9 +33031,10 @@ fi # after its creation but before its name has been assigned to `$tmp'. $debug || { - tmp= + tmp= ac_tmp= trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } @@ -33019,12 +33042,13 @@ $debug || { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" + test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -33046,7 +33070,7 @@ else ac_cs_awk_cr=$ac_cr fi -echo 'BEGIN {' >"$tmp/subs1.awk" && +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF @@ -33074,7 +33098,7 @@ done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h @@ -33122,7 +33146,7 @@ t delim rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" @@ -33154,7 +33178,7 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF @@ -33188,7 +33212,7 @@ fi # test -n "$CONFIG_FILES" # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then -cat >"$tmp/defines.awk" <<\_ACAWK || +cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF @@ -33200,8 +33224,8 @@ _ACEOF # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do - ac_t=`sed -n "/$ac_delim/p" confdefs.h` - if test -z "$ac_t"; then + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 @@ -33302,7 +33326,7 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -33321,7 +33345,7 @@ do for ac_f do case $ac_f in - -) ac_f="$tmp/stdin";; + -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. @@ -33330,7 +33354,7 @@ do [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -33356,8 +33380,8 @@ $as_echo "$as_me: creating $ac_file" >&6;} esac case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -33482,21 +33506,22 @@ s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} - rm -f "$tmp/stdin" + rm -f "$ac_tmp/stdin" case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; @@ -33507,20 +33532,20 @@ which seems to be undefined. Please make sure it is defined" >&2;} if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" - } >"$tmp/config.h" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" - mv "$tmp/config.h" "$ac_file" \ + mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; diff --git a/common/autoconf/toolchain_windows.m4 b/common/autoconf/toolchain_windows.m4 index dd093fdbc12..700339a9e17 100644 --- a/common/autoconf/toolchain_windows.m4 +++ b/common/autoconf/toolchain_windows.m4 @@ -280,6 +280,8 @@ AC_DEFUN([TOOLCHAIN_SETUP_DXSDK], dxsdk_path="$with_dxsdk" elif test "x$DXSDK_DIR" != x; then dxsdk_path="$DXSDK_DIR" + elif test -d "C:/DXSDK"; then + dxsdk_path="C:/DXSDK" else AC_MSG_ERROR([Could not find the DirectX SDK]) fi From 3a5d99bd97eaef4a12eacbf523c49ff729bab481 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:43:10 +0200 Subject: [PATCH 101/102] Added tag jdk8-b80 for changeset 3fa21fbf9be7 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 5f401115308..11f22d17598 100644 --- a/.hgtags +++ b/.hgtags @@ -201,3 +201,4 @@ f407160c280d1c5b00d314c535441ac26f195fee jdk8-b76 d17eb2e13e362085e866d46235314c50cc4661cc jdk8-b77 6d3dcd34b5b962ea1ef9eed0dafdee9e812401bc jdk8-b78 a1313a8d90d17d363a3b2a645dc4030ec204b168 jdk8-b79 +3fa21fbf9be7e6b482af43aacb6a09acfa30bdb6 jdk8-b80 From 4e8c9ce3082e9d5d00d093a374d6c6ac32e18fd7 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 14 Mar 2013 15:00:33 -0700 Subject: [PATCH 102/102] Added tag jdk8-b81 for changeset 86a86261de2b --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index fbd3f71e449..92fe10a1d9a 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -202,3 +202,4 @@ b2fc8e31cecc35b76188e821d4c5dc0e0b74ac24 jdk8-b77 00b7535d743f83eda763c10b3c9ea19ba4b67f55 jdk8-b78 c933505d75c2a0a671f06d6dac5d2237a9228d2d jdk8-b79 dfb40f066c6ce129822f0f5dc2ac89173808781a jdk8-b80 +c0f8022eba536dcdc8aae659005b33f3982b9368 jdk8-b81