From 7b9d6a79ac6d6edf7a713f4db6266a2ecde1db76 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 9 Jun 2009 16:19:10 -0700 Subject: [PATCH 01/61] 6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14 Disable escape analysis when jvmti/debugger is used. Add support for EA ibto SA. Reviewed-by: never --- .../jvm/hotspot/code/DebugInfoReadStream.java | 41 ++++++++ .../sun/jvm/hotspot/code/MonitorValue.java | 6 ++ .../sun/jvm/hotspot/code/ObjectValue.java | 93 +++++++++++++++++++ .../sun/jvm/hotspot/code/ScopeDesc.java | 48 +++++++++- .../sun/jvm/hotspot/code/ScopeValue.java | 7 ++ .../jvm/hotspot/jdi/ObjectReferenceImpl.java | 1 + .../jvm/hotspot/jdi/ThreadReferenceImpl.java | 3 + .../jvm/hotspot/runtime/CompiledVFrame.java | 25 +++-- .../hotspot/runtime/InterpretedVFrame.java | 6 +- .../sun/jvm/hotspot/runtime/MonitorInfo.java | 31 ++++++- .../sun/jvm/hotspot/runtime/StackValue.java | 11 ++- .../hotspot/utilities/soql/JSJavaThread.java | 4 + hotspot/src/share/vm/opto/c2compiler.cpp | 4 +- hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 3 + .../src/share/vm/runtime/biasedLocking.cpp | 2 + .../src/share/vm/runtime/deoptimization.cpp | 2 +- hotspot/src/share/vm/runtime/stackValue.cpp | 5 +- hotspot/src/share/vm/runtime/stackValue.hpp | 9 +- hotspot/src/share/vm/runtime/vframe.cpp | 37 ++++++-- hotspot/src/share/vm/runtime/vframe.hpp | 24 ++++- hotspot/src/share/vm/runtime/vframeArray.cpp | 3 + hotspot/src/share/vm/runtime/vframe_hp.cpp | 18 +++- 22 files changed, 350 insertions(+), 33 deletions(-) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ObjectValue.java diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java index 2fc3155fa91..fa60c49839b 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java @@ -24,23 +24,64 @@ package sun.jvm.hotspot.code; +import java.util.*; + import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.utilities.*; public class DebugInfoReadStream extends CompressedReadStream { private NMethod code; private int InvocationEntryBCI; + private List objectPool; // ArrayList public DebugInfoReadStream(NMethod code, int offset) { super(code.scopesDataBegin(), offset); InvocationEntryBCI = VM.getVM().getInvocationEntryBCI(); this.code = code; + this.objectPool = null; + } + + public DebugInfoReadStream(NMethod code, int offset, List objectPool) { + super(code.scopesDataBegin(), offset); + InvocationEntryBCI = VM.getVM().getInvocationEntryBCI(); + this.code = code; + this.objectPool = objectPool; } public OopHandle readOopHandle() { return code.getOopAt(readInt()); } + ScopeValue readObjectValue() { + int id = readInt(); + if (Assert.ASSERTS_ENABLED) { + Assert.that(objectPool != null, "object pool does not exist"); + for (Iterator itr = objectPool.iterator(); itr.hasNext();) { + ObjectValue ov = (ObjectValue) itr.next(); + Assert.that(ov.id() != id, "should not be read twice"); + } + } + ObjectValue result = new ObjectValue(id); + // Cache the object since an object field could reference it. + objectPool.add(result); + result.readObject(this); + return result; + } + + ScopeValue getCachedObject() { + int id = readInt(); + Assert.that(objectPool != null, "object pool does not exist"); + for (Iterator itr = objectPool.iterator(); itr.hasNext();) { + ObjectValue ov = (ObjectValue) itr.next(); + if (ov.id() == id) { + return ov; + } + } + Assert.that(false, "should not reach here"); + return null; + } + public int readBCI() { return readInt() + InvocationEntryBCI; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MonitorValue.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MonitorValue.java index cf539d311c8..43937fc690a 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MonitorValue.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MonitorValue.java @@ -29,6 +29,7 @@ import java.io.*; public class MonitorValue { private ScopeValue owner; private Location basicLock; + private boolean eliminated; // FIXME: not useful yet // MonitorValue(ScopeValue* owner, Location basic_lock); @@ -36,10 +37,12 @@ public class MonitorValue { public MonitorValue(DebugInfoReadStream stream) { basicLock = new Location(stream); owner = ScopeValue.readFrom(stream); + eliminated= stream.readBoolean(); } public ScopeValue owner() { return owner; } public Location basicLock() { return basicLock; } + public boolean eliminated() { return eliminated; } // FIXME: not yet implementable // void write_on(DebugInfoWriteStream* stream); @@ -50,5 +53,8 @@ public class MonitorValue { tty.print(","); basicLock().printOn(tty); tty.print("}"); + if (eliminated) { + tty.print(" (eliminated)"); + } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ObjectValue.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ObjectValue.java new file mode 100644 index 00000000000..1c38103faf3 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ObjectValue.java @@ -0,0 +1,93 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.code; + +import java.io.*; +import java.util.*; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.utilities.*; + +/** An ObjectValue describes an object eliminated by escape analysis. */ + +public class ObjectValue extends ScopeValue { + private int id; + private ScopeValue klass; + private List fieldsValue; // ArrayList + + // Field "boolean visited" is not implemented here since + // it is used only a during debug info creation. + + public ObjectValue(int id) { + this.id = id; + klass = null; + fieldsValue = new ArrayList(); + } + + public boolean isObject() { return true; } + public int id() { return id; } + public ScopeValue getKlass() { return klass; } + public List getFieldsValue() { return fieldsValue; } + public ScopeValue getFieldAt(int i) { return (ScopeValue)fieldsValue.get(i); } + public int fieldsSize() { return fieldsValue.size(); } + + // Field "value" is always NULL here since it is used + // only during deoptimization of a compiled frame + // pointing to reallocated object. + public OopHandle getValue() { return null; } + + /** Serialization of debugging information */ + + void readObject(DebugInfoReadStream stream) { + klass = readFrom(stream); + Assert.that(klass.isConstantOop(), "should be constant klass oop"); + int length = stream.readInt(); + for (int i = 0; i < length; i++) { + ScopeValue val = readFrom(stream); + fieldsValue.add(val); + } + } + + // Printing + + public void print() { + printOn(System.out); + } + + public void printOn(PrintStream tty) { + tty.print("scalarObj[" + id + "]"); + } + + void printFieldsOn(PrintStream tty) { + if (fieldsValue.size() > 0) { + ((ScopeValue)fieldsValue.get(0)).printOn(tty); + } + for (int i = 1; i < fieldsValue.size(); i++) { + tty.print(", "); + ((ScopeValue)fieldsValue.get(i)).printOn(tty); + } + } + +}; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java index b4d2d592d58..e75365ae226 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java @@ -27,8 +27,10 @@ package sun.jvm.hotspot.code; import java.io.*; import java.util.*; +import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.utilities.*; /** ScopeDescs contain the information that makes source-level debugging of nmethods possible; each scopeDesc describes a method @@ -45,10 +47,31 @@ public class ScopeDesc { private int localsDecodeOffset; private int expressionsDecodeOffset; private int monitorsDecodeOffset; + /** Scalar replaced bjects pool */ + private List objects; // ArrayList + public ScopeDesc(NMethod code, int decodeOffset) { this.code = code; this.decodeOffset = decodeOffset; + this.objects = decodeObjectValues(DebugInformationRecorder.SERIALIZED_NULL); + + // Decode header + DebugInfoReadStream stream = streamAt(decodeOffset); + + senderDecodeOffset = stream.readInt(); + method = (Method) VM.getVM().getObjectHeap().newOop(stream.readOopHandle()); + bci = stream.readBCI(); + // Decode offsets for body and sender + localsDecodeOffset = stream.readInt(); + expressionsDecodeOffset = stream.readInt(); + monitorsDecodeOffset = stream.readInt(); + } + + public ScopeDesc(NMethod code, int decodeOffset, int objectDecodeOffset) { + this.code = code; + this.decodeOffset = decodeOffset; + this.objects = decodeObjectValues(objectDecodeOffset); // Decode header DebugInfoReadStream stream = streamAt(decodeOffset); @@ -81,6 +104,11 @@ public class ScopeDesc { return decodeMonitorValues(monitorsDecodeOffset); } + /** Returns a List<MonitorValue> */ + public List getObjects() { + return objects; + } + /** Stack walking. Returns null if this is the outermost scope. */ public ScopeDesc sender() { if (isTop()) { @@ -131,7 +159,7 @@ public class ScopeDesc { // private DebugInfoReadStream streamAt(int decodeOffset) { - return new DebugInfoReadStream(code, decodeOffset); + return new DebugInfoReadStream(code, decodeOffset, objects); } /** Returns a List<ScopeValue> or null if no values were present */ @@ -161,4 +189,22 @@ public class ScopeDesc { } return res; } + + /** Returns a List<ObjectValue> or null if no values were present */ + private List decodeObjectValues(int decodeOffset) { + if (decodeOffset == DebugInformationRecorder.SERIALIZED_NULL) { + return null; + } + List res = new ArrayList(); + DebugInfoReadStream stream = new DebugInfoReadStream(code, decodeOffset, res); + int length = stream.readInt(); + for (int i = 0; i < length; i++) { + // Objects values are pushed to 'res' array during read so that + // object's fields could reference it (OBJECT_ID_CODE). + ScopeValue.readFrom(stream); + // res.add(ScopeValue.readFrom(stream)); + } + Assert.that(res.size() == length, "inconsistent debug information"); + return res; + } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeValue.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeValue.java index f9c99d3d4ce..71166a706b1 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeValue.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeValue.java @@ -49,12 +49,15 @@ public abstract class ScopeValue { static final int CONSTANT_OOP_CODE = 2; static final int CONSTANT_LONG_CODE = 3; static final int CONSTANT_DOUBLE_CODE = 4; + static final int CONSTANT_OBJECT_CODE = 5; + static final int CONSTANT_OBJECT_ID_CODE = 6; public boolean isLocation() { return false; } public boolean isConstantInt() { return false; } public boolean isConstantDouble() { return false; } public boolean isConstantLong() { return false; } public boolean isConstantOop() { return false; } + public boolean isObject() { return false; } public static ScopeValue readFrom(DebugInfoReadStream stream) { switch (stream.readInt()) { @@ -68,6 +71,10 @@ public abstract class ScopeValue { return new ConstantLongValue(stream); case CONSTANT_DOUBLE_CODE: return new ConstantDoubleValue(stream); + case CONSTANT_OBJECT_CODE: + return stream.readObjectValue(); + case CONSTANT_OBJECT_ID_CODE: + return stream.getCachedObject(); default: Assert.that(false, "should not reach here"); return null; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ObjectReferenceImpl.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ObjectReferenceImpl.java index 4911915c7f0..b469bde96b6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ObjectReferenceImpl.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ObjectReferenceImpl.java @@ -249,6 +249,7 @@ public class ObjectReferenceImpl extends ValueImpl implements ObjectReference { OopHandle givenHandle = obj.getHandle(); for (Iterator itr = monitors.iterator(); itr.hasNext();) { MonitorInfo mi = (MonitorInfo) itr.next(); + if (mi.eliminated() && frame.isCompiledFrame()) continue; // skip eliminated monitor if (givenHandle.equals(mi.owner())) { res++; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ThreadReferenceImpl.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ThreadReferenceImpl.java index 87dfc191f11..7ae8675f48a 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ThreadReferenceImpl.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ThreadReferenceImpl.java @@ -301,6 +301,9 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl List frameMonitors = frame.getMonitors(); // List for (Iterator miItr = frameMonitors.iterator(); miItr.hasNext(); ) { sun.jvm.hotspot.runtime.MonitorInfo mi = (sun.jvm.hotspot.runtime.MonitorInfo) miItr.next(); + if (mi.eliminated() && frame.isCompiledFrame()) { + continue; // skip eliminated monitor + } OopHandle obj = mi.owner(); if (obj == null) { // this monitor doesn't have an owning object so skip it diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java index 1642fefe2cb..6588da2e8bd 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java @@ -131,8 +131,18 @@ public class CompiledVFrame extends JavaVFrame { List result = new ArrayList(monitors.size()); for (int i = 0; i < monitors.size(); i++) { MonitorValue mv = (MonitorValue) monitors.get(i); - StackValue ownerSV = createStackValue(mv.owner()); // it is an oop - result.add(new MonitorInfo(ownerSV.getObject(), resolveMonitorLock(mv.basicLock()))); + ScopeValue ov = mv.owner(); + StackValue ownerSV = createStackValue(ov); // it is an oop + if (ov.isObject()) { // The owner object was scalar replaced + Assert.that(mv.eliminated() && ownerSV.objIsScalarReplaced(), "monitor should be eliminated for scalar replaced object"); + // Put klass for scalar replaced object. + ScopeValue kv = ((ObjectValue)ov).getKlass(); + Assert.that(kv.isConstantOop(), "klass should be oop constant for scalar replaced object"); + OopHandle k = ((ConstantOopReadValue)kv).getValue(); + result.add(new MonitorInfo(k, resolveMonitorLock(mv.basicLock()), mv.eliminated(), true)); + } else { + result.add(new MonitorInfo(ownerSV.getObject(), resolveMonitorLock(mv.basicLock()), mv.eliminated(), false)); + } } return result; } @@ -212,12 +222,12 @@ public class CompiledVFrame extends JavaVFrame { // long or is unused. He always saves a long. Here we know // a long was saved, but we only want an narrow oop back. Narrow the // saved long to the narrow oop that the JVM wants. - return new StackValue(valueAddr.getCompOopHandleAt(VM.getVM().getIntSize())); + return new StackValue(valueAddr.getCompOopHandleAt(VM.getVM().getIntSize()), 0); } else { - return new StackValue(valueAddr.getCompOopHandleAt(0)); + return new StackValue(valueAddr.getCompOopHandleAt(0), 0); } } else if( loc.holdsOop() ) { // Holds an oop? - return new StackValue(valueAddr.getOopHandleAt(0)); + return new StackValue(valueAddr.getOopHandleAt(0), 0); } else if( loc.holdsDouble() ) { // Double value in a single stack slot return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); @@ -277,7 +287,7 @@ public class CompiledVFrame extends JavaVFrame { return new StackValue(((ConstantIntValue) sv).getValue() & 0xFFFFFFFF); } else if (sv.isConstantOop()) { // constant oop - return new StackValue(((ConstantOopReadValue) sv).getValue()); + return new StackValue(((ConstantOopReadValue) sv).getValue(), 0); } else if (sv.isConstantDouble()) { // Constant double in a single stack slot double d = ((ConstantDoubleValue) sv).getValue(); @@ -285,6 +295,9 @@ public class CompiledVFrame extends JavaVFrame { } else if (VM.getVM().isLP64() && sv.isConstantLong()) { // Constant long in a single stack slot return new StackValue(((ConstantLongValue) sv).getValue() & 0xFFFFFFFF); + } else if (sv.isObject()) { + // Scalar replaced object in compiled frame + return new StackValue(((ObjectValue)sv).getValue(), 1); } // Unknown ScopeValue type diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java index ff5ad46c355..f86e4f7a2c5 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java @@ -61,7 +61,7 @@ public class InterpretedVFrame extends JavaVFrame { StackValue sv; if (oopMask.isOop(i)) { // oop value - sv = new StackValue(addr.getOopHandleAt(0)); + sv = new StackValue(addr.getOopHandleAt(0), 0); } else { // integer // Fetch a signed integer the size of a stack slot @@ -95,7 +95,7 @@ public class InterpretedVFrame extends JavaVFrame { StackValue sv; if (oopMask.isOop(i + nofLocals)) { // oop value - sv = new StackValue(addr.getOopHandleAt(0)); + sv = new StackValue(addr.getOopHandleAt(0), 0); } else { // integer // Fetch a signed integer the size of a stack slot @@ -113,7 +113,7 @@ public class InterpretedVFrame extends JavaVFrame { for (BasicObjectLock current = getFrame().interpreterFrameMonitorEnd(); current.address().lessThan(getFrame().interpreterFrameMonitorBegin().address()); current = getFrame().nextMonitorInInterpreterFrame(current)) { - result.add(new MonitorInfo(current.obj(), current.lock())); + result.add(new MonitorInfo(current.obj(), current.lock(), false, false)); } return result; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/MonitorInfo.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/MonitorInfo.java index d689d43597c..d4801fa05f6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/MonitorInfo.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/MonitorInfo.java @@ -25,16 +25,39 @@ package sun.jvm.hotspot.runtime; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.utilities.*; public class MonitorInfo { private OopHandle owner; private BasicLock lock; + private OopHandle ownerKlass; + private boolean eliminated; + private boolean ownerIsScalarReplaced; - public MonitorInfo(OopHandle owner, BasicLock lock) { - this.owner = owner; - this.lock = lock; + public MonitorInfo(OopHandle owner, BasicLock lock, boolean eliminated, boolean ownerIsScalarReplaced) { + if (!ownerIsScalarReplaced) { + this.owner = owner; + this.ownerKlass = null; + } else { + Assert.that(eliminated, "monitor should be eliminated for scalar replaced object"); + this.owner = null; + this.ownerKlass = owner; + } + this.eliminated = eliminated; + this.ownerIsScalarReplaced = ownerIsScalarReplaced; + } + + public OopHandle owner() { + Assert.that(!ownerIsScalarReplaced, "should not be called for scalar replaced object"); + return owner; + } + + public OopHandle ownerKlass() { + Assert.that(ownerIsScalarReplaced, "should not be called for not scalar replaced object"); + return ownerKlass; } - public OopHandle owner() { return owner; } public BasicLock lock() { return lock; } + public boolean eliminated() { return eliminated; } + public boolean ownerIsScalarReplaced() { return ownerIsScalarReplaced; } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java index 246b7098c77..98becd01816 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java @@ -37,9 +37,11 @@ public class StackValue { type = BasicType.getTConflict(); } - public StackValue(OopHandle h) { + public StackValue(OopHandle h, long scalar_replaced) { handleValue = h; type = BasicType.getTObject(); + integerValue = scalar_replaced; + Assert.that(integerValue == 0 || handleValue == null, "not null object should not be marked as scalar replaced"); } public StackValue(long i) { @@ -59,6 +61,13 @@ public class StackValue { return handleValue; } + boolean objIsScalarReplaced() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(type == BasicType.getTObject(), "type check"); + } + return integerValue != 0; + } + public long getInteger() { if (Assert.ASSERTS_ENABLED) { Assert.that(type == BasicType.getTInt(), "type check"); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaThread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaThread.java index 40402b5a3a8..b8fce3abdbf 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaThread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaThread.java @@ -135,6 +135,10 @@ public class JSJavaThread extends JSJavaInstance { List frameMonitors = frame.getMonitors(); // List for (Iterator miItr = frameMonitors.iterator(); miItr.hasNext(); ) { MonitorInfo mi = (MonitorInfo) miItr.next(); + + if (mi.eliminated() && frame.isCompiledFrame()) { + continue; // skip eliminated monitor + } OopHandle obj = mi.owner(); if (obj == null) { // this monitor doesn't have an owning object so skip it diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index 6be045c8078..22509077fbb 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -104,7 +104,9 @@ void C2Compiler::compile_method(ciEnv* env, initialize(); } bool subsume_loads = true; - bool do_escape_analysis = DoEscapeAnalysis; + bool do_escape_analysis = DoEscapeAnalysis && + !(env->jvmti_can_hotswap_or_post_breakpoint() || + env->jvmti_can_examine_or_deopt_anywhere()); while (!env->failing()) { // Attempt to compile while subsuming loads into machine instructions. Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis); diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index c0c98f01e53..142b60c54e4 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -606,6 +606,7 @@ JvmtiEnvBase::count_locked_objects(JavaThread *java_thread, Handle hobj) { if (!mons->is_empty()) { for (int i = 0; i < mons->length(); i++) { MonitorInfo *mi = mons->at(i); + if (mi->owner_is_scalar_replaced()) continue; // see if owner of the monitor is our object if (mi->owner() != NULL && mi->owner() == hobj()) { @@ -726,6 +727,8 @@ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread for (int i = 0; i < mons->length(); i++) { MonitorInfo *mi = mons->at(i); + if (mi->owner_is_scalar_replaced()) continue; + oop obj = mi->owner(); if (obj == NULL) { // this monitor doesn't have an owning object so skip it diff --git a/hotspot/src/share/vm/runtime/biasedLocking.cpp b/hotspot/src/share/vm/runtime/biasedLocking.cpp index 21d2ea7da87..ddc7305c77f 100644 --- a/hotspot/src/share/vm/runtime/biasedLocking.cpp +++ b/hotspot/src/share/vm/runtime/biasedLocking.cpp @@ -121,6 +121,7 @@ static GrowableArray* get_or_compute_monitor_info(JavaThread* thre // Walk monitors youngest to oldest for (int i = len - 1; i >= 0; i--) { MonitorInfo* mon_info = monitors->at(i); + if (mon_info->owner_is_scalar_replaced()) continue; oop owner = mon_info->owner(); if (owner != NULL) { info->append(mon_info); @@ -694,6 +695,7 @@ void BiasedLocking::preserve_marks() { // Walk monitors youngest to oldest for (int i = len - 1; i >= 0; i--) { MonitorInfo* mon_info = monitors->at(i); + if (mon_info->owner_is_scalar_replaced()) continue; oop owner = mon_info->owner(); if (owner != NULL) { markOop mark = owner->mark(); diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index e18f38ef6c5..586f4f5fd2f 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -933,7 +933,7 @@ static void collect_monitors(compiledVFrame* cvf, GrowableArray* objects GrowableArray* monitors = cvf->monitors(); for (int i = 0; i < monitors->length(); i++) { MonitorInfo* mon_info = monitors->at(i); - if (mon_info->owner() != NULL && !mon_info->eliminated()) { + if (!mon_info->eliminated() && mon_info->owner() != NULL) { objects_to_revoke->append(Handle(mon_info->owner())); } } diff --git a/hotspot/src/share/vm/runtime/stackValue.cpp b/hotspot/src/share/vm/runtime/stackValue.cpp index b6b2e359acf..9f3fb0f0ec3 100644 --- a/hotspot/src/share/vm/runtime/stackValue.cpp +++ b/hotspot/src/share/vm/runtime/stackValue.cpp @@ -146,8 +146,9 @@ StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* r value.jl = ((ConstantLongValue *)sv)->value(); return new StackValue(value.p); #endif - } else if (sv->is_object()) { - return new StackValue(((ObjectValue *)sv)->value()); + } else if (sv->is_object()) { // Scalar replaced object in compiled frame + Handle ov = ((ObjectValue *)sv)->value(); + return new StackValue(ov, (ov.is_null()) ? 1 : 0); } // Unknown ScopeValue type diff --git a/hotspot/src/share/vm/runtime/stackValue.hpp b/hotspot/src/share/vm/runtime/stackValue.hpp index 6296b8073a4..1715ec65b20 100644 --- a/hotspot/src/share/vm/runtime/stackValue.hpp +++ b/hotspot/src/share/vm/runtime/stackValue.hpp @@ -34,9 +34,11 @@ class StackValue : public ResourceObj { _i = value; } - StackValue(Handle value) { + StackValue(Handle value, intptr_t scalar_replaced = 0) { _type = T_OBJECT; + _i = scalar_replaced; _o = value; + assert(_i == 0 || _o.is_null(), "not null object should not be marked as scalar replaced"); } StackValue() { @@ -56,6 +58,11 @@ class StackValue : public ResourceObj { return _o; } + bool obj_is_scalar_replaced() const { + assert(type() == T_OBJECT, "type check"); + return _i != 0; + } + void set_obj(Handle value) { assert(type() == T_OBJECT, "type check"); _o = value; diff --git a/hotspot/src/share/vm/runtime/vframe.cpp b/hotspot/src/share/vm/runtime/vframe.cpp index 6474e6fabf8..64215384091 100644 --- a/hotspot/src/share/vm/runtime/vframe.cpp +++ b/hotspot/src/share/vm/runtime/vframe.cpp @@ -106,6 +106,7 @@ GrowableArray* javaVFrame::locked_monitors() { for (int index = (mons->length()-1); index >= 0; index--) { MonitorInfo* monitor = mons->at(index); + if (monitor->eliminated() && is_compiled_frame()) continue; // skip eliminated monitor oop obj = monitor->owner(); if (obj == NULL) continue; // skip unowned monitor // @@ -162,6 +163,18 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { bool found_first_monitor = false; for (int index = (mons->length()-1); index >= 0; index--) { MonitorInfo* monitor = mons->at(index); + if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code + if (monitor->owner_is_scalar_replaced()) { + Klass* k = Klass::cast(monitor->owner_klass()); + st->print("\t- eliminated (a %s)", k->external_name()); + } else { + oop obj = monitor->owner(); + if (obj != NULL) { + print_locked_object_class_name(st, obj, "eliminated"); + } + } + continue; + } if (monitor->owner() != NULL) { // First, assume we have the monitor locked. If we haven't found an @@ -171,11 +184,11 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { const char *lock_state = "locked"; // assume we have the monitor locked if (!found_first_monitor && frame_count == 0) { - markOop mark = monitor->owner()->mark(); - if (mark->has_monitor() && - mark->monitor() == thread()->current_pending_monitor()) { + markOop mark = monitor->owner()->mark(); + if (mark->has_monitor() && + mark->monitor() == thread()->current_pending_monitor()) { lock_state = "waiting to lock"; - } + } } found_first_monitor = true; @@ -206,7 +219,7 @@ GrowableArray* interpretedVFrame::monitors() const { for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin())); current >= fr().interpreter_frame_monitor_end(); current = fr().previous_monitor_in_interpreter_frame(current)) { - result->push(new MonitorInfo(current->obj(), current->lock(), false)); + result->push(new MonitorInfo(current->obj(), current->lock(), false, false)); } return result; } @@ -531,8 +544,18 @@ void javaVFrame::print() { tty->print_cr("\tmonitor list:"); for (int index = (list->length()-1); index >= 0; index--) { MonitorInfo* monitor = list->at(index); - tty->print("\t obj\t"); monitor->owner()->print_value(); - tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner()); + tty->print("\t obj\t"); + if (monitor->owner_is_scalar_replaced()) { + Klass* k = Klass::cast(monitor->owner_klass()); + tty->print("( is scalar replaced %s)", k->external_name()); + } else if (monitor->owner() == NULL) { + tty->print("( null )"); + } else { + monitor->owner()->print_value(); + tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner()); + } + if (monitor->eliminated() && is_compiled_frame()) + tty->print(" ( lock is eliminated )"); tty->cr(); tty->print("\t "); monitor->lock()->print_on(tty); diff --git a/hotspot/src/share/vm/runtime/vframe.hpp b/hotspot/src/share/vm/runtime/vframe.hpp index febfb02cb46..2924aeae983 100644 --- a/hotspot/src/share/vm/runtime/vframe.hpp +++ b/hotspot/src/share/vm/runtime/vframe.hpp @@ -230,18 +230,36 @@ class MonitorInfo : public ResourceObj { private: oop _owner; // the object owning the monitor BasicLock* _lock; + oop _owner_klass; // klass if owner was scalar replaced bool _eliminated; + bool _owner_is_scalar_replaced; public: // Constructor - MonitorInfo(oop owner, BasicLock* lock, bool eliminated) { - _owner = owner; + MonitorInfo(oop owner, BasicLock* lock, bool eliminated, bool owner_is_scalar_replaced) { + if (!owner_is_scalar_replaced) { + _owner = owner; + _owner_klass = NULL; + } else { + assert(eliminated, "monitor should be eliminated for scalar replaced object"); + _owner = NULL; + _owner_klass = owner; + } _lock = lock; _eliminated = eliminated; + _owner_is_scalar_replaced = owner_is_scalar_replaced; } // Accessors - oop owner() const { return _owner; } + oop owner() const { + assert(!_owner_is_scalar_replaced, "should not be called for scalar replaced object"); + return _owner; + } + klassOop owner_klass() const { + assert(_owner_is_scalar_replaced, "should not be called for not scalar replaced object"); + return (klassOop)_owner_klass; + } BasicLock* lock() const { return _lock; } bool eliminated() const { return _eliminated; } + bool owner_is_scalar_replaced() const { return _owner_is_scalar_replaced; } }; class vframeStreamCommon : StackObj { diff --git a/hotspot/src/share/vm/runtime/vframeArray.cpp b/hotspot/src/share/vm/runtime/vframeArray.cpp index 84130636685..60a2a23b737 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.cpp +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp @@ -61,6 +61,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) { // Migrate the BasicLocks from the stack to the monitor chunk for (index = 0; index < list->length(); index++) { MonitorInfo* monitor = list->at(index); + assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already"); assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased"); BasicObjectLock* dest = _monitors->at(index); dest->set_obj(monitor->owner()); @@ -89,6 +90,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) { StackValue* value = locs->at(index); switch(value->type()) { case T_OBJECT: + assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); // preserve object type _locals->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); break; @@ -113,6 +115,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) { StackValue* value = exprs->at(index); switch(value->type()) { case T_OBJECT: + assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); // preserve object type _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); break; diff --git a/hotspot/src/share/vm/runtime/vframe_hp.cpp b/hotspot/src/share/vm/runtime/vframe_hp.cpp index 5f781f39c47..1fc0f2b7d18 100644 --- a/hotspot/src/share/vm/runtime/vframe_hp.cpp +++ b/hotspot/src/share/vm/runtime/vframe_hp.cpp @@ -190,7 +190,7 @@ GrowableArray* compiledVFrame::monitors() const { // Casting away const frame& fr = (frame&) _fr; MonitorInfo* info = new MonitorInfo(fr.compiled_synchronized_native_monitor_owner(nm), - fr.compiled_synchronized_native_monitor(nm), false); + fr.compiled_synchronized_native_monitor(nm), false, false); monitors->push(info); return monitors; } @@ -201,8 +201,20 @@ GrowableArray* compiledVFrame::monitors() const { GrowableArray* result = new GrowableArray(monitors->length()); for (int index = 0; index < monitors->length(); index++) { MonitorValue* mv = monitors->at(index); - StackValue *owner_sv = create_stack_value(mv->owner()); // it is an oop - result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()), mv->eliminated())); + ScopeValue* ov = mv->owner(); + StackValue *owner_sv = create_stack_value(ov); // it is an oop + if (ov->is_object() && owner_sv->obj_is_scalar_replaced()) { // The owner object was scalar replaced + assert(mv->eliminated(), "monitor should be eliminated for scalar replaced object"); + // Put klass for scalar replaced object. + ScopeValue* kv = ((ObjectValue *)ov)->klass(); + assert(kv->is_constant_oop(), "klass should be oop constant for scalar replaced object"); + KlassHandle k(((ConstantOopReadValue*)kv)->value()()); + result->push(new MonitorInfo(k->as_klassOop(), resolve_monitor_lock(mv->basic_lock()), + mv->eliminated(), true)); + } else { + result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()), + mv->eliminated(), false)); + } } return result; } From 0f4f530213d4cd22a1811e73bda9c333648cff8f Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 10 Jun 2009 12:19:48 -0700 Subject: [PATCH 02/61] 6849574: VM crash using NonBlockingHashMap (high_scale_lib) Reviewed-by: kvn --- .../cpu/sparc/vm/c1_LIRGenerator_sparc.cpp | 7 +-- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 6 +-- hotspot/test/compiler/6849574/Test.java | 44 +++++++++++++++++++ 3 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 hotspot/test/compiler/6849574/Test.java diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 239d867a043..a6e6c60e2a7 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -371,7 +371,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { } __ move(value.result(), array_addr, null_check_info); if (obj_store) { - // Is this precise? + // Precise card mark post_barrier(LIR_OprFact::address(array_addr), value.result()); } } @@ -685,11 +685,8 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) { LIR_Opr result = rlock_result(x); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); if (type == objectType) { // Write-barrier needed for Object fields. -#ifdef PRECISE_CARDMARK + // Precise card mark since could either be object or array post_barrier(addr, val.result()); -#else - post_barrier(obj.result(), val.result()); -#endif // PRECISE_CARDMARK } } diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 14071816982..47587792922 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -1534,12 +1534,8 @@ void LIRGenerator::do_StoreField(StoreField* x) { } if (is_oop) { -#ifdef PRECISE_CARDMARK - // Precise cardmarks don't work - post_barrier(LIR_OprFact::address(address), value.result()); -#else + // Store to object so mark the card of the header post_barrier(object.result(), value.result()); -#endif // PRECISE_CARDMARK } if (is_volatile && os::is_MP()) { diff --git a/hotspot/test/compiler/6849574/Test.java b/hotspot/test/compiler/6849574/Test.java new file mode 100644 index 00000000000..7ba048c3b9f --- /dev/null +++ b/hotspot/test/compiler/6849574/Test.java @@ -0,0 +1,44 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/** + * @test + * @bug 6849574 + * @summary VM crash using NonBlockingHashMap (high_scale_lib) + * + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+VerifyBeforeGC Test + */ + +import java.util.concurrent.atomic.*; + +public class Test extends Thread { + + public static void main(String[] args) { + AtomicReferenceArray a = new AtomicReferenceArray(10000); + for (int i = 0; i < 100000; i++) { + a.getAndSet(9999, new Object()); + if (i > 99990) System.gc(); + } + } +} From bc2c9e927f7570e9ec691ac2091729f852faf4b2 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Wed, 17 Jun 2009 09:08:56 -0700 Subject: [PATCH 03/61] 6851829: solaris build fails with 5.8 compilers Solaris builds with the CC 5.8 compilers (used for jdk6 update builds) fail while compiling adlc. Reviewed-by: never --- hotspot/make/solaris/makefiles/adlc.make | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hotspot/make/solaris/makefiles/adlc.make b/hotspot/make/solaris/makefiles/adlc.make index b13e1fa528f..e2f848c26a5 100644 --- a/hotspot/make/solaris/makefiles/adlc.make +++ b/hotspot/make/solaris/makefiles/adlc.make @@ -68,7 +68,9 @@ endif # CFLAGS_WARN holds compiler options to suppress/enable warnings. # Compiler warnings are treated as errors -CFLAGS_WARN = +w -errwarn +ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) + CFLAGS_WARN = +w -errwarn +endif CFLAGS += $(CFLAGS_WARN) ifeq ("${Platform_compiler}", "sparcWorks") From babd1164a44c543e3f723105ea01fada8e6eb050 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Mon, 22 Jun 2009 10:13:20 -0700 Subject: [PATCH 04/61] 6853596: Update Build README-build.html with new info regarding update for Solaris 10u2 and BOOTDIR update Reviewed-by: tbell, ohair --- README-builds.html | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/README-builds.html b/README-builds.html index ad7d16cb30b..dfc2904785e 100644 --- a/README-builds.html +++ b/README-builds.html @@ -119,6 +119,7 @@ Base OS and Architecture OS C/C++ Compiler + BOOT JDK @@ -126,57 +127,65 @@ Linux X86 (32-bit) Fedora 9 gcc 4 + JDK 6u14 FCS Linux X64 (64-bit) Fedora 9 gcc 4 + JDK 6u14 FCS Solaris SPARC (32-bit) - Solaris 10 + patches + Solaris 10u2 + patches
See SunSolve for patch downloads. Sun Studio 12 + JDK 6u14 FCS Solaris SPARCV9 (64-bit) - Solaris 10 + patches + Solaris 10u2 + patches
See SunSolve for patch downloads. Sun Studio 12 + JDK 6u14 FCS Solaris X86 (32-bit) - Solaris 10 + patches + Solaris 10u2 + patches
See SunSolve for patch downloads. Sun Studio 12 + JDK 6u14 FCS Solaris X64 (64-bit) - Solaris 10 + patches + Solaris 10u2 + patches
See SunSolve for patch downloads. Sun Studio 12 + JDK 6u14 FCS Windows X86 (32-bit) Windows XP Microsoft Visual Studio C++ 2008 Standard Edition + JDK 6u14 FCS Windows X64 (64-bit) Windows Server 2003 - Enterprise x64 Edition Microsoft Platform SDK - April 2005 + JDK 6u14 FCS From 2c5f52b511262c52de883364fcccfbc7c5f7c00e Mon Sep 17 00:00:00 2001 From: Chuck Rasbold Date: Tue, 23 Jun 2009 17:52:29 -0700 Subject: [PATCH 05/61] 6837094: False positive for "meet not symmetric" failure Have the meet not symmetric check recursively do the interface-vs-oop check on array subtypes. Reviewed-by: jrose --- hotspot/src/share/vm/opto/type.cpp | 49 ++++++++++--- hotspot/src/share/vm/opto/type.hpp | 13 ++++ hotspot/test/compiler/6837094/Test.java | 94 +++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 9 deletions(-) create mode 100644 hotspot/test/compiler/6837094/Test.java diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index e831a2ad6f7..3c32c348c7e 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -487,6 +487,23 @@ bool Type::is_nan() const { return false; } +//----------------------interface_vs_oop--------------------------------------- +#ifdef ASSERT +bool Type::interface_vs_oop(const Type *t) const { + bool result = false; + + const TypeInstPtr* this_inst = this->isa_instptr(); + const TypeInstPtr* t_inst = t->isa_instptr(); + if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) { + bool this_interface = this_inst->klass()->is_interface(); + bool t_interface = t_inst->klass()->is_interface(); + result = this_interface ^ t_interface; + } + + return result; +} +#endif + //------------------------------meet------------------------------------------- // Compute the MEET of two types. NOT virtual. It enforces that meet is // commutative and the lattice is symmetric. @@ -507,16 +524,8 @@ const Type *Type::meet( const Type *t ) const { // Interface meet Oop is Not Symmetric: // Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull // Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull - const TypeInstPtr* this_inst = this->isa_instptr(); - const TypeInstPtr* t_inst = t->isa_instptr(); - bool interface_vs_oop = false; - if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) { - bool this_interface = this_inst->klass()->is_interface(); - bool t_interface = t_inst->klass()->is_interface(); - interface_vs_oop = this_interface ^ t_interface; - } - if( !interface_vs_oop && (t2t != t->_dual || t2this != _dual) ) { + if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != _dual) ) { tty->print_cr("=== Meet Not Symmetric ==="); tty->print("t = "); t->dump(); tty->cr(); tty->print("this= "); dump(); tty->cr(); @@ -1800,6 +1809,17 @@ int TypeAry::hash(void) const { return (intptr_t)_elem + (intptr_t)_size; } +//----------------------interface_vs_oop--------------------------------------- +#ifdef ASSERT +bool TypeAry::interface_vs_oop(const Type *t) const { + const TypeAry* t_ary = t->is_ary(); + if (t_ary) { + return _elem->interface_vs_oop(t_ary->_elem); + } + return false; +} +#endif + //------------------------------dump2------------------------------------------ #ifndef PRODUCT void TypeAry::dump2( Dict &d, uint depth, outputStream *st ) const { @@ -3389,6 +3409,17 @@ const Type *TypeAryPtr::xdual() const { return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id() ); } +//----------------------interface_vs_oop--------------------------------------- +#ifdef ASSERT +bool TypeAryPtr::interface_vs_oop(const Type *t) const { + const TypeAryPtr* t_aryptr = t->isa_aryptr(); + if (t_aryptr) { + return _ary->interface_vs_oop(t_aryptr->_ary); + } + return false; +} +#endif + //------------------------------dump2------------------------------------------ #ifndef PRODUCT void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const { diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 917c271cce0..1683c384b65 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -190,6 +190,11 @@ public: // Currently, it also works around limitations involving interface types. virtual const Type *filter( const Type *kills ) const; +#ifdef ASSERT + // One type is interface, the other is oop + virtual bool interface_vs_oop(const Type *t) const; +#endif + // Returns true if this pointer points at memory which contains a // compressed oop references. bool is_ptr_to_narrowoop() const; @@ -546,6 +551,10 @@ public: virtual const Type *xmeet( const Type *t ) const; virtual const Type *xdual() const; // Compute dual right now. bool ary_must_be_exact() const; // true if arrays of such are never generic +#ifdef ASSERT + // One type is interface, the other is oop + virtual bool interface_vs_oop(const Type *t) const; +#endif #ifndef PRODUCT virtual void dump2( Dict &d, uint, outputStream *st ) const; // Specialized per-Type dumping #endif @@ -867,6 +876,10 @@ public: } static const TypeAryPtr *_array_body_type[T_CONFLICT+1]; // sharpen the type of an int which is used as an array size +#ifdef ASSERT + // One type is interface, the other is oop + virtual bool interface_vs_oop(const Type *t) const; +#endif #ifndef PRODUCT virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping #endif diff --git a/hotspot/test/compiler/6837094/Test.java b/hotspot/test/compiler/6837094/Test.java new file mode 100644 index 00000000000..9fe2a6a35e5 --- /dev/null +++ b/hotspot/test/compiler/6837094/Test.java @@ -0,0 +1,94 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/** + * @test + * @bug 6837094 + * @summary False positive for "meet not symmetric" failure + * + * @run main/othervm -Xbatch -XX:CompileOnly=Test.collectIs,Test$Factory$1.getArray,Test$Factory$2.getArray Test + */ + +import java.util.Set; +import java.util.HashSet; + +public class Test { + + private interface Factory { + Factory Zero = new Factory() { + public Child0[] getArray() { return new Child0[1]; } + }; + + Factory One = new Factory() { + public Child1[] getArray() { return new Child1[1]; } + }; + + M[] getArray(); + } + + /** + * C2 asserts when compiling this method. Bimorphic inlining happens at + * getArray call site. A Phi in the catch block tries to join the meet type + * from he inline site (Parent[]) with the type expected by CI (Interface[]). + * + * C2 throws an assert when it doesn't need to. + */ + private static void collectIs( + Factory factory, Set s) { + for (I i : factory.getArray()) { + try { + s.add(i); + } catch (Exception e) { + } + } + } + + static public void main(String argv[]) { + Set s = new HashSet(); + + for (int i = 0; i < 25000; i++) { + collectIs(Factory.Zero, s); + collectIs(Factory.One, s); + } + } +} + +/** + * Establish necessary class hierarchy + */ + +interface Interface { +} + +class Parent { +} + +class Child0 extends Parent implements Interface { +} + +class Child1 extends Parent implements Interface { +} + +class Child2 extends Parent implements Interface { +} From 3a643c42b00d1ba7c358906d1a11aa40ef9ceb6b Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 24 Jun 2009 11:42:03 -0400 Subject: [PATCH 06/61] 6850869: G1: RSet "scrubbing" scrubs too much RSet scrubbing incorrectly deletes RSet entries that point to regions tagged as "continues humongous" due to a race when RSet scrubbing iterates over regions in parallel. Reviewed-by: apetrusenko, iveresov --- .../gc_implementation/g1/concurrentMark.cpp | 53 +++++++++++++++---- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 34880cc7eb6..d0a702a371c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -1233,6 +1233,41 @@ public: CardTableModRefBS::card_shift); } + // It takes a region that's not empty (i.e., it has at least one + // live object in it and sets its corresponding bit on the region + // bitmap to 1. If the region is "starts humongous" it will also set + // to 1 the bits on the region bitmap that correspond to its + // associated "continues humongous" regions. + void set_bit_for_region(HeapRegion* hr) { + assert(!hr->continuesHumongous(), "should have filtered those out"); + + size_t index = hr->hrs_index(); + if (!hr->startsHumongous()) { + // Normal (non-humongous) case: just set the bit. + _region_bm->par_at_put((BitMap::idx_t) index, true); + } else { + // Starts humongous case: calculate how many regions are part of + // this humongous region and then set the bit range. It might + // have been a bit more efficient to look at the object that + // spans these humongous regions to calculate their number from + // the object's size. However, it's a good idea to calculate + // this based on the metadata itself, and not the region + // contents, so that this code is not aware of what goes into + // the humongous regions (in case this changes in the future). + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + size_t end_index = index + 1; + while (index < g1h->n_regions()) { + HeapRegion* chr = g1h->region_at(index); + if (!chr->continuesHumongous()) { + break; + } + end_index += 1; + } + _region_bm->par_at_put_range((BitMap::idx_t) index, + (BitMap::idx_t) end_index, true); + } + } + bool doHeapRegion(HeapRegion* hr) { if (_co_tracker != NULL) _co_tracker->update(); @@ -1241,13 +1276,13 @@ public: _start_vtime_sec = os::elapsedVTime(); if (hr->continuesHumongous()) { - HeapRegion* hum_start = hr->humongous_start_region(); - // If the head region of the humongous region has been determined - // to be alive, then all the tail regions should be marked - // such as well. - if (_region_bm->at(hum_start->hrs_index())) { - _region_bm->par_at_put(hr->hrs_index(), 1); - } + // We will ignore these here and process them when their + // associated "starts humongous" region is processed (see + // set_bit_for_heap_region()). Note that we cannot rely on their + // associated "starts humongous" region to have their bit set to + // 1 since, due to the region chunking in the parallel region + // iteration, a "continues humongous" region might be visited + // before its associated "starts humongous". return false; } @@ -1343,14 +1378,14 @@ public: intptr_t(uintptr_t(tp) >> CardTableModRefBS::card_shift); mark_card_num_range(start_card_num, last_card_num); // This definitely means the region has live objects. - _region_bm->par_at_put(hr->hrs_index(), 1); + set_bit_for_region(hr); } } hr->add_to_marked_bytes(marked_bytes); // Update the live region bitmap. if (marked_bytes > 0) { - _region_bm->par_at_put(hr->hrs_index(), 1); + set_bit_for_region(hr); } hr->set_top_at_conc_mark_count(nextTop); _tot_live += hr->next_live_bytes(); From 8f6070ce0eb0841120026d3d25aaa68953513247 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 24 Jun 2009 12:00:51 -0700 Subject: [PATCH 07/61] 6841800: Incorrect boundary values behavior for option -XX:MaxLabelRootDepth=0-6 leads to jvm crash MaxLabelRootDepth value less then 10 is invalid. Reviewed-by: never --- hotspot/src/share/vm/opto/matcher.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 2723a32fd34..c5f75e8bbe5 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -141,6 +141,10 @@ void Matcher::verify_new_nodes_only(Node* xroot) { //---------------------------match--------------------------------------------- void Matcher::match( ) { + if( MaxLabelRootDepth < 100 ) { // Too small? + assert(false, "invalid MaxLabelRootDepth, increase it to 100 minimum"); + MaxLabelRootDepth = 100; + } // One-time initialization of some register masks. init_spill_mask( C->root()->in(1) ); _return_addr_mask = return_addr(); From a9ad90fa87e4a0c92059b6968088226d4f8155df Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Fri, 26 Jun 2009 07:26:10 -0700 Subject: [PATCH 08/61] 5057225: Remove useless I2L conversions The optimizer should be told to normalize (AndL (ConvI2L x) 0xFF) to (ConvI2L (AndI x 0xFF)), and then the existing matcher rule will work for free. Reviewed-by: kvn --- hotspot/src/cpu/sparc/vm/sparc.ad | 172 ++++++++++++++++-- hotspot/src/cpu/x86/vm/x86_32.ad | 131 ++++++++++++- hotspot/src/cpu/x86/vm/x86_64.ad | 83 ++++++++- hotspot/src/share/vm/opto/mulnode.cpp | 74 ++++---- .../test/compiler/5057225/Test5057225.java | 140 ++++++++++++++ 5 files changed, 541 insertions(+), 59 deletions(-) create mode 100644 hotspot/test/compiler/5057225/Test5057225.java diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index e3fd272f0cd..757bb388356 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -1891,17 +1891,17 @@ RegMask Matcher::modL_proj_mask() { // The intptr_t operand types, defined by textual substitution. // (Cf. opto/type.hpp. This lets us avoid many, many other ifdefs.) #ifdef _LP64 -#define immX immL -#define immX13 immL13 -#define immX13m7 immL13m7 -#define iRegX iRegL -#define g1RegX g1RegL +#define immX immL +#define immX13 immL13 +#define immX13m7 immL13m7 +#define iRegX iRegL +#define g1RegX g1RegL #else -#define immX immI -#define immX13 immI13 -#define immX13m7 immI13m7 -#define iRegX iRegI -#define g1RegX g1RegI +#define immX immI +#define immX13 immI13 +#define immX13m7 immI13m7 +#define iRegX iRegI +#define g1RegX g1RegI #endif //----------ENCODING BLOCK----------------------------------------------------- @@ -3446,6 +3446,15 @@ operand immI() %{ interface(CONST_INTER); %} +// Integer Immediate: 8-bit +operand immI8() %{ + predicate(Assembler::is_simm(n->get_int(), 8)); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + // Integer Immediate: 13-bit operand immI13() %{ predicate(Assembler::is_simm13(n->get_int())); @@ -3466,6 +3475,15 @@ operand immI13m7() %{ interface(CONST_INTER); %} +// Integer Immediate: 16-bit +operand immI16() %{ + predicate(Assembler::is_simm(n->get_int(), 16)); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + // Unsigned (positive) Integer Immediate: 13-bit operand immU13() %{ predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int())); @@ -5544,7 +5562,7 @@ instruct loadUB(iRegI dst, memory mem) %{ ins_encode %{ __ ldub($mem$$Address, $dst$$Register); %} - ins_pipe(iload_mask_mem); + ins_pipe(iload_mem); %} // Load Unsigned Byte (8bit UNsigned) into a Long Register @@ -5557,7 +5575,22 @@ instruct loadUB2L(iRegL dst, memory mem) %{ ins_encode %{ __ ldub($mem$$Address, $dst$$Register); %} - ins_pipe(iload_mask_mem); + ins_pipe(iload_mem); +%} + +// Load Unsigned Byte (8 bit UNsigned) with 8-bit mask into Long Register +instruct loadUB2L_immI8(iRegL dst, memory mem, immI8 mask) %{ + match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); + ins_cost(MEMORY_REF_COST + DEFAULT_COST); + + size(2*4); + format %{ "LDUB $mem,$dst\t# ubyte & 8-bit mask -> long\n\t" + "AND $dst,$mask,$dst" %} + ins_encode %{ + __ ldub($mem$$Address, $dst$$Register); + __ and3($dst$$Register, $mask$$constant, $dst$$Register); + %} + ins_pipe(iload_mem); %} // Load Short (16bit signed) @@ -5610,7 +5643,7 @@ instruct loadUS(iRegI dst, memory mem) %{ ins_encode %{ __ lduh($mem$$Address, $dst$$Register); %} - ins_pipe(iload_mask_mem); + ins_pipe(iload_mem); %} // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) @@ -5636,7 +5669,56 @@ instruct loadUS2L(iRegL dst, memory mem) %{ ins_encode %{ __ lduh($mem$$Address, $dst$$Register); %} - ins_pipe(iload_mask_mem); + ins_pipe(iload_mem); +%} + +// Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register +instruct loadUS2L_immI_255(iRegL dst, indOffset13m7 mem, immI_255 mask) %{ + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "LDUB $mem+1,$dst\t! ushort/char & 0xFF -> long" %} + ins_encode %{ + __ ldub($mem$$Address, $dst$$Register, 1); // LSB is index+1 on BE + %} + ins_pipe(iload_mem); +%} + +// Load Unsigned Short/Char (16bit UNsigned) with a 13-bit mask into a Long Register +instruct loadUS2L_immI13(iRegL dst, memory mem, immI13 mask) %{ + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); + ins_cost(MEMORY_REF_COST + DEFAULT_COST); + + size(2*4); + format %{ "LDUH $mem,$dst\t! ushort/char & 13-bit mask -> long\n\t" + "AND $dst,$mask,$dst" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ lduh($mem$$Address, Rdst); + __ and3(Rdst, $mask$$constant, Rdst); + %} + ins_pipe(iload_mem); +%} + +// Load Unsigned Short/Char (16bit UNsigned) with a 16-bit mask into a Long Register +instruct loadUS2L_immI16(iRegL dst, memory mem, immI16 mask, iRegL tmp) %{ + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); + effect(TEMP dst, TEMP tmp); + ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); + + size(3*4); + format %{ "LDUH $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t" + "SET $mask,$tmp\n\t" + "AND $dst,$tmp,$dst" %} + ins_encode %{ + Register Rdst = $dst$$Register; + Register Rtmp = $tmp$$Register; + __ lduh($mem$$Address, Rdst); + __ set($mask$$constant, Rtmp); + __ and3(Rdst, Rtmp, Rdst); + %} + ins_pipe(iload_mem); %} // Load Integer @@ -5718,6 +5800,68 @@ instruct loadI2L(iRegL dst, memory mem) %{ ins_encode %{ __ ldsw($mem$$Address, $dst$$Register); %} + ins_pipe(iload_mask_mem); +%} + +// Load Integer with mask 0xFF into a Long Register +instruct loadI2L_immI_255(iRegL dst, indOffset13m7 mem, immI_255 mask) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "LDUB $mem+3,$dst\t! int & 0xFF -> long" %} + ins_encode %{ + __ ldub($mem$$Address, $dst$$Register, 3); // LSB is index+3 on BE + %} + ins_pipe(iload_mem); +%} + +// Load Integer with mask 0xFFFF into a Long Register +instruct loadI2L_immI_65535(iRegL dst, indOffset13m7 mem, immI_65535 mask) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "LDUH $mem+2,$dst\t! int & 0xFFFF -> long" %} + ins_encode %{ + __ lduh($mem$$Address, $dst$$Register, 2); // LSW is index+2 on BE + %} + ins_pipe(iload_mem); +%} + +// Load Integer with a 13-bit mask into a Long Register +instruct loadI2L_immI13(iRegL dst, memory mem, immI13 mask) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + ins_cost(MEMORY_REF_COST + DEFAULT_COST); + + size(2*4); + format %{ "LDUW $mem,$dst\t! int & 13-bit mask -> long\n\t" + "AND $dst,$mask,$dst" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ lduw($mem$$Address, Rdst); + __ and3(Rdst, $mask$$constant, Rdst); + %} + ins_pipe(iload_mem); +%} + +// Load Integer with a 32-bit mask into a Long Register +instruct loadI2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + effect(TEMP dst, TEMP tmp); + ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); + + size(3*4); + format %{ "LDUW $mem,$dst\t! int & 32-bit mask -> long\n\t" + "SET $mask,$tmp\n\t" + "AND $dst,$tmp,$dst" %} + ins_encode %{ + Register Rdst = $dst$$Register; + Register Rtmp = $tmp$$Register; + __ lduw($mem$$Address, Rdst); + __ set($mask$$constant, Rtmp); + __ and3(Rdst, Rtmp, Rdst); + %} ins_pipe(iload_mem); %} diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 1edf7f35a07..58723cd89d1 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -6885,8 +6885,9 @@ instruct loadB(xRegI dst, memory mem) %{ %} // Load Byte (8bit signed) into Long Register -instruct loadB2L(eRegL dst, memory mem) %{ +instruct loadB2L(eRegL dst, memory mem, eFlagsReg cr) %{ match(Set dst (ConvI2L (LoadB mem))); + effect(KILL cr); ins_cost(375); format %{ "MOVSX8 $dst.lo,$mem\t# byte -> long\n\t" @@ -6917,22 +6918,40 @@ instruct loadUB(xRegI dst, memory mem) %{ %} // Load Unsigned Byte (8 bit UNsigned) into Long Register -instruct loadUB2L(eRegL dst, memory mem) -%{ +instruct loadUB2L(eRegL dst, memory mem, eFlagsReg cr) %{ match(Set dst (ConvI2L (LoadUB mem))); + effect(KILL cr); ins_cost(250); format %{ "MOVZX8 $dst.lo,$mem\t# ubyte -> long\n\t" "XOR $dst.hi,$dst.hi" %} ins_encode %{ - __ movzbl($dst$$Register, $mem$$Address); - __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register)); + Register Rdst = $dst$$Register; + __ movzbl(Rdst, $mem$$Address); + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); %} ins_pipe(ialu_reg_mem); %} +// Load Unsigned Byte (8 bit UNsigned) with mask into Long Register +instruct loadUB2L_immI8(eRegL dst, memory mem, immI8 mask, eFlagsReg cr) %{ + match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); + effect(KILL cr); + + format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 8-bit mask -> long\n\t" + "XOR $dst.hi,$dst.hi\n\t" + "AND $dst.lo,$mask" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ movzbl(Rdst, $mem$$Address); + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); + __ andl(Rdst, $mask$$constant); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Short (16bit signed) instruct loadS(eRegI dst, memory mem) %{ match(Set dst (LoadS mem)); @@ -6960,8 +6979,9 @@ instruct loadS2B(eRegI dst, memory mem, immI_24 twentyfour) %{ %} // Load Short (16bit signed) into Long Register -instruct loadS2L(eRegL dst, memory mem) %{ +instruct loadS2L(eRegL dst, memory mem, eFlagsReg cr) %{ match(Set dst (ConvI2L (LoadS mem))); + effect(KILL cr); ins_cost(375); format %{ "MOVSX $dst.lo,$mem\t# short -> long\n\t" @@ -7004,8 +7024,9 @@ instruct loadUS2B(eRegI dst, memory mem, immI_24 twentyfour) %{ %} // Load Unsigned Short/Char (16 bit UNsigned) into Long Register -instruct loadUS2L(eRegL dst, memory mem) %{ +instruct loadUS2L(eRegL dst, memory mem, eFlagsReg cr) %{ match(Set dst (ConvI2L (LoadUS mem))); + effect(KILL cr); ins_cost(250); format %{ "MOVZX $dst.lo,$mem\t# ushort/char -> long\n\t" @@ -7019,6 +7040,38 @@ instruct loadUS2L(eRegL dst, memory mem) %{ ins_pipe(ialu_reg_mem); %} +// Load Unsigned Short/Char (16 bit UNsigned) with mask 0xFF into Long Register +instruct loadUS2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) %{ + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); + effect(KILL cr); + + format %{ "MOVZX8 $dst.lo,$mem\t# ushort/char & 0xFF -> long\n\t" + "XOR $dst.hi,$dst.hi" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ movzbl(Rdst, $mem$$Address); + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Unsigned Short/Char (16 bit UNsigned) with a 16-bit mask into Long Register +instruct loadUS2L_immI16(eRegL dst, memory mem, immI16 mask, eFlagsReg cr) %{ + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); + effect(KILL cr); + + format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 16-bit mask -> long\n\t" + "XOR $dst.hi,$dst.hi\n\t" + "AND $dst.lo,$mask" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ movzwl(Rdst, $mem$$Address); + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); + __ andl(Rdst, $mask$$constant); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Integer instruct loadI(eRegI dst, memory mem) %{ match(Set dst (LoadI mem)); @@ -7082,8 +7135,9 @@ instruct loadI2US(eRegI dst, memory mem, immI_65535 mask) %{ %} // Load Integer into Long Register -instruct loadI2L(eRegL dst, memory mem) %{ +instruct loadI2L(eRegL dst, memory mem, eFlagsReg cr) %{ match(Set dst (ConvI2L (LoadI mem))); + effect(KILL cr); ins_cost(375); format %{ "MOV $dst.lo,$mem\t# int -> long\n\t" @@ -7099,9 +7153,57 @@ instruct loadI2L(eRegL dst, memory mem) %{ ins_pipe(ialu_reg_mem); %} +// Load Integer with mask 0xFF into Long Register +instruct loadI2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + effect(KILL cr); + + format %{ "MOVZX8 $dst.lo,$mem\t# int & 0xFF -> long\n\t" + "XOR $dst.hi,$dst.hi" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ movzbl(Rdst, $mem$$Address); + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer with mask 0xFFFF into Long Register +instruct loadI2L_immI_65535(eRegL dst, memory mem, immI_65535 mask, eFlagsReg cr) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + effect(KILL cr); + + format %{ "MOVZX $dst.lo,$mem\t# int & 0xFFFF -> long\n\t" + "XOR $dst.hi,$dst.hi" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ movzwl(Rdst, $mem$$Address); + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer with 32-bit mask into Long Register +instruct loadI2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + effect(KILL cr); + + format %{ "MOV $dst.lo,$mem\t# int & 32-bit mask -> long\n\t" + "XOR $dst.hi,$dst.hi\n\t" + "AND $dst.lo,$mask" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ movl(Rdst, $mem$$Address); + __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); + __ andl(Rdst, $mask$$constant); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Unsigned Integer into Long Register -instruct loadUI2L(eRegL dst, memory mem) %{ +instruct loadUI2L(eRegL dst, memory mem, eFlagsReg cr) %{ match(Set dst (LoadUI2L mem)); + effect(KILL cr); ins_cost(250); format %{ "MOV $dst.lo,$mem\t# uint -> long\n\t" @@ -7695,6 +7797,17 @@ instruct storeL(long_memory mem, eRegL src) %{ ins_pipe( ialu_mem_long_reg ); %} +// Store Long to Integer +instruct storeL2I(memory mem, eRegL src) %{ + match(Set mem (StoreI mem (ConvL2I src))); + + format %{ "MOV $mem,$src.lo\t# long -> int" %} + ins_encode %{ + __ movl($mem$$Address, $src$$Register); + %} + ins_pipe(ialu_mem_reg); +%} + // Volatile Store Long. Must be atomic, so move it into // the FP TOS and then do a 64-bit FIST. Has to probe the // target address before the store (for null-ptr checks) diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index c0ffe70eb19..52afa81f659 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -6444,6 +6444,21 @@ instruct loadUB2L(rRegL dst, memory mem) ins_pipe(ialu_reg_mem); %} +// Load Unsigned Byte (8 bit UNsigned) with a 8-bit mask into Long Register +instruct loadUB2L_immI8(rRegL dst, memory mem, immI8 mask, rFlagsReg cr) %{ + match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); + effect(KILL cr); + + format %{ "movzbq $dst, $mem\t# ubyte & 8-bit mask -> long\n\t" + "andl $dst, $mask" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ movzbq(Rdst, $mem$$Address); + __ andl(Rdst, $mask$$constant); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Short (16 bit signed) instruct loadS(rRegI dst, memory mem) %{ @@ -6528,6 +6543,32 @@ instruct loadUS2L(rRegL dst, memory mem) ins_pipe(ialu_reg_mem); %} +// Load Unsigned Short/Char (16 bit UNsigned) with mask 0xFF into Long Register +instruct loadUS2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{ + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); + + format %{ "movzbq $dst, $mem\t# ushort/char & 0xFF -> long" %} + ins_encode %{ + __ movzbq($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Unsigned Short/Char (16 bit UNsigned) with mask into Long Register +instruct loadUS2L_immI16(rRegL dst, memory mem, immI16 mask, rFlagsReg cr) %{ + match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); + effect(KILL cr); + + format %{ "movzwq $dst, $mem\t# ushort/char & 16-bit mask -> long\n\t" + "andl $dst, $mask" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ movzwq(Rdst, $mem$$Address); + __ andl(Rdst, $mask$$constant); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Integer instruct loadI(rRegI dst, memory mem) %{ @@ -6606,6 +6647,43 @@ instruct loadI2L(rRegL dst, memory mem) ins_pipe(ialu_reg_mem); %} +// Load Integer with mask 0xFF into Long Register +instruct loadI2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + + format %{ "movzbq $dst, $mem\t# int & 0xFF -> long" %} + ins_encode %{ + __ movzbq($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer with mask 0xFFFF into Long Register +instruct loadI2L_immI_65535(rRegL dst, memory mem, immI_65535 mask) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + + format %{ "movzwq $dst, $mem\t# int & 0xFFFF -> long" %} + ins_encode %{ + __ movzwq($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg_mem); +%} + +// Load Integer with a 32-bit mask into Long Register +instruct loadI2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{ + match(Set dst (ConvI2L (AndI (LoadI mem) mask))); + effect(KILL cr); + + format %{ "movl $dst, $mem\t# int & 32-bit mask -> long\n\t" + "andl $dst, $mask" %} + ins_encode %{ + Register Rdst = $dst$$Register; + __ movl(Rdst, $mem$$Address); + __ andl(Rdst, $mask$$constant); + %} + ins_pipe(ialu_reg_mem); +%} + // Load Unsigned Integer into Long Register instruct loadUI2L(rRegL dst, memory mem) %{ @@ -11673,8 +11751,9 @@ instruct convI2L_reg_reg(rRegL dst, rRegI src) ins_cost(125); format %{ "movslq $dst, $src\t# i2l" %} - opcode(0x63); // needs REX.W - ins_encode(REX_reg_reg_wide(dst, src), OpcP, reg_reg(dst,src)); + ins_encode %{ + __ movslq($dst$$Register, $src$$Register); + %} ins_pipe(ialu_reg_reg); %} diff --git a/hotspot/src/share/vm/opto/mulnode.cpp b/hotspot/src/share/vm/opto/mulnode.cpp index 7700272f6d9..b9dc06bb369 100644 --- a/hotspot/src/share/vm/opto/mulnode.cpp +++ b/hotspot/src/share/vm/opto/mulnode.cpp @@ -430,31 +430,28 @@ Node *AndINode::Identity( PhaseTransform *phase ) { // x & x => x if (phase->eqv(in(1), in(2))) return in(1); - Node *load = in(1); - const TypeInt *t2 = phase->type( in(2) )->isa_int(); - if( t2 && t2->is_con() ) { + Node* in1 = in(1); + uint op = in1->Opcode(); + const TypeInt* t2 = phase->type(in(2))->isa_int(); + if (t2 && t2->is_con()) { int con = t2->get_con(); // Masking off high bits which are always zero is useless. const TypeInt* t1 = phase->type( in(1) )->isa_int(); if (t1 != NULL && t1->_lo >= 0) { - jint t1_support = ((jint)1 << (1 + log2_intptr(t1->_hi))) - 1; + jint t1_support = right_n_bits(1 + log2_intptr(t1->_hi)); if ((t1_support & con) == t1_support) - return load; + return in1; } - uint lop = load->Opcode(); - if( lop == Op_LoadUS && - con == 0x0000FFFF ) // Already zero-extended - return load; // Masking off the high bits of a unsigned-shift-right is not // needed either. - if( lop == Op_URShiftI ) { - const TypeInt *t12 = phase->type( load->in(2) )->isa_int(); - if( t12 && t12->is_con() ) { // Shift is by a constant + if (op == Op_URShiftI) { + const TypeInt* t12 = phase->type(in1->in(2))->isa_int(); + if (t12 && t12->is_con()) { // Shift is by a constant int shift = t12->get_con(); shift &= BitsPerJavaInteger - 1; // semantics of Java shifts int mask = max_juint >> shift; - if( (mask&con) == mask ) // If AND is useless, skip it - return load; + if ((mask & con) == mask) // If AND is useless, skip it + return in1; } } } @@ -476,26 +473,17 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) { return new (phase->C, 3) AndINode(load,phase->intcon(mask&0xFFFF)); // Masking bits off of a Short? Loading a Character does some masking - if( lop == Op_LoadS && - (mask & 0xFFFF0000) == 0 ) { + if (lop == Op_LoadS && (mask & 0xFFFF0000) == 0 ) { Node *ldus = new (phase->C, 3) LoadUSNode(load->in(MemNode::Control), - load->in(MemNode::Memory), - load->in(MemNode::Address), - load->adr_type()); + load->in(MemNode::Memory), + load->in(MemNode::Address), + load->adr_type()); ldus = phase->transform(ldus); - return new (phase->C, 3) AndINode(ldus, phase->intcon(mask&0xFFFF)); + return new (phase->C, 3) AndINode(ldus, phase->intcon(mask & 0xFFFF)); } - // Masking sign bits off of a Byte? Do an unsigned byte load. - if (lop == Op_LoadB && mask == 0x000000FF) { - return new (phase->C, 3) LoadUBNode(load->in(MemNode::Control), - load->in(MemNode::Memory), - load->in(MemNode::Address), - load->adr_type()); - } - - // Masking sign bits off of a Byte plus additional lower bits? Do - // an unsigned byte load plus an and. + // Masking sign bits off of a Byte? Do an unsigned byte load plus + // an and. if (lop == Op_LoadB && (mask & 0xFFFFFF00) == 0) { Node* ldub = new (phase->C, 3) LoadUBNode(load->in(MemNode::Control), load->in(MemNode::Memory), @@ -605,8 +593,13 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* in1 = in(1); uint op = in1->Opcode(); - // Masking sign bits off of an integer? Do an unsigned integer to long load. - if (op == Op_ConvI2L && in1->in(1)->Opcode() == Op_LoadI && mask == 0x00000000FFFFFFFFL) { + // Masking sign bits off of an integer? Do an unsigned integer to + // long load. + // NOTE: This check must be *before* we try to convert the AndLNode + // to an AndINode and commute it with ConvI2LNode because + // 0xFFFFFFFFL masks the whole integer and we get a sign extension, + // which is wrong. + if (op == Op_ConvI2L && in1->in(1)->Opcode() == Op_LoadI && mask == CONST64(0x00000000FFFFFFFF)) { Node* load = in1->in(1); return new (phase->C, 3) LoadUI2LNode(load->in(MemNode::Control), load->in(MemNode::Memory), @@ -614,9 +607,22 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { load->adr_type()); } + // Are we masking a long that was converted from an int with a mask + // that fits in 32-bits? Commute them and use an AndINode. + if (op == Op_ConvI2L && (mask & CONST64(0xFFFFFFFF00000000)) == 0) { + // If we are doing an UI2L conversion (i.e. the mask is + // 0x00000000FFFFFFFF) we cannot convert the AndL to an AndI + // because the AndI would be optimized away later in Identity. + if (mask != CONST64(0x00000000FFFFFFFF)) { + Node* andi = new (phase->C, 3) AndINode(in1->in(1), phase->intcon(mask)); + andi = phase->transform(andi); + return new (phase->C, 2) ConvI2LNode(andi); + } + } + // Masking off sign bits? Dont make them! if (op == Op_RShiftL) { - const TypeInt *t12 = phase->type(in1->in(2))->isa_int(); + const TypeInt* t12 = phase->type(in1->in(2))->isa_int(); if( t12 && t12->is_con() ) { // Shift is by a constant int shift = t12->get_con(); shift &= BitsPerJavaLong - 1; // semantics of Java shifts @@ -626,7 +632,7 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { if( (sign_bits_mask & mask) == 0 ) { // Use zero-fill shift instead Node *zshift = phase->transform(new (phase->C, 3) URShiftLNode(in1->in(1), in1->in(2))); - return new (phase->C, 3) AndLNode( zshift, in(2) ); + return new (phase->C, 3) AndLNode(zshift, in(2)); } } } diff --git a/hotspot/test/compiler/5057225/Test5057225.java b/hotspot/test/compiler/5057225/Test5057225.java new file mode 100644 index 00000000000..2a7360f7de8 --- /dev/null +++ b/hotspot/test/compiler/5057225/Test5057225.java @@ -0,0 +1,140 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 5057225 + * @summary Remove useless I2L conversions + * + * @run main/othervm -Xcomp -XX:CompileOnly=Test5057225.doload Test5057225 + */ + +import java.net.URLClassLoader; + +public class Test5057225 { + static byte[] ba = new byte[] { -1 }; + static short[] sa = new short[] { -1 }; + static int[] ia = new int[] { -1 }; + + static final long[] BYTE_MASKS = { + 0x0FL, + 0x7FL, // 7-bit + 0xFFL, + }; + + static final long[] SHORT_MASKS = { + 0x000FL, + 0x007FL, // 7-bit + 0x00FFL, + 0x0FFFL, + 0x3FFFL, // 14-bit + 0x7FFFL, // 15-bit + 0xFFFFL, + }; + + static final long[] INT_MASKS = { + 0x0000000FL, + 0x0000007FL, // 7-bit + 0x000000FFL, + 0x00000FFFL, + 0x00003FFFL, // 14-bit + 0x00007FFFL, // 15-bit + 0x0000FFFFL, + 0x00FFFFFFL, + 0x7FFFFFFFL, // 31-bit + 0xFFFFFFFFL, + }; + + public static void main(String[] args) throws Exception { + for (int i = 0; i < BYTE_MASKS.length; i++) { + System.setProperty("value", "" + BYTE_MASKS[i]); + loadAndRunClass("Test5057225$loadUB2L"); + } + + for (int i = 0; i < SHORT_MASKS.length; i++) { + System.setProperty("value", "" + SHORT_MASKS[i]); + loadAndRunClass("Test5057225$loadUS2L"); + } + + for (int i = 0; i < INT_MASKS.length; i++) { + System.setProperty("value", "" + INT_MASKS[i]); + loadAndRunClass("Test5057225$loadUI2L"); + } + } + + static void check(long result, long expected) { + if (result != expected) + throw new InternalError(result + " != " + expected); + } + + static void loadAndRunClass(String classname) throws Exception { + Class cl = Class.forName(classname); + URLClassLoader apploader = (URLClassLoader) cl.getClassLoader(); + ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent()); + Class c = loader.loadClass(classname); + Runnable r = (Runnable) c.newInstance(); + r.run(); + } + + public static class loadUB2L implements Runnable { + static final long MASK; + static { + long value = 0; + try { + value = Long.decode(System.getProperty("value")); + } catch (Throwable e) {} + MASK = value; + } + + public void run() { check(doload(ba), MASK); } + static long doload(byte[] ba) { return ba[0] & MASK; } + } + + public static class loadUS2L implements Runnable { + static final long MASK; + static { + long value = 0; + try { + value = Long.decode(System.getProperty("value")); + } catch (Throwable e) {} + MASK = value; + } + + public void run() { check(doload(sa), MASK); } + static long doload(short[] sa) { return sa[0] & MASK; } + } + + public static class loadUI2L implements Runnable { + static final long MASK; + static { + long value = 0; + try { + value = Long.decode(System.getProperty("value")); + } catch (Throwable e) {} + MASK = value; + } + + public void run() { check(doload(ia), MASK); } + static long doload(int[] ia) { return ia[0] & MASK; } + } +} From bf215dbb7e1d25af32bbeedcef1835ff665301e2 Mon Sep 17 00:00:00 2001 From: Andrey Petrusenko Date: Fri, 26 Jun 2009 09:22:19 -0700 Subject: [PATCH 09/61] 6854027: Precompiled headers are not being updated in Linux/GCC builds Fixes incorrect handling of precompiled headers in diff mode. Reviewed-by: never, twisti --- .../src/share/tools/MakeDeps/Database.java | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/tools/MakeDeps/Database.java b/hotspot/src/share/tools/MakeDeps/Database.java index 3cdffebca49..861fc2ef553 100644 --- a/hotspot/src/share/tools/MakeDeps/Database.java +++ b/hotspot/src/share/tools/MakeDeps/Database.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ public class Database { private HashMap platformDepFiles; private long threshold; private int nOuterFiles; - private int nPrecompiledFiles; private boolean missingOk; private Platform plat; /** These allow you to specify files not in the include database @@ -62,7 +61,6 @@ public class Database { threshold = t; nOuterFiles = 0; - nPrecompiledFiles = 0; missingOk = false; firstFile = null; lastFile = null; @@ -343,7 +341,6 @@ public class Database { plat.getGIFileTemplate().getInvDir() + list.getName() + "\""); - nPrecompiledFiles += 1; } } inclFile.println(); @@ -408,22 +405,22 @@ public class Database { gd.println(); } - if (nPrecompiledFiles > 0) { - // write Precompiled_Files = ... - gd.println("Precompiled_Files = \\"); - for (Iterator iter = grandInclude.iterator(); iter.hasNext(); ) { - FileList list = (FileList) iter.next(); + // write Precompiled_Files = ... + gd.println("Precompiled_Files = \\"); + for (Iterator iter = grandInclude.iterator(); iter.hasNext(); ) { + FileList list = (FileList) iter.next(); + if (list.getCount() >= threshold) { gd.println(list.getName() + " \\"); String platformDep = platformDepFiles.get(list.getName()); if (platformDep != null) { - // make sure changes to the platform dependent file will - // cause regeneration of the pch file. - gd.println(platformDep + " \\"); + // make sure changes to the platform dependent file will + // cause regeneration of the pch file. + gd.println(platformDep + " \\"); } } - gd.println(); - gd.println(); } + gd.println(); + gd.println(); gd.println("DTraced_Files = \\"); for (Iterator iter = outerFiles.iterator(); iter.hasNext(); ) { @@ -483,7 +480,6 @@ public class Database { } if (plat.includeGIDependencies() - && nPrecompiledFiles > 0 && anII.getUseGrandInclude()) { gd.println(" $(Precompiled_Files) \\"); } From 3bdd70fe1877b3edc93118d2f7583021f87e1a3c Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 26 Jun 2009 13:03:29 -0700 Subject: [PATCH 10/61] 6818666: G1: Type lost in g1 pre-barrier Reviewed-by: kvn --- hotspot/src/share/vm/opto/graphKit.cpp | 33 ++++++++++++++++------ hotspot/src/share/vm/opto/graphKit.hpp | 9 +++--- hotspot/src/share/vm/opto/library_call.cpp | 9 +++--- hotspot/src/share/vm/opto/parse2.cpp | 2 +- hotspot/src/share/vm/opto/parse3.cpp | 4 +-- 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index f309c05c6c6..5bf9a759c08 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1378,7 +1378,7 @@ void GraphKit::pre_barrier(Node* ctl, Node* adr, uint adr_idx, Node *val, - const Type* val_type, + const TypeOopPtr* val_type, BasicType bt) { BarrierSet* bs = Universe::heap()->barrier_set(); set_control(ctl); @@ -1436,7 +1436,7 @@ Node* GraphKit::store_oop_to_object(Node* ctl, Node* adr, const TypePtr* adr_type, Node *val, - const Type* val_type, + const TypeOopPtr* val_type, BasicType bt) { uint adr_idx = C->get_alias_index(adr_type); Node* store; @@ -1451,7 +1451,7 @@ Node* GraphKit::store_oop_to_array(Node* ctl, Node* adr, const TypePtr* adr_type, Node *val, - const Type* val_type, + const TypeOopPtr* val_type, BasicType bt) { uint adr_idx = C->get_alias_index(adr_type); Node* store; @@ -1466,12 +1466,29 @@ Node* GraphKit::store_oop_to_unknown(Node* ctl, Node* adr, const TypePtr* adr_type, Node *val, - const Type* val_type, BasicType bt) { - uint adr_idx = C->get_alias_index(adr_type); - Node* store; + Compile::AliasType* at = C->alias_type(adr_type); + const TypeOopPtr* val_type = NULL; + if (adr_type->isa_instptr()) { + if (at->field() != NULL) { + // known field. This code is a copy of the do_put_xxx logic. + ciField* field = at->field(); + if (!field->type()->is_loaded()) { + val_type = TypeInstPtr::BOTTOM; + } else { + val_type = TypeOopPtr::make_from_klass(field->type()->as_klass()); + } + } + } else if (adr_type->isa_aryptr()) { + val_type = adr_type->is_aryptr()->elem()->isa_oopptr(); + } + if (val_type == NULL) { + val_type = TypeInstPtr::BOTTOM; + } + + uint adr_idx = at->index(); pre_barrier(ctl, obj, adr, adr_idx, val, val_type, bt); - store = store_to_memory(control(), adr, val, bt, adr_idx); + Node* store = store_to_memory(control(), adr, val, bt, adr_idx); post_barrier(control(), store, obj, adr, adr_idx, val, bt, true); return store; } @@ -3202,7 +3219,7 @@ void GraphKit::g1_write_barrier_pre(Node* obj, Node* adr, uint alias_idx, Node* val, - const Type* val_type, + const TypeOopPtr* val_type, BasicType bt) { IdealKit ideal(gvn(), control(), merged_memory(), true); #define __ ideal. diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index f47bc49a706..7904a0b0f2f 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -454,7 +454,7 @@ class GraphKit : public Phase { Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, - const Type* val_type, + const TypeOopPtr* val_type, BasicType bt); Node* store_oop_to_array(Node* ctl, @@ -462,7 +462,7 @@ class GraphKit : public Phase { Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, - const Type* val_type, + const TypeOopPtr* val_type, BasicType bt); // Could be an array or object we don't know at compile time (unsafe ref.) @@ -471,12 +471,11 @@ class GraphKit : public Phase { Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, - const Type* val_type, BasicType bt); // For the few case where the barriers need special help void pre_barrier(Node* ctl, Node* obj, Node* adr, uint adr_idx, - Node* val, const Type* val_type, BasicType bt); + Node* val, const TypeOopPtr* val_type, BasicType bt); void post_barrier(Node* ctl, Node* store, Node* obj, Node* adr, uint adr_idx, Node* val, BasicType bt, bool use_precise); @@ -599,7 +598,7 @@ class GraphKit : public Phase { Node* adr, uint alias_idx, Node* val, - const Type* val_type, + const TypeOopPtr* val_type, BasicType bt); void g1_write_barrier_post(Node* store, diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 136b8cb0d11..483c070e3e6 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -2178,9 +2178,8 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas // Possibly an oop being stored to Java heap or native memory if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { // oop to Java heap. - (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, val->bottom_type(), type); + (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type); } else { - // We can't tell at compile time if we are storing in the Java heap or outside // of it. So we need to emit code to conditionally do the proper type of // store. @@ -2189,7 +2188,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas kit.declares_done(); // QQQ who knows what probability is here?? kit.if_then(heap_base_oop, BoolTest::ne, null(), PROB_UNLIKELY(0.999)); { - (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, val->bottom_type(), type); + (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type); } kit.else_(); { (void) store_to_memory(control(), adr, val, type, adr_type, is_volatile); } kit.end_if(); @@ -2394,7 +2393,7 @@ bool LibraryCallKit::inline_unsafe_CAS(BasicType type) { case T_OBJECT: // reference stores need a store barrier. // (They don't if CAS fails, but it isn't worth checking.) - pre_barrier(control(), base, adr, alias_idx, newval, value_type, T_OBJECT); + pre_barrier(control(), base, adr, alias_idx, newval, value_type->is_oopptr(), T_OBJECT); #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop()) { Node *newval_enc = _gvn.transform(new (C, 2) EncodePNode(newval, newval->bottom_type()->make_narrowoop())); @@ -2489,7 +2488,7 @@ bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { bool require_atomic_access = true; Node* store; if (type == T_OBJECT) // reference stores need a store barrier. - store = store_oop_to_unknown(control(), base, adr, adr_type, val, value_type, type); + store = store_oop_to_unknown(control(), base, adr, adr_type, val, type); else { store = store_to_memory(control(), adr, val, type, adr_type, require_atomic_access); } diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 02a6ceccf07..19e486d83a9 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -1565,7 +1565,7 @@ void Parse::do_one_bytecode() { c = pop(); // Oop to store b = pop(); // index (already used) a = pop(); // the array itself - const Type* elemtype = _gvn.type(a)->is_aryptr()->elem(); + const TypeOopPtr* elemtype = _gvn.type(a)->is_aryptr()->elem()->is_oopptr(); const TypeAryPtr* adr_type = TypeAryPtr::OOPS; Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT); break; diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index b3e95ad66fa..960b95c1c9c 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -222,7 +222,7 @@ void Parse::do_put_xxx(const TypePtr* obj_type, Node* obj, ciField* field, bool // Store the value. Node* store; if (bt == T_OBJECT) { - const TypePtr* field_type; + const TypeOopPtr* field_type; if (!field->type()->is_loaded()) { field_type = TypeInstPtr::BOTTOM; } else { @@ -361,7 +361,7 @@ Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, in guarantee(length_con >= 0, "non-constant multianewarray"); ciArrayKlass* array_klass_1 = array_klass->as_obj_array_klass()->element_klass()->as_array_klass(); const TypePtr* adr_type = TypeAryPtr::OOPS; - const Type* elemtype = _gvn.type(array)->is_aryptr()->elem(); + const TypeOopPtr* elemtype = _gvn.type(array)->is_aryptr()->elem()->is_oopptr(); const intptr_t header = arrayOopDesc::base_offset_in_bytes(T_OBJECT); for (jint i = 0; i < length_con; i++) { Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs); From 986d5709816c5544366cd4b44f7c799bc28b6895 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 26 Jun 2009 16:14:31 -0700 Subject: [PATCH 11/61] 6851908: interpreter null check profiling broken causing extra compilation invalidation Reviewed-by: kvn --- hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp | 2 ++ hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp index 9dc29f31da9..db0b6e32f49 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp @@ -1372,6 +1372,8 @@ void InterpreterMacroAssembler::profile_null_seen(Register mdp) { // If no method data exists, go to profile_continue. test_method_data_pointer(mdp, profile_continue); + set_mdp_flag_at(mdp, BitData::null_seen_byte_constant()); + // The method data pointer needs to be updated. int mdp_delta = in_bytes(BitData::bit_data_size()); if (TypeProfileCasts) { diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp index dbd858da298..0c1af9b0814 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp @@ -1409,6 +1409,8 @@ void InterpreterMacroAssembler::profile_null_seen(Register mdp) { // If no method data exists, go to profile_continue. test_method_data_pointer(mdp, profile_continue); + set_mdp_flag_at(mdp, BitData::null_seen_byte_constant()); + // The method data pointer needs to be updated. int mdp_delta = in_bytes(BitData::bit_data_size()); if (TypeProfileCasts) { From eec17fe775929425c741fff10b70d7b779433e96 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Mon, 29 Jun 2009 12:17:03 -0400 Subject: [PATCH 12/61] 6855115: G1: Fix for 6850869 is incorrect Missed updating two variable names when improving the code for 6850869. Reviewed-by: iveresov, jmasa, ysr --- hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index d0a702a371c..20f001d7758 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -1256,8 +1256,8 @@ public: // the humongous regions (in case this changes in the future). G1CollectedHeap* g1h = G1CollectedHeap::heap(); size_t end_index = index + 1; - while (index < g1h->n_regions()) { - HeapRegion* chr = g1h->region_at(index); + while (end_index < g1h->n_regions()) { + HeapRegion* chr = g1h->region_at(end_index); if (!chr->continuesHumongous()) { break; } From f7b598496d40200f6bab01a8fdac27060a6111c3 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 30 Jun 2009 11:11:10 +0100 Subject: [PATCH 13/61] 6843003: Windows Server 2008 R2 system recognition Reviewed-by: ohair, sherman --- .../windows/native/java/lang/java_props_md.c | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/jdk/src/windows/native/java/lang/java_props_md.c b/jdk/src/windows/native/java/lang/java_props_md.c index b15a9bafac0..4ab139ad307 100644 --- a/jdk/src/windows/native/java/lang/java_props_md.c +++ b/jdk/src/windows/native/java/lang/java_props_md.c @@ -714,10 +714,10 @@ GetJavaProperties(JNIEnv* env) * Windows XP 64 bit 5 2 * where ((&ver.wServicePackMinor) + 2) = 1 * and si.wProcessorArchitecture = 9 - * Windows Vista family 6 0 - * Windows 2008 6 0 - * where ((&ver.wServicePackMinor) + 2) = 1 - * Windows 7 6 1 + * Windows Vista family 6 0 (VER_NT_WORKSTATION) + * Windows Server 2008 6 0 (!VER_NT_WORKSTATION) + * Windows 7 6 1 (VER_NT_WORKSTATION) + * Windows Server 2008 R2 6 1 (!VER_NT_WORKSTATION) * * This mapping will presumably be augmented as new Windows * versions are released. @@ -768,14 +768,7 @@ GetJavaProperties(JNIEnv* env) } } else if (ver.dwMajorVersion == 6) { /* - * From MSDN OSVERSIONINFOEX documentation: - * - * "Because the version numbers for Windows Server 2008 - * and Windows Vista are identical, you must also test - * whether the wProductType member is VER_NT_WORKSTATION. - * If wProductType is VER_NT_WORKSTATION, the operating - * system is Windows Vista or 7; otherwise, it is Windows - * Server 2008." + * See table in MSDN OSVERSIONINFOEX documentation. */ if (ver.wProductType == VER_NT_WORKSTATION) { switch (ver.dwMinorVersion) { @@ -784,7 +777,11 @@ GetJavaProperties(JNIEnv* env) default: sprops.os_name = "Windows NT (unknown)"; } } else { - sprops.os_name = "Windows Server 2008"; + switch (ver.dwMinorVersion) { + case 0: sprops.os_name = "Windows Server 2008"; break; + case 1: sprops.os_name = "Windows Server 2008 R2"; break; + default: sprops.os_name = "Windows NT (unknown)"; + } } } else { sprops.os_name = "Windows NT (unknown)"; From da11e65fa42372d78a2981b61842d6f84af5a91e Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 1 Jul 2009 12:22:23 -0700 Subject: [PATCH 14/61] 6856025: assert(_base >= OopPtr && _base <= KlassPtr,"Not a Java pointer") Reviewed-by: kvn --- hotspot/src/share/vm/adlc/output_h.cpp | 4 ++-- hotspot/src/share/vm/opto/graphKit.cpp | 2 +- hotspot/src/share/vm/opto/library_call.cpp | 2 +- hotspot/src/share/vm/opto/parse2.cpp | 2 +- hotspot/src/share/vm/opto/parse3.cpp | 2 +- hotspot/src/share/vm/opto/type.cpp | 22 +++++++++--------- hotspot/src/share/vm/opto/type.hpp | 27 ++++++++++++++-------- 7 files changed, 35 insertions(+), 26 deletions(-) diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp index 4668d68f9fa..23f0827b2e8 100644 --- a/hotspot/src/share/vm/adlc/output_h.cpp +++ b/hotspot/src/share/vm/adlc/output_h.cpp @@ -1367,11 +1367,11 @@ void ArchDesc::declareClasses(FILE *fp) { else if (!strcmp(oper->ideal_type(_globalNames), "ConN")) { // Access the locally stored constant fprintf(fp," virtual intptr_t constant() const {"); - fprintf(fp, " return _c0->make_oopptr()->get_con();"); + fprintf(fp, " return _c0->get_ptrtype()->get_con();"); fprintf(fp, " }\n"); // Generate query to determine if this pointer is an oop fprintf(fp," virtual bool constant_is_oop() const {"); - fprintf(fp, " return _c0->make_oopptr()->isa_oop_ptr();"); + fprintf(fp, " return _c0->get_ptrtype()->isa_oop_ptr();"); fprintf(fp, " }\n"); } else if (!strcmp(oper->ideal_type(_globalNames), "ConL")) { diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 5bf9a759c08..83646c54ed9 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1480,7 +1480,7 @@ Node* GraphKit::store_oop_to_unknown(Node* ctl, } } } else if (adr_type->isa_aryptr()) { - val_type = adr_type->is_aryptr()->elem()->isa_oopptr(); + val_type = adr_type->is_aryptr()->elem()->make_oopptr(); } if (val_type == NULL) { val_type = TypeInstPtr::BOTTOM; diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 483c070e3e6..dc674f93821 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -2393,7 +2393,7 @@ bool LibraryCallKit::inline_unsafe_CAS(BasicType type) { case T_OBJECT: // reference stores need a store barrier. // (They don't if CAS fails, but it isn't worth checking.) - pre_barrier(control(), base, adr, alias_idx, newval, value_type->is_oopptr(), T_OBJECT); + pre_barrier(control(), base, adr, alias_idx, newval, value_type->make_oopptr(), T_OBJECT); #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop()) { Node *newval_enc = _gvn.transform(new (C, 2) EncodePNode(newval, newval->bottom_type()->make_narrowoop())); diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 19e486d83a9..40675d41cbc 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -1565,7 +1565,7 @@ void Parse::do_one_bytecode() { c = pop(); // Oop to store b = pop(); // index (already used) a = pop(); // the array itself - const TypeOopPtr* elemtype = _gvn.type(a)->is_aryptr()->elem()->is_oopptr(); + const TypeOopPtr* elemtype = _gvn.type(a)->is_aryptr()->elem()->make_oopptr(); const TypeAryPtr* adr_type = TypeAryPtr::OOPS; Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT); break; diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 960b95c1c9c..0869ee6b634 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -361,7 +361,7 @@ Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, in guarantee(length_con >= 0, "non-constant multianewarray"); ciArrayKlass* array_klass_1 = array_klass->as_obj_array_klass()->element_klass()->as_array_klass(); const TypePtr* adr_type = TypeAryPtr::OOPS; - const TypeOopPtr* elemtype = _gvn.type(array)->is_aryptr()->elem()->is_oopptr(); + const TypeOopPtr* elemtype = _gvn.type(array)->is_aryptr()->elem()->make_oopptr(); const intptr_t header = arrayOopDesc::base_offset_in_bytes(T_OBJECT); for (jint i = 0; i < length_con; i++) { Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs); diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 3c32c348c7e..1db520a4254 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -3484,27 +3484,27 @@ const TypeNarrowOop* TypeNarrowOop::make(const TypePtr* type) { //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeNarrowOop::hash(void) const { - return _ooptype->hash() + 7; + return _ptrtype->hash() + 7; } bool TypeNarrowOop::eq( const Type *t ) const { const TypeNarrowOop* tc = t->isa_narrowoop(); if (tc != NULL) { - if (_ooptype->base() != tc->_ooptype->base()) { + if (_ptrtype->base() != tc->_ptrtype->base()) { return false; } - return tc->_ooptype->eq(_ooptype); + return tc->_ptrtype->eq(_ptrtype); } return false; } bool TypeNarrowOop::singleton(void) const { // TRUE if type is a singleton - return _ooptype->singleton(); + return _ptrtype->singleton(); } bool TypeNarrowOop::empty(void) const { - return _ooptype->empty(); + return _ptrtype->empty(); } //------------------------------xmeet------------------------------------------ @@ -3538,7 +3538,7 @@ const Type *TypeNarrowOop::xmeet( const Type *t ) const { return this; case NarrowOop: { - const Type* result = _ooptype->xmeet(t->make_ptr()); + const Type* result = _ptrtype->xmeet(t->make_ptr()); if (result->isa_ptr()) { return TypeNarrowOop::make(result->is_ptr()); } @@ -3554,13 +3554,13 @@ const Type *TypeNarrowOop::xmeet( const Type *t ) const { } const Type *TypeNarrowOop::xdual() const { // Compute dual right now. - const TypePtr* odual = _ooptype->dual()->is_ptr(); + const TypePtr* odual = _ptrtype->dual()->is_ptr(); return new TypeNarrowOop(odual); } const Type *TypeNarrowOop::filter( const Type *kills ) const { if (kills->isa_narrowoop()) { - const Type* ft =_ooptype->filter(kills->is_narrowoop()->_ooptype); + const Type* ft =_ptrtype->filter(kills->is_narrowoop()->_ptrtype); if (ft->empty()) return Type::TOP; // Canonical empty value if (ft->isa_ptr()) { @@ -3568,7 +3568,7 @@ const Type *TypeNarrowOop::filter( const Type *kills ) const { } return ft; } else if (kills->isa_ptr()) { - const Type* ft = _ooptype->join(kills); + const Type* ft = _ptrtype->join(kills); if (ft->empty()) return Type::TOP; // Canonical empty value return ft; @@ -3579,13 +3579,13 @@ const Type *TypeNarrowOop::filter( const Type *kills ) const { intptr_t TypeNarrowOop::get_con() const { - return _ooptype->get_con(); + return _ptrtype->get_con(); } #ifndef PRODUCT void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const { st->print("narrowoop: "); - _ooptype->dump2(d, depth, st); + _ptrtype->dump2(d, depth, st); } #endif diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 1683c384b65..06419149147 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -232,6 +232,11 @@ public: // Returns this ptr type or the equivalent ptr type for this compressed pointer. const TypePtr* make_ptr() const; + + // Returns this oopptr type or the equivalent oopptr type for this compressed pointer. + // Asserts if the underlying type is not an oopptr or narrowoop. + const TypeOopPtr* make_oopptr() const; + // Returns this compressed pointer or the equivalent compressed version // of this pointer type. const TypeNarrowOop* make_narrowoop() const; @@ -932,13 +937,13 @@ public: // between the normal and the compressed form. class TypeNarrowOop : public Type { protected: - const TypePtr* _ooptype; // Could be TypePtr::NULL_PTR + const TypePtr* _ptrtype; // Could be TypePtr::NULL_PTR - TypeNarrowOop( const TypePtr* ooptype): Type(NarrowOop), - _ooptype(ooptype) { - assert(ooptype->offset() == 0 || - ooptype->offset() == OffsetBot || - ooptype->offset() == OffsetTop, "no real offsets"); + TypeNarrowOop( const TypePtr* ptrtype): Type(NarrowOop), + _ptrtype(ptrtype) { + assert(ptrtype->offset() == 0 || + ptrtype->offset() == OffsetBot || + ptrtype->offset() == OffsetTop, "no real offsets"); } public: virtual bool eq( const Type *t ) const; @@ -962,8 +967,8 @@ public: } // returns the equivalent ptr type for this compressed pointer - const TypePtr *make_oopptr() const { - return _ooptype; + const TypePtr *get_ptrtype() const { + return _ptrtype; } static const TypeNarrowOop *BOTTOM; @@ -1150,10 +1155,14 @@ inline const TypeKlassPtr *Type::is_klassptr() const { } inline const TypePtr* Type::make_ptr() const { - return (_base == NarrowOop) ? is_narrowoop()->make_oopptr() : + return (_base == NarrowOop) ? is_narrowoop()->get_ptrtype() : (isa_ptr() ? is_ptr() : NULL); } +inline const TypeOopPtr* Type::make_oopptr() const { + return (_base == NarrowOop) ? is_narrowoop()->get_ptrtype()->is_oopptr() : is_oopptr(); +} + inline const TypeNarrowOop* Type::make_narrowoop() const { return (_base == NarrowOop) ? is_narrowoop() : (isa_ptr() ? TypeNarrowOop::make(is_ptr()) : NULL); From bb726c6f280ed074ac9100c10d96e3fa9397642c Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 1 Jul 2009 20:22:18 -0700 Subject: [PATCH 15/61] 6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14 Put missed reference to allocated array in copyOf() intrinsic into OopMap for the call slow_arraycopy(). Reviewed-by: never --- .../hotspot/ui/tree/OopTreeNodeAdapter.java | 2 + hotspot/make/solaris/makefiles/optimized.make | 2 +- hotspot/src/share/vm/opto/block.cpp | 3 + hotspot/src/share/vm/opto/block.hpp | 4 + hotspot/src/share/vm/opto/buildOopMap.cpp | 25 +- hotspot/src/share/vm/opto/gcm.cpp | 3 + hotspot/src/share/vm/opto/library_call.cpp | 334 +++++++++--------- 7 files changed, 189 insertions(+), 184 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/tree/OopTreeNodeAdapter.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/tree/OopTreeNodeAdapter.java index 4edcd787ad5..6ee998699bd 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/tree/OopTreeNodeAdapter.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/tree/OopTreeNodeAdapter.java @@ -161,6 +161,8 @@ public class OopTreeNodeAdapter extends FieldTreeNodeAdapter { child = new OopTreeNodeAdapter(field.getValue(getObj()), field.getID(), getTreeTableMode()); } catch (AddressException e) { child = new BadOopTreeNodeAdapter(field.getValueAsOopHandle(getObj()), field.getID(), getTreeTableMode()); + } catch (UnknownOopException e) { + child = new BadOopTreeNodeAdapter(field.getValueAsOopHandle(getObj()), field.getID(), getTreeTableMode()); } } ++curField; diff --git a/hotspot/make/solaris/makefiles/optimized.make b/hotspot/make/solaris/makefiles/optimized.make index 69848b73661..66609cae946 100644 --- a/hotspot/make/solaris/makefiles/optimized.make +++ b/hotspot/make/solaris/makefiles/optimized.make @@ -41,7 +41,7 @@ ifeq ($(COMPILER_REV_NUMERIC),509) endif # Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12) -ifeq ($(COMPILER_REV_NUMERIC),508)) +ifeq ($(COMPILER_REV_NUMERIC),508) OPT_CFLAGS/ciTypeFlow.o = $(OPT_CFLAGS/O2) endif # COMPILER_REV_NUMERIC == 508 diff --git a/hotspot/src/share/vm/opto/block.cpp b/hotspot/src/share/vm/opto/block.cpp index 10ceec302f9..7af5c4f57f6 100644 --- a/hotspot/src/share/vm/opto/block.cpp +++ b/hotspot/src/share/vm/opto/block.cpp @@ -357,6 +357,9 @@ PhaseCFG::PhaseCFG( Arena *a, RootNode *r, Matcher &m ) : #ifndef PRODUCT , _trace_opto_pipelining(TraceOptoPipelining || C->method_has_option("TraceOptoPipelining")) #endif +#ifdef ASSERT + , _raw_oops(a) +#endif { ResourceMark rm; // I'll need a few machine-specific GotoNodes. Make an Ideal GotoNode, diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index aac5105d66a..93940b466c3 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -380,6 +380,10 @@ class PhaseCFG : public Phase { bool _trace_opto_pipelining; // tracing flag #endif +#ifdef ASSERT + Unique_Node_List _raw_oops; +#endif + // Build dominators void Dominators(); diff --git a/hotspot/src/share/vm/opto/buildOopMap.cpp b/hotspot/src/share/vm/opto/buildOopMap.cpp index 9401e024a7c..81ad6b7dbee 100644 --- a/hotspot/src/share/vm/opto/buildOopMap.cpp +++ b/hotspot/src/share/vm/opto/buildOopMap.cpp @@ -74,9 +74,11 @@ struct OopFlow : public ResourceObj { // this block. Block *_b; // Block for this struct OopFlow *_next; // Next free OopFlow + // or NULL if dead/conflict + Compile* C; - OopFlow( short *callees, Node **defs ) : _callees(callees), _defs(defs), - _b(NULL), _next(NULL) { } + OopFlow( short *callees, Node **defs, Compile* c ) : _callees(callees), _defs(defs), + _b(NULL), _next(NULL), C(c) { } // Given reaching-defs for this block start, compute it for this block end void compute_reach( PhaseRegAlloc *regalloc, int max_reg, Dict *safehash ); @@ -88,7 +90,7 @@ struct OopFlow : public ResourceObj { void clone( OopFlow *flow, int max_size); // Make a new OopFlow from scratch - static OopFlow *make( Arena *A, int max_size ); + static OopFlow *make( Arena *A, int max_size, Compile* C ); // Build an oopmap from the current flow info OopMap *build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, int* live ); @@ -180,11 +182,11 @@ void OopFlow::clone( OopFlow *flow, int max_size ) { } //------------------------------make------------------------------------------- -OopFlow *OopFlow::make( Arena *A, int max_size ) { +OopFlow *OopFlow::make( Arena *A, int max_size, Compile* C ) { short *callees = NEW_ARENA_ARRAY(A,short,max_size+1); Node **defs = NEW_ARENA_ARRAY(A,Node*,max_size+1); debug_only( memset(defs,0,(max_size+1)*sizeof(Node*)) ); - OopFlow *flow = new (A) OopFlow(callees+1, defs+1); + OopFlow *flow = new (A) OopFlow(callees+1, defs+1, C); assert( &flow->_callees[OptoReg::Bad] == callees, "Ok to index at OptoReg::Bad" ); assert( &flow->_defs [OptoReg::Bad] == defs , "Ok to index at OptoReg::Bad" ); return flow; @@ -288,7 +290,7 @@ OopMap *OopFlow::build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, i m = m->in(idx); } } - guarantee( 0, "must find derived/base pair" ); + guarantee( 0, "must find derived/base pair" ); } found: ; Node *base = n->in(i+1); // Base is other half of pair @@ -347,6 +349,13 @@ OopMap *OopFlow::build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, i } else { // Other - some reaching non-oop value omap->set_value( r); +#ifdef ASSERT + if( t->isa_rawptr() && C->cfg()->_raw_oops.member(def) ) { + def->dump(); + n->dump(); + assert(false, "there should be a oop in OopMap instead of a live raw oop at safepoint"); + } +#endif } } @@ -562,7 +571,7 @@ void Compile::BuildOopMaps() { // Do the first block 'by hand' to prime the worklist Block *entry = _cfg->_blocks[1]; - OopFlow *rootflow = OopFlow::make(A,max_reg); + OopFlow *rootflow = OopFlow::make(A,max_reg,this); // Initialize to 'bottom' (not 'top') memset( rootflow->_callees, OptoReg::Bad, max_reg*sizeof(short) ); memset( rootflow->_defs , 0, max_reg*sizeof(Node*) ); @@ -628,7 +637,7 @@ void Compile::BuildOopMaps() { // Carry it forward. } else { // Draw a new OopFlow from the freelist if( !free_list ) - free_list = OopFlow::make(A,max_reg); + free_list = OopFlow::make(A,max_reg,C); flow = free_list; assert( flow->_b == NULL, "oopFlow is not free" ); free_list = flow->_next; diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index e502a74ea9d..0f596f7bfc7 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -1130,6 +1130,9 @@ void PhaseCFG::schedule_late(VectorSet &visited, Node_List &stack) { Node *def = self->in(1); if (def != NULL && def->bottom_type()->base() == Type::RawPtr) { early->add_inst(self); +#ifdef ASSERT + _raw_oops.push(def); +#endif continue; } break; diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index dc674f93821..2894cf9a505 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -165,6 +165,7 @@ class LibraryCallKit : public GraphKit { bool inline_native_getLength(); bool inline_array_copyOf(bool is_copyOfRange); bool inline_array_equals(); + void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark); bool inline_native_clone(bool is_virtual); bool inline_native_Reflection_getCallerClass(); bool inline_native_AtomicLong_get(); @@ -181,7 +182,6 @@ class LibraryCallKit : public GraphKit { Node* src, Node* src_offset, Node* dest, Node* dest_offset, Node* copy_length, - int nargs, // arguments on stack for debug info bool disjoint_bases = false, bool length_never_negative = false, RegionNode* slow_region = NULL); @@ -202,17 +202,16 @@ class LibraryCallKit : public GraphKit { void generate_slow_arraycopy(const TypePtr* adr_type, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length, - int nargs); + Node* copy_length); Node* generate_checkcast_arraycopy(const TypePtr* adr_type, Node* dest_elem_klass, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length, int nargs); + Node* copy_length); Node* generate_generic_arraycopy(const TypePtr* adr_type, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length, int nargs); + Node* copy_length); void generate_unchecked_arraycopy(const TypePtr* adr_type, BasicType basic_elem_type, bool disjoint_bases, @@ -3229,7 +3228,8 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { Node* orig_tail = _gvn.transform( new(C, 3) SubINode(orig_length, start) ); Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length); - Node* newcopy = new_array(klass_node, length, nargs); + const bool raw_mem_only = true; + Node* newcopy = new_array(klass_node, length, nargs, raw_mem_only); // Generate a direct call to the right arraycopy function(s). // We know the copy is disjoint but we might not know if the @@ -3240,7 +3240,7 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { bool length_never_negative = true; generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, original, start, newcopy, intcon(0), moved, - nargs, disjoint_bases, length_never_negative); + disjoint_bases, length_never_negative); push(newcopy); } @@ -3882,6 +3882,98 @@ bool LibraryCallKit::inline_unsafe_copyMemory() { return true; } +//------------------------clone_coping----------------------------------- +// Helper function for inline_native_clone. +void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark) { + assert(obj_size != NULL, ""); + Node* raw_obj = alloc_obj->in(1); + assert(alloc_obj->is_CheckCastPP() && raw_obj->is_Proj() && raw_obj->in(0)->is_Allocate(), ""); + + if (ReduceBulkZeroing) { + // We will be completely responsible for initializing this object - + // mark Initialize node as complete. + AllocateNode* alloc = AllocateNode::Ideal_allocation(alloc_obj, &_gvn); + // The object was just allocated - there should be no any stores! + guarantee(alloc != NULL && alloc->maybe_set_complete(&_gvn), ""); + } + + // Cast to Object for arraycopy. + // We can't use the original CheckCastPP since it should be moved + // after the arraycopy to prevent stores flowing above it. + Node* new_obj = new(C, 2) CheckCastPPNode(alloc_obj->in(0), raw_obj, + TypeInstPtr::NOTNULL); + new_obj = _gvn.transform(new_obj); + // Substitute in the locally valid dest_oop. + replace_in_map(alloc_obj, new_obj); + + // Copy the fastest available way. + // TODO: generate fields copies for small objects instead. + Node* src = obj; + Node* dest = new_obj; + Node* size = _gvn.transform(obj_size); + + // Exclude the header but include array length to copy by 8 bytes words. + // Can't use base_offset_in_bytes(bt) since basic type is unknown. + int base_off = is_array ? arrayOopDesc::length_offset_in_bytes() : + instanceOopDesc::base_offset_in_bytes(); + // base_off: + // 8 - 32-bit VM + // 12 - 64-bit VM, compressed oops + // 16 - 64-bit VM, normal oops + if (base_off % BytesPerLong != 0) { + assert(UseCompressedOops, ""); + if (is_array) { + // Exclude length to copy by 8 bytes words. + base_off += sizeof(int); + } else { + // Include klass to copy by 8 bytes words. + base_off = instanceOopDesc::klass_offset_in_bytes(); + } + assert(base_off % BytesPerLong == 0, "expect 8 bytes alignment"); + } + src = basic_plus_adr(src, base_off); + dest = basic_plus_adr(dest, base_off); + + // Compute the length also, if needed: + Node* countx = size; + countx = _gvn.transform( new (C, 3) SubXNode(countx, MakeConX(base_off)) ); + countx = _gvn.transform( new (C, 3) URShiftXNode(countx, intcon(LogBytesPerLong) )); + + const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; + bool disjoint_bases = true; + generate_unchecked_arraycopy(raw_adr_type, T_LONG, disjoint_bases, + src, NULL, dest, NULL, countx); + + // If necessary, emit some card marks afterwards. (Non-arrays only.) + if (card_mark) { + assert(!is_array, ""); + // Put in store barrier for any and all oops we are sticking + // into this object. (We could avoid this if we could prove + // that the object type contains no oop fields at all.) + Node* no_particular_value = NULL; + Node* no_particular_field = NULL; + int raw_adr_idx = Compile::AliasIdxRaw; + post_barrier(control(), + memory(raw_adr_type), + new_obj, + no_particular_field, + raw_adr_idx, + no_particular_value, + T_OBJECT, + false); + } + + // Move the original CheckCastPP after arraycopy. + _gvn.hash_delete(alloc_obj); + alloc_obj->set_req(0, control()); + // Replace raw memory edge with new CheckCastPP to have a live oop + // at safepoints instead of raw value. + assert(new_obj->is_CheckCastPP() && new_obj->in(1) == alloc_obj->in(1), "sanity"); + alloc_obj->set_req(1, new_obj); // cast to the original type + _gvn.hash_find_insert(alloc_obj); // put back into GVN table + // Restore in the locally valid dest_oop. + replace_in_map(new_obj, alloc_obj); +} //------------------------inline_native_clone---------------------------- // Here are the simple edge cases: @@ -3916,8 +4008,9 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { // paths into result_reg: enum { _slow_path = 1, // out-of-line call to clone method (virtual or not) - _objArray_path, // plain allocation, plus arrayof_oop_arraycopy - _fast_path, // plain allocation, plus a CopyArray operation + _objArray_path, // plain array allocation, plus arrayof_oop_arraycopy + _array_path, // plain array allocation, plus arrayof_long_arraycopy + _instance_path, // plain instance allocation, plus arrayof_long_arraycopy PATH_LIMIT }; RegionNode* result_reg = new(C, PATH_LIMIT) RegionNode(PATH_LIMIT); @@ -3932,18 +4025,6 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { int raw_adr_idx = Compile::AliasIdxRaw; const bool raw_mem_only = true; - // paths into alloc_reg (on the fast path, just before the CopyArray): - enum { _typeArray_alloc = 1, _instance_alloc, ALLOC_LIMIT }; - RegionNode* alloc_reg = new(C, ALLOC_LIMIT) RegionNode(ALLOC_LIMIT); - PhiNode* alloc_val = new(C, ALLOC_LIMIT) PhiNode(alloc_reg, raw_adr_type); - PhiNode* alloc_siz = new(C, ALLOC_LIMIT) PhiNode(alloc_reg, TypeX_X); - PhiNode* alloc_i_o = new(C, ALLOC_LIMIT) PhiNode(alloc_reg, Type::ABIO); - PhiNode* alloc_mem = new(C, ALLOC_LIMIT) PhiNode(alloc_reg, Type::MEMORY, - raw_adr_type); - record_for_igvn(alloc_reg); - - bool card_mark = false; // (see below) - Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)NULL); if (array_ctl != NULL) { // It's an array. @@ -3953,16 +4034,6 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { Node* obj_size = NULL; Node* alloc_obj = new_array(obj_klass, obj_length, nargs, raw_mem_only, &obj_size); - assert(obj_size != NULL, ""); - Node* raw_obj = alloc_obj->in(1); - assert(raw_obj->is_Proj() && raw_obj->in(0)->is_Allocate(), ""); - if (ReduceBulkZeroing) { - AllocateNode* alloc = AllocateNode::Ideal_allocation(alloc_obj, &_gvn); - if (alloc != NULL) { - // We will be completely responsible for initializing this object. - alloc->maybe_set_complete(&_gvn); - } - } if (!use_ReduceInitialCardMarks()) { // If it is an oop array, it requires very special treatment, @@ -3976,7 +4047,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { bool length_never_negative = true; generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, obj, intcon(0), alloc_obj, intcon(0), - obj_length, nargs, + obj_length, disjoint_bases, length_never_negative); result_reg->init_req(_objArray_path, control()); result_val->init_req(_objArray_path, alloc_obj); @@ -3991,19 +4062,24 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { // the object. // Otherwise, there are no card marks to worry about. - alloc_val->init_req(_typeArray_alloc, raw_obj); - alloc_siz->init_req(_typeArray_alloc, obj_size); - alloc_reg->init_req(_typeArray_alloc, control()); - alloc_i_o->init_req(_typeArray_alloc, i_o()); - alloc_mem->init_req(_typeArray_alloc, memory(raw_adr_type)); + + if (!stopped()) { + copy_to_clone(obj, alloc_obj, obj_size, true, false); + + // Present the results of the copy. + result_reg->init_req(_array_path, control()); + result_val->init_req(_array_path, alloc_obj); + result_i_o ->set_req(_array_path, i_o()); + result_mem ->set_req(_array_path, reset_memory()); + } } - // We only go to the fast case code if we pass a number of guards. + // We only go to the instance fast case code if we pass a number of guards. // The paths which do not pass are accumulated in the slow_region. RegionNode* slow_region = new (C, 1) RegionNode(1); record_for_igvn(slow_region); if (!stopped()) { - // It's an instance. Make the slow-path tests. + // It's an instance (we did array above). Make the slow-path tests. // If this is a virtual call, we generate a funny guard. We grab // the vtable entry corresponding to clone() from the target object. // If the target method which we are calling happens to be the @@ -4030,25 +4106,14 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { PreserveJVMState pjvms(this); Node* obj_size = NULL; Node* alloc_obj = new_instance(obj_klass, NULL, raw_mem_only, &obj_size); - assert(obj_size != NULL, ""); - Node* raw_obj = alloc_obj->in(1); - assert(raw_obj->is_Proj() && raw_obj->in(0)->is_Allocate(), ""); - if (ReduceBulkZeroing) { - AllocateNode* alloc = AllocateNode::Ideal_allocation(alloc_obj, &_gvn); - if (alloc != NULL && !alloc->maybe_set_complete(&_gvn)) - alloc = NULL; - } - if (!use_ReduceInitialCardMarks()) { - // Put in store barrier for any and all oops we are sticking - // into this object. (We could avoid this if we could prove - // that the object type contains no oop fields at all.) - card_mark = true; - } - alloc_val->init_req(_instance_alloc, raw_obj); - alloc_siz->init_req(_instance_alloc, obj_size); - alloc_reg->init_req(_instance_alloc, control()); - alloc_i_o->init_req(_instance_alloc, i_o()); - alloc_mem->init_req(_instance_alloc, memory(raw_adr_type)); + + copy_to_clone(obj, alloc_obj, obj_size, false, !use_ReduceInitialCardMarks()); + + // Present the results of the slow call. + result_reg->init_req(_instance_path, control()); + result_val->init_req(_instance_path, alloc_obj); + result_i_o ->set_req(_instance_path, i_o()); + result_mem ->set_req(_instance_path, reset_memory()); } // Generate code for the slow case. We make a call to clone(). @@ -4064,82 +4129,12 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { result_mem ->set_req(_slow_path, reset_memory()); } - // The object is allocated, as an array and/or an instance. Now copy it. - set_control( _gvn.transform(alloc_reg) ); - set_i_o( _gvn.transform(alloc_i_o) ); - set_memory( _gvn.transform(alloc_mem), raw_adr_type ); - Node* raw_obj = _gvn.transform(alloc_val); - - if (!stopped()) { - // Copy the fastest available way. - // (No need for PreserveJVMState, since we're using it all up now.) - // TODO: generate fields/elements copies for small objects instead. - Node* src = obj; - Node* dest = raw_obj; - Node* size = _gvn.transform(alloc_siz); - - // Exclude the header. - int base_off = instanceOopDesc::base_offset_in_bytes(); - if (UseCompressedOops) { - assert(base_off % BytesPerLong != 0, "base with compressed oops"); - // With compressed oops base_offset_in_bytes is 12 which creates - // the gap since countx is rounded by 8 bytes below. - // Copy klass and the gap. - base_off = instanceOopDesc::klass_offset_in_bytes(); - } - src = basic_plus_adr(src, base_off); - dest = basic_plus_adr(dest, base_off); - - // Compute the length also, if needed: - Node* countx = size; - countx = _gvn.transform( new (C, 3) SubXNode(countx, MakeConX(base_off)) ); - countx = _gvn.transform( new (C, 3) URShiftXNode(countx, intcon(LogBytesPerLong) )); - - // Select an appropriate instruction to initialize the range. - // The CopyArray instruction (if supported) can be optimized - // into a discrete set of scalar loads and stores. - bool disjoint_bases = true; - generate_unchecked_arraycopy(raw_adr_type, T_LONG, disjoint_bases, - src, NULL, dest, NULL, countx); - - // Now that the object is properly initialized, type it as an oop. - // Use a secondary InitializeNode memory barrier. - InitializeNode* init = insert_mem_bar_volatile(Op_Initialize, raw_adr_idx, - raw_obj)->as_Initialize(); - init->set_complete(&_gvn); // (there is no corresponding AllocateNode) - Node* new_obj = new(C, 2) CheckCastPPNode(control(), raw_obj, - TypeInstPtr::NOTNULL); - new_obj = _gvn.transform(new_obj); - - // If necessary, emit some card marks afterwards. (Non-arrays only.) - if (card_mark) { - Node* no_particular_value = NULL; - Node* no_particular_field = NULL; - post_barrier(control(), - memory(raw_adr_type), - new_obj, - no_particular_field, - raw_adr_idx, - no_particular_value, - T_OBJECT, - false); - } - // Present the results of the slow call. - result_reg->init_req(_fast_path, control()); - result_val->init_req(_fast_path, new_obj); - result_i_o ->set_req(_fast_path, i_o()); - result_mem ->set_req(_fast_path, reset_memory()); - } - // Return the combined state. set_control( _gvn.transform(result_reg) ); set_i_o( _gvn.transform(result_i_o) ); set_all_memory( _gvn.transform(result_mem) ); - // Cast the result to a sharper type, since we know what clone does. - Node* new_obj = _gvn.transform(result_val); - Node* cast = new (C, 2) CheckCastPPNode(control(), new_obj, toop); - push(_gvn.transform(cast)); + push(_gvn.transform(result_val)); return true; } @@ -4278,8 +4273,7 @@ bool LibraryCallKit::inline_arraycopy() { // Call StubRoutines::generic_arraycopy stub. generate_arraycopy(TypeRawPtr::BOTTOM, T_CONFLICT, - src, src_offset, dest, dest_offset, length, - nargs); + src, src_offset, dest, dest_offset, length); // Do not let reads from the destination float above the arraycopy. // Since we cannot type the arrays, we don't know which slices @@ -4302,8 +4296,7 @@ bool LibraryCallKit::inline_arraycopy() { // The component types are not the same or are not recognized. Punt. // (But, avoid the native method wrapper to JVM_ArrayCopy.) generate_slow_arraycopy(TypePtr::BOTTOM, - src, src_offset, dest, dest_offset, length, - nargs); + src, src_offset, dest, dest_offset, length); return true; } @@ -4360,7 +4353,7 @@ bool LibraryCallKit::inline_arraycopy() { const TypePtr* adr_type = TypeAryPtr::get_array_body_type(dest_elem); generate_arraycopy(adr_type, dest_elem, src, src_offset, dest, dest_offset, length, - nargs, false, false, slow_region); + false, false, slow_region); return true; } @@ -4405,7 +4398,6 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, Node* src, Node* src_offset, Node* dest, Node* dest_offset, Node* copy_length, - int nargs, bool disjoint_bases, bool length_never_negative, RegionNode* slow_region) { @@ -4417,7 +4409,6 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, Node* original_dest = dest; AllocateArrayNode* alloc = NULL; // used for zeroing, if needed - Node* raw_dest = NULL; // used before zeroing, if needed bool must_clear_dest = false; // See if this is the initialization of a newly-allocated array. @@ -4436,15 +4427,18 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, // "You break it, you buy it." InitializeNode* init = alloc->initialization(); assert(init->is_complete(), "we just did this"); - assert(dest->Opcode() == Op_CheckCastPP, "sanity"); + assert(dest->is_CheckCastPP(), "sanity"); assert(dest->in(0)->in(0) == init, "dest pinned"); - raw_dest = dest->in(1); // grab the raw pointer! - original_dest = dest; - dest = raw_dest; + + // Cast to Object for arraycopy. + // We can't use the original CheckCastPP since it should be moved + // after the arraycopy to prevent stores flowing above it. + Node* new_obj = new(C, 2) CheckCastPPNode(dest->in(0), dest->in(1), + TypeInstPtr::NOTNULL); + dest = _gvn.transform(new_obj); + // Substitute in the locally valid dest_oop. + replace_in_map(original_dest, dest); adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory - // Decouple the original InitializeNode, turning it into a simple membar. - // We will build a new one at the end of this routine. - init->set_req(InitializeNode::RawAddress, top()); // From this point on, every exit path is responsible for // initializing any non-copied parts of the object to zero. must_clear_dest = true; @@ -4487,7 +4481,7 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, assert(!must_clear_dest, ""); Node* cv = generate_generic_arraycopy(adr_type, src, src_offset, dest, dest_offset, - copy_length, nargs); + copy_length); if (cv == NULL) cv = intcon(-1); // failure (no stub available) checked_control = control(); checked_i_o = i_o(); @@ -4519,6 +4513,14 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, } } + // Use a secondary InitializeNode as raw memory barrier. + // Currently it is needed only on this path since other + // paths have stub or runtime calls as raw memory barriers. + InitializeNode* init = insert_mem_bar_volatile(Op_Initialize, + Compile::AliasIdxRaw, + top())->as_Initialize(); + init->set_complete(&_gvn); // (there is no corresponding AllocateNode) + // Present the results of the fast call. result_region->init_req(zero_path, control()); result_i_o ->init_req(zero_path, i_o()); @@ -4637,8 +4639,7 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, Node* cv = generate_checkcast_arraycopy(adr_type, dest_elem_klass, src, src_offset, dest, dest_offset, - copy_length, - nargs); + copy_length); if (cv == NULL) cv = intcon(-1); // failure (no stub available) checked_control = control(); checked_i_o = i_o(); @@ -4700,8 +4701,8 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, slow_i_o2 ->init_req(1, slow_i_o); slow_mem2 ->init_req(1, slow_mem); slow_reg2 ->init_req(2, control()); - slow_i_o2 ->init_req(2, i_o()); - slow_mem2 ->init_req(2, memory(adr_type)); + slow_i_o2 ->init_req(2, checked_i_o); + slow_mem2 ->init_req(2, checked_mem); slow_control = _gvn.transform(slow_reg2); slow_i_o = _gvn.transform(slow_i_o2); @@ -4746,21 +4747,9 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, alloc->in(AllocateNode::AllocSize)); } - if (dest != original_dest) { - // Promote from rawptr to oop, so it looks right in the call's GC map. - dest = _gvn.transform( new(C,2) CheckCastPPNode(control(), dest, - TypeInstPtr::NOTNULL) ); - - // Edit the call's debug-info to avoid referring to original_dest. - // (The problem with original_dest is that it isn't ready until - // after the InitializeNode completes, but this stuff is before.) - // Substitute in the locally valid dest_oop. - replace_in_map(original_dest, dest); - } - generate_slow_arraycopy(adr_type, src, src_offset, dest, dest_offset, - copy_length, nargs); + copy_length); result_region->init_req(slow_call_path, control()); result_i_o ->init_req(slow_call_path, i_o()); @@ -4780,16 +4769,16 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, if (dest != original_dest) { // Pin the "finished" array node after the arraycopy/zeroing operations. - // Use a secondary InitializeNode memory barrier. - InitializeNode* init = insert_mem_bar_volatile(Op_Initialize, - Compile::AliasIdxRaw, - raw_dest)->as_Initialize(); - init->set_complete(&_gvn); // (there is no corresponding AllocateNode) _gvn.hash_delete(original_dest); original_dest->set_req(0, control()); + // Replace raw memory edge with new CheckCastPP to have a live oop + // at safepoints instead of raw value. + assert(dest->is_CheckCastPP() && dest->in(1) == original_dest->in(1), "sanity"); + original_dest->set_req(1, dest); // cast to the original type _gvn.hash_find_insert(original_dest); // put back into GVN table + // Restore in the locally valid dest_oop. + replace_in_map(dest, original_dest); } - // The memory edges above are precise in order to model effects around // array copies accurately to allow value numbering of field loads around // arraycopy. Such field loads, both before and after, are common in Java @@ -5073,16 +5062,13 @@ void LibraryCallKit::generate_slow_arraycopy(const TypePtr* adr_type, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length, - int nargs) { - _sp += nargs; // any deopt will start just before call to enclosing method + Node* copy_length) { Node* call = make_runtime_call(RC_NO_LEAF | RC_UNCOMMON, OptoRuntime::slow_arraycopy_Type(), OptoRuntime::slow_arraycopy_Java(), "slow_arraycopy", adr_type, src, src_offset, dest, dest_offset, copy_length); - _sp -= nargs; // Handle exceptions thrown by this fellow: make_slow_call_ex(call, env()->Throwable_klass(), false); @@ -5094,8 +5080,7 @@ LibraryCallKit::generate_checkcast_arraycopy(const TypePtr* adr_type, Node* dest_elem_klass, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length, - int nargs) { + Node* copy_length) { if (stopped()) return NULL; address copyfunc_addr = StubRoutines::checkcast_arraycopy(); @@ -5136,8 +5121,7 @@ Node* LibraryCallKit::generate_generic_arraycopy(const TypePtr* adr_type, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length, - int nargs) { + Node* copy_length) { if (stopped()) return NULL; address copyfunc_addr = StubRoutines::generic_arraycopy(); From 2914141733e7a560d030168c5a4ec82dbe444aa0 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 2 Jul 2009 19:48:11 +0400 Subject: [PATCH 16/61] 6380849: RFE: Automatic discovery of PersistanceDelegates Reviewed-by: rupashka, alexp --- .../com/sun/beans/finder/BeanInfoFinder.java | 102 +++++++++++++ .../com/sun/beans/finder/InstanceFinder.java | 111 ++++++++++++++ .../finder/PersistenceDelegateFinder.java | 63 ++++++++ .../beans/finder/PropertyEditorFinder.java | 81 ++++++++++ jdk/src/share/classes/java/beans/Encoder.java | 23 +-- .../classes/java/beans/Introspector.java | 101 ++++--------- .../java/beans/PropertyEditorManager.java | 96 ++++-------- .../Introspector/6380849/TestBeanInfo.java | 102 +++++++++++++ .../Introspector/6380849/beans/FirstBean.java | 4 + .../6380849/beans/FirstBeanBeanInfo.java | 11 ++ .../6380849/beans/SecondBean.java | 4 + .../Introspector/6380849/beans/ThirdBean.java | 4 + .../6380849/infos/SecondBeanBeanInfo.java | 13 ++ .../6380849/infos/ThirdBeanBeanInfo.java | 11 ++ .../PropertyEditor/6380849/FirstBean.java | 2 + .../6380849/FirstBeanEditor.java | 4 + .../PropertyEditor/6380849/SecondBean.java | 2 + .../6380849/TestPropertyEditor.java | 141 ++++++++++++++++++ .../PropertyEditor/6380849/ThirdBean.java | 2 + .../6380849/editors/SecondBeanEditor.java | 6 + .../6380849/editors/ThirdBeanEditor.java | 6 + .../java/beans/XMLEncoder/6380849/Bean.java | 2 + .../6380849/BeanPersistenceDelegate.java | 5 + .../6380849/TestPersistenceDelegate.java | 60 ++++++++ 24 files changed, 811 insertions(+), 145 deletions(-) create mode 100644 jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java create mode 100644 jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java create mode 100644 jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java create mode 100644 jdk/test/java/beans/Introspector/6380849/beans/FirstBean.java create mode 100644 jdk/test/java/beans/Introspector/6380849/beans/FirstBeanBeanInfo.java create mode 100644 jdk/test/java/beans/Introspector/6380849/beans/SecondBean.java create mode 100644 jdk/test/java/beans/Introspector/6380849/beans/ThirdBean.java create mode 100644 jdk/test/java/beans/Introspector/6380849/infos/SecondBeanBeanInfo.java create mode 100644 jdk/test/java/beans/Introspector/6380849/infos/ThirdBeanBeanInfo.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/FirstBean.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/FirstBeanEditor.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/SecondBean.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/TestPropertyEditor.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/ThirdBean.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/editors/SecondBeanEditor.java create mode 100644 jdk/test/java/beans/PropertyEditor/6380849/editors/ThirdBeanEditor.java create mode 100644 jdk/test/java/beans/XMLEncoder/6380849/Bean.java create mode 100644 jdk/test/java/beans/XMLEncoder/6380849/BeanPersistenceDelegate.java create mode 100644 jdk/test/java/beans/XMLEncoder/6380849/TestPersistenceDelegate.java diff --git a/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java b/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java new file mode 100644 index 00000000000..3e1c37c2d57 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java @@ -0,0 +1,102 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.beans.BeanDescriptor; +import java.beans.BeanInfo; +import java.beans.MethodDescriptor; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; + +/** + * This is utility class that provides functionality + * to find a {@link BeanInfo} for a JavaBean specified by its type. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class BeanInfoFinder + extends InstanceFinder { + + private static final String DEFAULT = "sun.beans.infos"; + + public BeanInfoFinder() { + super(BeanInfo.class, true, "BeanInfo", DEFAULT); + } + + private static boolean isValid(Class type, Method method) { + return (method != null) && type.equals(method.getDeclaringClass()); + } + + @Override + protected BeanInfo instantiate(Class type, String name) { + BeanInfo info = super.instantiate(type, name); + if (info != null) { + // make sure that the returned BeanInfo matches the class + BeanDescriptor bd = info.getBeanDescriptor(); + if (bd != null) { + if (type.equals(bd.getBeanClass())) { + return info; + } + } + else { + PropertyDescriptor[] pds = info.getPropertyDescriptors(); + if (pds != null) { + for (PropertyDescriptor pd : pds) { + Method method = pd.getReadMethod(); + if (method == null) { + method = pd.getWriteMethod(); + } + if (isValid(type, method)) { + return info; + } + } + } + else { + MethodDescriptor[] mds = info.getMethodDescriptors(); + if (mds != null) { + for (MethodDescriptor md : mds) { + if (isValid(type, md.getMethod())) { + return info; + } + } + } + } + } + } + return null; + } + + @Override + protected BeanInfo instantiate(Class type, String prefix, String name) { + // this optimization will only use the BeanInfo search path + // if is has changed from the original + // or trying to get the ComponentBeanInfo + return !DEFAULT.equals(prefix) || "ComponentBeanInfo".equals(name) + ? super.instantiate(type, prefix, name) + : null; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java b/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java new file mode 100644 index 00000000000..ddf4b80264b --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java @@ -0,0 +1,111 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +/** + * This is utility class that provides basic functionality + * to find an auxiliary class for a JavaBean specified by its type. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +class InstanceFinder { + + private static final String[] EMPTY = { }; + + private final Class type; + private final boolean allow; + private final String suffix; + private String[] packages; + + InstanceFinder(Class type, boolean allow, String suffix, String... packages) { + this.type = type; + this.allow = allow; + this.suffix = suffix; + this.packages = packages.clone(); + } + + public String[] getPackages() { + return (this.packages.length > 0) + ? this.packages.clone() + : this.packages; + } + + public void setPackages(String... packages) { + this.packages = (packages != null) && (packages.length > 0) + ? packages.clone() + : EMPTY; + } + + public T find(Class type) { + if (type == null) { + return null; + } + String name = type.getName() + this.suffix; + T object = instantiate(type, name); + if (object != null) { + return object; + } + if (this.allow) { + object = instantiate(type, null); + if (object != null) { + return object; + } + } + int index = name.lastIndexOf('.') + 1; + if (index > 0) { + name = name.substring(index); + } + for (String prefix : this.packages) { + object = instantiate(type, prefix, name); + if (object != null) { + return object; + } + } + return null; + } + + protected T instantiate(Class type, String name) { + if (type != null) { + try { + if (name != null) { + type = ClassFinder.findClass(name, type.getClassLoader()); + } + if (this.type.isAssignableFrom(type)) { + return (T) type.newInstance(); + } + } + catch (Exception exception) { + // ignore any exceptions + } + } + return null; + } + + protected T instantiate(Class type, String prefix, String name) { + return instantiate(type, prefix + '.' + name); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java b/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java new file mode 100644 index 00000000000..f7638b65ca7 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java @@ -0,0 +1,63 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.beans.PersistenceDelegate; +import java.util.HashMap; +import java.util.Map; + +/** + * This is utility class that provides functionality + * to find a {@link PersistenceDelegate} for a JavaBean specified by its type. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class PersistenceDelegateFinder + extends InstanceFinder { + + private final Map, PersistenceDelegate> registry; + + public PersistenceDelegateFinder() { + super(PersistenceDelegate.class, true, "PersistenceDelegate"); + this.registry = new HashMap, PersistenceDelegate>(); + } + + public void register(Class type, PersistenceDelegate delegate) { + if (delegate != null) { + this.registry.put(type, delegate); + } + else { + this.registry.remove(type); + } + } + + @Override + public PersistenceDelegate find(Class type) { + PersistenceDelegate delegate = this.registry.get(type); + return (delegate != null) ? delegate : super.find(type); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java b/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java new file mode 100644 index 00000000000..604952a1a23 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java @@ -0,0 +1,81 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import com.sun.beans.WeakCache; + +import java.beans.PropertyEditor; + +import sun.beans.editors.BooleanEditor; +import sun.beans.editors.ByteEditor; +import sun.beans.editors.DoubleEditor; +import sun.beans.editors.EnumEditor; +import sun.beans.editors.FloatEditor; +import sun.beans.editors.IntegerEditor; +import sun.beans.editors.LongEditor; +import sun.beans.editors.ShortEditor; + +/** + * This is utility class that provides functionality + * to find a {@link PropertyEditor} for a JavaBean specified by its type. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class PropertyEditorFinder + extends InstanceFinder { + + private final WeakCache, Class> registry; + + public PropertyEditorFinder() { + super(PropertyEditor.class, false, "Editor", "sun.beans.editors"); + + this.registry = new WeakCache, Class>(); + this.registry.put(Byte.TYPE, ByteEditor.class); + this.registry.put(Short.TYPE, ShortEditor.class); + this.registry.put(Integer.TYPE, IntegerEditor.class); + this.registry.put(Long.TYPE, LongEditor.class); + this.registry.put(Boolean.TYPE, BooleanEditor.class); + this.registry.put(Float.TYPE, FloatEditor.class); + this.registry.put(Double.TYPE, DoubleEditor.class); + } + + public void register(Class type, Class editor) { + this.registry.put(type, editor); + } + + @Override + public PropertyEditor find(Class type) { + PropertyEditor editor = instantiate(this.registry.get(type), null); + if (editor == null) { + editor = super.find(type); + if ((editor == null) && (null != type.getEnumConstants())) { + editor = new EnumEditor(type); + } + } + return editor; + } +} diff --git a/jdk/src/share/classes/java/beans/Encoder.java b/jdk/src/share/classes/java/beans/Encoder.java index 2fcd5b5c727..92e3d695bcb 100644 --- a/jdk/src/share/classes/java/beans/Encoder.java +++ b/jdk/src/share/classes/java/beans/Encoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,8 @@ */ package java.beans; -import java.util.Collections; +import com.sun.beans.finder.PersistenceDelegateFinder; + import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Map; @@ -45,8 +46,7 @@ import java.util.Map; */ public class Encoder { - private final Map, PersistenceDelegate> delegates - = Collections.synchronizedMap(new HashMap, PersistenceDelegate>()); + private final PersistenceDelegateFinder finder = new PersistenceDelegateFinder(); private Map bindings = new IdentityHashMap(); private ExceptionListener exceptionListener; boolean executeStatements = true; @@ -166,8 +166,13 @@ public class Encoder { * @see java.beans.BeanInfo#getBeanDescriptor */ public PersistenceDelegate getPersistenceDelegate(Class type) { - PersistenceDelegate pd = this.delegates.get(type); - return (pd != null) ? pd : MetaData.getPersistenceDelegate(type); + synchronized (this.finder) { + PersistenceDelegate pd = this.finder.find(type); + if (pd != null) { + return pd; + } + } + return MetaData.getPersistenceDelegate(type); } /** @@ -184,10 +189,8 @@ public class Encoder { public void setPersistenceDelegate(Class type, PersistenceDelegate persistenceDelegate) { - if (persistenceDelegate != null) { - this.delegates.put(type, persistenceDelegate); - } else { - this.delegates.remove(type); + synchronized (this.finder) { + this.finder.register(type, persistenceDelegate); } } diff --git a/jdk/src/share/classes/java/beans/Introspector.java b/jdk/src/share/classes/java/beans/Introspector.java index 6a50cbe7f7d..b43911cf123 100644 --- a/jdk/src/share/classes/java/beans/Introspector.java +++ b/jdk/src/share/classes/java/beans/Introspector.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package java.beans; +import com.sun.beans.finder.BeanInfoFinder; import com.sun.beans.finder.ClassFinder; import java.lang.ref.Reference; @@ -45,6 +46,8 @@ import java.util.EventListener; import java.util.List; import java.util.WeakHashMap; import java.util.TreeMap; + +import sun.awt.AppContext; import sun.reflect.misc.ReflectUtil; /** @@ -137,10 +140,6 @@ public class Introspector { // events maps from String names to EventSetDescriptors private Map events; - private final static String DEFAULT_INFO_PATH = "sun.beans.infos"; - - private static String[] searchPath = { DEFAULT_INFO_PATH }; - private final static EventSetDescriptor[] EMPTY_EVENTSETDESCRIPTORS = new EventSetDescriptor[0]; static final String ADD_PREFIX = "add"; @@ -149,7 +148,7 @@ public class Introspector { static final String SET_PREFIX = "set"; static final String IS_PREFIX = "is"; - private static final String BEANINFO_SUFFIX = "BeanInfo"; + private static final Object FINDER_KEY = new Object(); //====================================================================== // Public methods @@ -309,13 +308,11 @@ public class Introspector { * Sun implementation initially sets to {"sun.beans.infos"}. */ - public static synchronized String[] getBeanInfoSearchPath() { - // Return a copy of the searchPath. - String result[] = new String[searchPath.length]; - for (int i = 0; i < searchPath.length; i++) { - result[i] = searchPath[i]; + public static String[] getBeanInfoSearchPath() { + BeanInfoFinder finder = getFinder(); + synchronized (finder) { + return finder.getPackages(); } - return result; } /** @@ -334,12 +331,15 @@ public class Introspector { * @see SecurityManager#checkPropertiesAccess */ - public static synchronized void setBeanInfoSearchPath(String path[]) { + public static void setBeanInfoSearchPath(String[] path) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPropertiesAccess(); } - searchPath = path; + BeanInfoFinder finder = getFinder(); + synchronized (finder) { + finder.setPackages(path); + } } @@ -447,67 +447,14 @@ public class Introspector { * then it checks to see if the class is its own BeanInfo. Finally, * the BeanInfo search path is prepended to the class and searched. * + * @param beanClass the class type of the bean * @return Instance of an explicit BeanInfo class or null if one isn't found. */ - private static synchronized BeanInfo findExplicitBeanInfo(Class beanClass) { - String name = beanClass.getName() + BEANINFO_SUFFIX; - try { - return (java.beans.BeanInfo)instantiate(beanClass, name); - } catch (Exception ex) { - // Just drop through - + private static BeanInfo findExplicitBeanInfo(Class beanClass) { + BeanInfoFinder finder = getFinder(); + synchronized (finder) { + return finder.find(beanClass); } - // Now try checking if the bean is its own BeanInfo. - try { - if (isSubclass(beanClass, java.beans.BeanInfo.class)) { - return (java.beans.BeanInfo)beanClass.newInstance(); - } - } catch (Exception ex) { - // Just drop through - } - // Now try looking for .fooBeanInfo - name = name.substring(name.lastIndexOf('.')+1); - - for (int i = 0; i < searchPath.length; i++) { - // This optimization will only use the BeanInfo search path if is has changed - // from the original or trying to get the ComponentBeanInfo. - if (!DEFAULT_INFO_PATH.equals(searchPath[i]) || - DEFAULT_INFO_PATH.equals(searchPath[i]) && "ComponentBeanInfo".equals(name)) { - try { - String fullName = searchPath[i] + "." + name; - java.beans.BeanInfo bi = (java.beans.BeanInfo)instantiate(beanClass, fullName); - - // Make sure that the returned BeanInfo matches the class. - if (bi.getBeanDescriptor() != null) { - if (bi.getBeanDescriptor().getBeanClass() == beanClass) { - return bi; - } - } else if (bi.getPropertyDescriptors() != null) { - PropertyDescriptor[] pds = bi.getPropertyDescriptors(); - for (int j = 0; j < pds.length; j++) { - Method method = pds[j].getReadMethod(); - if (method == null) { - method = pds[j].getWriteMethod(); - } - if (method != null && method.getDeclaringClass() == beanClass) { - return bi; - } - } - } else if (bi.getMethodDescriptors() != null) { - MethodDescriptor[] mds = bi.getMethodDescriptors(); - for (int j = 0; j < mds.length; j++) { - Method method = mds[j].getMethod(); - if (method != null && method.getDeclaringClass() == beanClass) { - return bi; - } - } - } - } catch (Exception ex) { - // Silently ignore any errors. - } - } - } - return null; } /** @@ -1483,6 +1430,16 @@ public class Introspector { return false; } + private static BeanInfoFinder getFinder() { + AppContext context = AppContext.getAppContext(); + Object object = context.get(FINDER_KEY); + if (object instanceof BeanInfoFinder) { + return (BeanInfoFinder) object; + } + BeanInfoFinder finder = new BeanInfoFinder(); + context.put(FINDER_KEY, finder); + return finder; + } /** * Try to create an instance of a named class. diff --git a/jdk/src/share/classes/java/beans/PropertyEditorManager.java b/jdk/src/share/classes/java/beans/PropertyEditorManager.java index a456c2bff54..d884e9f0c0c 100644 --- a/jdk/src/share/classes/java/beans/PropertyEditorManager.java +++ b/jdk/src/share/classes/java/beans/PropertyEditorManager.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ package java.beans; -import com.sun.beans.WeakCache; -import sun.beans.editors.*; +import com.sun.beans.finder.PropertyEditorFinder; +import sun.awt.AppContext; /** * The PropertyEditorManager can be used to locate a property editor for @@ -55,6 +55,8 @@ import sun.beans.editors.*; public class PropertyEditorManager { + private static final Object FINDER_KEY = new Object(); + /** * Registers an editor class to edit values of the given target class. * If the editor class is {@code null}, @@ -74,12 +76,15 @@ public class PropertyEditorManager { * * @see SecurityManager#checkPropertiesAccess */ - public static synchronized void registerEditor(Class targetType, Class editorClass) { + public static void registerEditor(Class targetType, Class editorClass) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPropertiesAccess(); } - registry.put(targetType, editorClass); + PropertyEditorFinder finder = getFinder(); + synchronized (finder) { + finder.register(targetType, editorClass); + } } /** @@ -89,46 +94,11 @@ public class PropertyEditorManager { * @return An editor object for the given target class. * The result is null if no suitable editor can be found. */ - public static synchronized PropertyEditor findEditor(Class targetType) { - Class editorClass = registry.get(targetType); - if (editorClass != null) { - try { - Object o = editorClass.newInstance(); - return (PropertyEditor)o; - } catch (Exception ex) { - System.err.println("Couldn't instantiate type editor \"" + - editorClass.getName() + "\" : " + ex); - } + public static PropertyEditor findEditor(Class targetType) { + PropertyEditorFinder finder = getFinder(); + synchronized (finder) { + return finder.find(targetType); } - - // Now try adding "Editor" to the class name. - - String editorName = targetType.getName() + "Editor"; - try { - return (PropertyEditor) Introspector.instantiate(targetType, editorName); - } catch (Exception ex) { - // Silently ignore any errors. - } - - // Now try looking for .fooEditor - int index = editorName.lastIndexOf('.') + 1; - if (index > 0) { - editorName = editorName.substring(index); - } - for (String path : searchPath) { - String name = path + '.' + editorName; - try { - return (PropertyEditor) Introspector.instantiate(targetType, name); - } catch (Exception ex) { - // Silently ignore any errors. - } - } - - if (null != targetType.getEnumConstants()) { - return new EnumEditor(targetType); - } - // We couldn't find a suitable Editor. - return null; } /** @@ -139,8 +109,11 @@ public class PropertyEditorManager { *

The default value for this array is implementation-dependent, * e.g. Sun implementation initially sets to {"sun.beans.editors"}. */ - public static synchronized String[] getEditorSearchPath() { - return searchPath.clone(); + public static String[] getEditorSearchPath() { + PropertyEditorFinder finder = getFinder(); + synchronized (finder) { + return finder.getPackages(); + } } /** @@ -156,28 +129,25 @@ public class PropertyEditorManager { * of system properties. * @see SecurityManager#checkPropertiesAccess */ - public static synchronized void setEditorSearchPath(String[] path) { + public static void setEditorSearchPath(String[] path) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPropertiesAccess(); } - searchPath = (path != null) - ? path.clone() - : EMPTY; + PropertyEditorFinder finder = getFinder(); + synchronized (finder) { + finder.setPackages(path); + } } - private static String[] searchPath = { "sun.beans.editors" }; - private static final String[] EMPTY = {}; - private static final WeakCache, Class> registry; - - static { - registry = new WeakCache, Class>(); - registry.put(Byte.TYPE, ByteEditor.class); - registry.put(Short.TYPE, ShortEditor.class); - registry.put(Integer.TYPE, IntegerEditor.class); - registry.put(Long.TYPE, LongEditor.class); - registry.put(Boolean.TYPE, BooleanEditor.class); - registry.put(Float.TYPE, FloatEditor.class); - registry.put(Double.TYPE, DoubleEditor.class); + private static PropertyEditorFinder getFinder() { + AppContext context = AppContext.getAppContext(); + Object object = context.get(FINDER_KEY); + if (object instanceof PropertyEditorFinder) { + return (PropertyEditorFinder) object; + } + PropertyEditorFinder finder = new PropertyEditorFinder(); + context.put(FINDER_KEY, finder); + return finder; } } diff --git a/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java new file mode 100644 index 00000000000..b149bffb820 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java @@ -0,0 +1,102 @@ +/** + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6380849 + * @summary Tests BeanInfo finder + * @author Sergey Malenkov + */ + +import beans.FirstBean; +import beans.FirstBeanBeanInfo; +import beans.SecondBean; +import beans.ThirdBean; + +import infos.SecondBeanBeanInfo; +import infos.ThirdBeanBeanInfo; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.lang.reflect.Field; + +import sun.awt.SunToolkit; + +public class TestBeanInfo implements Runnable { + + private static final String[] SEARCH_PATH = { "infos" }; // NON-NLS: package name + + public static void main(String[] args) throws InterruptedException { + TestBeanInfo test = new TestBeanInfo(); + test.run(); + // the following tests fails on previous build + ThreadGroup group = new ThreadGroup("$$$"); // NON-NLS: unique thread name + Thread thread = new Thread(group, test); + thread.start(); + thread.join(); + } + + private static void test(Class type, Class expected) { + BeanInfo actual; + try { + actual = Introspector.getBeanInfo(type); + type = actual.getClass(); + Field field = type.getDeclaredField("targetBeanInfo"); // NON-NLS: field name + field.setAccessible(true); + actual = (BeanInfo) field.get(actual); + } + catch (Exception exception) { + throw new Error("unexpected error", exception); + } + if ((actual == null) && (expected != null)) { + throw new Error("expected info is not found"); + } + if ((actual != null) && !actual.getClass().equals(expected)) { + throw new Error("found unexpected info"); + } + } + + private boolean passed; + + public void run() { + if (this.passed) { + SunToolkit.createNewAppContext(); + } + Introspector.flushCaches(); + + test(FirstBean.class, FirstBeanBeanInfo.class); + test(SecondBean.class, null); + test(ThirdBean.class, null); + test(ThirdBeanBeanInfo.class, ThirdBeanBeanInfo.class); + + Introspector.setBeanInfoSearchPath(SEARCH_PATH); + Introspector.flushCaches(); + + test(FirstBean.class, FirstBeanBeanInfo.class); + test(SecondBean.class, SecondBeanBeanInfo.class); + test(ThirdBean.class, null); + test(ThirdBeanBeanInfo.class, ThirdBeanBeanInfo.class); + + this.passed = true; + } +} diff --git a/jdk/test/java/beans/Introspector/6380849/beans/FirstBean.java b/jdk/test/java/beans/Introspector/6380849/beans/FirstBean.java new file mode 100644 index 00000000000..cafb44e0bab --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/beans/FirstBean.java @@ -0,0 +1,4 @@ +package beans; + +public class FirstBean { +} diff --git a/jdk/test/java/beans/Introspector/6380849/beans/FirstBeanBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/beans/FirstBeanBeanInfo.java new file mode 100644 index 00000000000..f4d1355703e --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/beans/FirstBeanBeanInfo.java @@ -0,0 +1,11 @@ +package beans; + +import java.beans.BeanDescriptor; +import java.beans.SimpleBeanInfo; + +public class FirstBeanBeanInfo extends SimpleBeanInfo { + @Override + public BeanDescriptor getBeanDescriptor() { + return new BeanDescriptor(FirstBean.class); + } +} diff --git a/jdk/test/java/beans/Introspector/6380849/beans/SecondBean.java b/jdk/test/java/beans/Introspector/6380849/beans/SecondBean.java new file mode 100644 index 00000000000..fbde3902724 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/beans/SecondBean.java @@ -0,0 +1,4 @@ +package beans; + +public class SecondBean { +} diff --git a/jdk/test/java/beans/Introspector/6380849/beans/ThirdBean.java b/jdk/test/java/beans/Introspector/6380849/beans/ThirdBean.java new file mode 100644 index 00000000000..8fb8b9a92b8 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/beans/ThirdBean.java @@ -0,0 +1,4 @@ +package beans; + +public class ThirdBean { +} diff --git a/jdk/test/java/beans/Introspector/6380849/infos/SecondBeanBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/infos/SecondBeanBeanInfo.java new file mode 100644 index 00000000000..999a6df9040 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/infos/SecondBeanBeanInfo.java @@ -0,0 +1,13 @@ +package infos; + +import beans.SecondBean; + +import java.beans.BeanDescriptor; +import java.beans.SimpleBeanInfo; + +public class SecondBeanBeanInfo extends SimpleBeanInfo { + @Override + public BeanDescriptor getBeanDescriptor() { + return new BeanDescriptor(SecondBean.class); + } +} diff --git a/jdk/test/java/beans/Introspector/6380849/infos/ThirdBeanBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/infos/ThirdBeanBeanInfo.java new file mode 100644 index 00000000000..7d295bd07b3 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6380849/infos/ThirdBeanBeanInfo.java @@ -0,0 +1,11 @@ +package infos; + +import java.beans.BeanDescriptor; +import java.beans.SimpleBeanInfo; + +public class ThirdBeanBeanInfo extends SimpleBeanInfo { + @Override + public BeanDescriptor getBeanDescriptor() { + return new BeanDescriptor(ThirdBeanBeanInfo.class); + } +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/FirstBean.java b/jdk/test/java/beans/PropertyEditor/6380849/FirstBean.java new file mode 100644 index 00000000000..e112dbfaa7e --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/FirstBean.java @@ -0,0 +1,2 @@ +public class FirstBean { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/FirstBeanEditor.java b/jdk/test/java/beans/PropertyEditor/6380849/FirstBeanEditor.java new file mode 100644 index 00000000000..8a227be21fe --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/FirstBeanEditor.java @@ -0,0 +1,4 @@ +import java.beans.PropertyEditorSupport; + +public class FirstBeanEditor extends PropertyEditorSupport { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/SecondBean.java b/jdk/test/java/beans/PropertyEditor/6380849/SecondBean.java new file mode 100644 index 00000000000..51eea295806 --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/SecondBean.java @@ -0,0 +1,2 @@ +public class SecondBean { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/TestPropertyEditor.java b/jdk/test/java/beans/PropertyEditor/6380849/TestPropertyEditor.java new file mode 100644 index 00000000000..f7f4d1b1ad1 --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/TestPropertyEditor.java @@ -0,0 +1,141 @@ +/** + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6380849 + * @summary Tests PropertyEditor finder + * @author Sergey Malenkov + */ + +import editors.SecondBeanEditor; +import editors.ThirdBeanEditor; + +import java.awt.Color; +import java.awt.Font; +import java.beans.PropertyEditor; +import java.beans.PropertyEditorManager; + +import sun.awt.SunToolkit; +import sun.beans.editors.BooleanEditor; +import sun.beans.editors.ByteEditor; +import sun.beans.editors.ColorEditor; +import sun.beans.editors.DoubleEditor; +import sun.beans.editors.EnumEditor; +import sun.beans.editors.FloatEditor; +import sun.beans.editors.FontEditor; +import sun.beans.editors.IntegerEditor; +import sun.beans.editors.LongEditor; +import sun.beans.editors.ShortEditor; +import sun.beans.editors.StringEditor; + +public class TestPropertyEditor implements Runnable { + + private enum Enumeration { + FIRST, SECOND, THIRD + } + + private static final String[] SEARCH_PATH = { "editors" }; // NON-NLS: package name + + public static void main(String[] args) throws InterruptedException { + TestPropertyEditor test = new TestPropertyEditor(); + test.run(); + // the following tests fails on previous build + ThreadGroup group = new ThreadGroup("$$$"); // NON-NLS: unique thread name + Thread thread = new Thread(group, test); + thread.start(); + thread.join(); + } + + private static void test(Class type, Class expected) { + PropertyEditor actual = PropertyEditorManager.findEditor(type); + if ((actual == null) && (expected != null)) { + throw new Error("expected editor is not found"); + } + if ((actual != null) && !actual.getClass().equals(expected)) { + throw new Error("found unexpected editor"); + } + } + + private boolean passed; + + public void run() { + if (this.passed) { + SunToolkit.createNewAppContext(); + } + PropertyEditorManager.registerEditor(ThirdBean.class, ThirdBeanEditor.class); + + test(FirstBean.class, FirstBeanEditor.class); + test(SecondBean.class, null); + test(ThirdBean.class, ThirdBeanEditor.class); + // test editors for default primitive types + test(Byte.TYPE, ByteEditor.class); + test(Short.TYPE, ShortEditor.class); + test(Integer.TYPE, IntegerEditor.class); + test(Long.TYPE, LongEditor.class); + test(Boolean.TYPE, BooleanEditor.class); + test(Float.TYPE, FloatEditor.class); + test(Double.TYPE, DoubleEditor.class); + // test editors for default object types + test(Byte.class, ByteEditor.class); + test(Short.class, ShortEditor.class); + test(Integer.class, IntegerEditor.class); + test(Long.class, LongEditor.class); + test(Boolean.class, BooleanEditor.class); + test(Float.class, FloatEditor.class); + test(Double.class, DoubleEditor.class); + test(String.class, StringEditor.class); + test(Color.class, ColorEditor.class); + test(Font.class, FontEditor.class); + test(Enumeration.class, EnumEditor.class); + + PropertyEditorManager.registerEditor(ThirdBean.class, null); + PropertyEditorManager.setEditorSearchPath(SEARCH_PATH); + + test(FirstBean.class, FirstBeanEditor.class); + test(SecondBean.class, SecondBeanEditor.class); + test(ThirdBean.class, ThirdBeanEditor.class); + // test editors for default primitive types + test(Byte.TYPE, ByteEditor.class); + test(Short.TYPE, ShortEditor.class); + test(Integer.TYPE, IntegerEditor.class); + test(Long.TYPE, LongEditor.class); + test(Boolean.TYPE, BooleanEditor.class); + test(Float.TYPE, FloatEditor.class); + test(Double.TYPE, DoubleEditor.class); + // test editors for default object types + test(Byte.class, null); + test(Short.class, null); + test(Integer.class, null); + test(Long.class, null); + test(Boolean.class, null); + test(Float.class, null); + test(Double.class, null); + test(String.class, null); + test(Color.class, null); + test(Font.class, null); + test(Enumeration.class, EnumEditor.class); + + this.passed = true; + } +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/ThirdBean.java b/jdk/test/java/beans/PropertyEditor/6380849/ThirdBean.java new file mode 100644 index 00000000000..094ab830efb --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/ThirdBean.java @@ -0,0 +1,2 @@ +public class ThirdBean { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/editors/SecondBeanEditor.java b/jdk/test/java/beans/PropertyEditor/6380849/editors/SecondBeanEditor.java new file mode 100644 index 00000000000..e8b48e0f2ea --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/editors/SecondBeanEditor.java @@ -0,0 +1,6 @@ +package editors; + +import java.beans.PropertyEditorSupport; + +public class SecondBeanEditor extends PropertyEditorSupport { +} diff --git a/jdk/test/java/beans/PropertyEditor/6380849/editors/ThirdBeanEditor.java b/jdk/test/java/beans/PropertyEditor/6380849/editors/ThirdBeanEditor.java new file mode 100644 index 00000000000..14bf7b8d168 --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/6380849/editors/ThirdBeanEditor.java @@ -0,0 +1,6 @@ +package editors; + +import java.beans.PropertyEditorSupport; + +public class ThirdBeanEditor extends PropertyEditorSupport { +} diff --git a/jdk/test/java/beans/XMLEncoder/6380849/Bean.java b/jdk/test/java/beans/XMLEncoder/6380849/Bean.java new file mode 100644 index 00000000000..54145979197 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6380849/Bean.java @@ -0,0 +1,2 @@ +public class Bean { +} diff --git a/jdk/test/java/beans/XMLEncoder/6380849/BeanPersistenceDelegate.java b/jdk/test/java/beans/XMLEncoder/6380849/BeanPersistenceDelegate.java new file mode 100644 index 00000000000..34278b419e6 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6380849/BeanPersistenceDelegate.java @@ -0,0 +1,5 @@ +import java.beans.DefaultPersistenceDelegate; + +public class BeanPersistenceDelegate + extends DefaultPersistenceDelegate { +} diff --git a/jdk/test/java/beans/XMLEncoder/6380849/TestPersistenceDelegate.java b/jdk/test/java/beans/XMLEncoder/6380849/TestPersistenceDelegate.java new file mode 100644 index 00000000000..35dde1ab794 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6380849/TestPersistenceDelegate.java @@ -0,0 +1,60 @@ +/** + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6380849 + * @summary Tests PersistenceDelegate finder + * @author Sergey Malenkov + */ + +import java.beans.PersistenceDelegate; +import java.beans.XMLEncoder; +import java.beans.DefaultPersistenceDelegate; + +public class TestPersistenceDelegate { + + private static final XMLEncoder ENCODER = new XMLEncoder(System.out); + + public static void main(String[] args) throws InterruptedException { + Class type = TestPersistenceDelegate.class; + test(type, DefaultPersistenceDelegate.class); + ENCODER.setPersistenceDelegate(type, new BeanPersistenceDelegate()); + test(type, BeanPersistenceDelegate.class); + ENCODER.setPersistenceDelegate(type, null); + test(type, DefaultPersistenceDelegate.class); + // the following tests fails on previous build + test(Bean.class, BeanPersistenceDelegate.class); + test(BeanPersistenceDelegate.class, BeanPersistenceDelegate.class); + } + + private static void test(Class type, Class expected) { + PersistenceDelegate actual = ENCODER.getPersistenceDelegate(type); + if ((actual == null) && (expected != null)) { + throw new Error("expected delegate is not found"); + } + if ((actual != null) && !actual.getClass().equals(expected)) { + throw new Error("found unexpected delegate"); + } + } +} From 7a36ade1ec931b061b19646b55185d14cf832ade Mon Sep 17 00:00:00 2001 From: Changpeng Fang Date: Thu, 2 Jul 2009 16:18:19 -0700 Subject: [PATCH 17/61] 6855164: SIGSEGV during compilation of method involving loop over CharSequence Don not split a block if it contains a FastLockNode with a PhiNode input. Reviewed-by: kvn, never --- hotspot/src/share/vm/opto/loopopts.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp index 454c207fd81..5084e3d8234 100644 --- a/hotspot/src/share/vm/opto/loopopts.cpp +++ b/hotspot/src/share/vm/opto/loopopts.cpp @@ -667,7 +667,6 @@ static bool merge_point_too_heavy(Compile* C, Node* region) { } } -#ifdef _LP64 static bool merge_point_safe(Node* region) { // 4799512: Stop split_if_with_blocks from splitting a block with a ConvI2LNode // having a PhiNode input. This sidesteps the dangerous case where the split @@ -676,20 +675,25 @@ static bool merge_point_safe(Node* region) { // uses. // A better fix for this problem can be found in the BugTraq entry, but // expediency for Mantis demands this hack. + // 6855164: If the merge point has a FastLockNode with a PhiNode input, we stop + // split_if_with_blocks from splitting a block because we could not move around + // the FastLockNode. for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { Node* n = region->fast_out(i); if (n->is_Phi()) { for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { Node* m = n->fast_out(j); - if (m->Opcode() == Op_ConvI2L) { + if (m->is_FastLock()) return false; - } +#ifdef _LP64 + if (m->Opcode() == Op_ConvI2L) + return false; +#endif } } } return true; } -#endif //------------------------------place_near_use--------------------------------- @@ -771,12 +775,10 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) { if( get_loop(n_ctrl->in(j)) != n_loop ) return; -#ifdef _LP64 // Check for safety of the merge point. if( !merge_point_safe(n_ctrl) ) { return; } -#endif // Split compare 'n' through the merge point if it is profitable Node *phi = split_thru_phi( n, n_ctrl, policy ); From 5363b41a3e61cd88a565c1568508c9598b239131 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Fri, 3 Jul 2009 11:13:42 +0800 Subject: [PATCH 18/61] 6853793: OutOfMemoryError in sun.security.provider.certpath.OCSPChecker.check Allocate memory dynamically, keep reading until EOF. Reviewed-by: weijun --- .../provider/certpath/OCSPChecker.java | 23 ++++++++---- .../security/timestamp/HttpTimestamper.java | 35 ++++++++++++------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java b/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java index 35ed85def19..04e0649d8ff 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -351,18 +351,27 @@ class OCSPChecker extends PKIXCertPathChecker { } in = con.getInputStream(); + byte[] response = null; + int total = 0; int contentLength = con.getContentLength(); - if (contentLength == -1) { + if (contentLength != -1) { + response = new byte[contentLength]; + } else { + response = new byte[2048]; contentLength = Integer.MAX_VALUE; } - byte[] response = new byte[contentLength]; - int total = 0; - int count = 0; - while (count != -1 && total < contentLength) { - count = in.read(response, total, response.length - total); + while (total < contentLength) { + int count = in.read(response, total, response.length - total); + if (count < 0) + break; + total += count; + if (total >= response.length && total < contentLength) { + response = Arrays.copyOf(response, total * 2); + } } + response = Arrays.copyOf(response, total); OCSPResponse ocspResponse = new OCSPResponse(response, pkixParams, responderCert); diff --git a/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java b/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java index 690f13a2a0f..bb735141159 100644 --- a/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java +++ b/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import java.net.URL; import java.net.HttpURLConnection; import java.util.Iterator; import java.util.Set; +import java.util.Arrays; import sun.security.pkcs.*; @@ -137,23 +138,33 @@ public class HttpTimestamper implements Timestamper { } System.out.println(); } - int contentLength = connection.getContentLength(); - if (contentLength == -1) { - contentLength = Integer.MAX_VALUE; - } verifyMimeType(connection.getContentType()); - replyBuffer = new byte[contentLength]; int total = 0; - int count = 0; - while (count != -1 && total < contentLength) { - count = input.read(replyBuffer, total, - replyBuffer.length - total); - total += count; + int contentLength = connection.getContentLength(); + if (contentLength != -1) { + replyBuffer = new byte[contentLength]; + } else { + replyBuffer = new byte[2048]; + contentLength = Integer.MAX_VALUE; } + + while (total < contentLength) { + int count = input.read(replyBuffer, total, + replyBuffer.length - total); + if (count < 0) + break; + + total += count; + if (total >= replyBuffer.length && total < contentLength) { + replyBuffer = Arrays.copyOf(replyBuffer, total * 2); + } + } + replyBuffer = Arrays.copyOf(replyBuffer, total); + if (DEBUG) { System.out.println("received timestamp response (length=" + - replyBuffer.length + ")"); + total + ")"); } } finally { if (input != null) { From 64bc185e5502ed93d84f3106038b55cb5b7e6dd9 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 3 Jul 2009 16:56:29 +0400 Subject: [PATCH 19/61] 6329581: RFE: LTP: java.beans.XMLEncoder does not manage ClassLoader Reviewed-by: rupashka, alexp --- jdk/src/share/classes/java/beans/Encoder.java | 11 ++- .../share/classes/java/beans/MetaData.java | 6 +- .../share/classes/java/beans/Statement.java | 3 +- .../beans/XMLEncoder/6329581/Test6329581.java | 75 +++++++++++++++++++ 4 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 jdk/test/java/beans/XMLEncoder/6329581/Test6329581.java diff --git a/jdk/src/share/classes/java/beans/Encoder.java b/jdk/src/share/classes/java/beans/Encoder.java index 92e3d695bcb..e7f63397340 100644 --- a/jdk/src/share/classes/java/beans/Encoder.java +++ b/jdk/src/share/classes/java/beans/Encoder.java @@ -246,12 +246,11 @@ public class Encoder { for (int i = 0; i < oldArgs.length; i++) { newArgs[i] = writeObject1(oldArgs[i]); } - if (oldExp.getClass() == Statement.class) { - return new Statement(newTarget, oldExp.getMethodName(), newArgs); - } - else { - return new Expression(newTarget, oldExp.getMethodName(), newArgs); - } + Statement newExp = Statement.class.equals(oldExp.getClass()) + ? new Statement(newTarget, oldExp.getMethodName(), newArgs) + : new Expression(newTarget, oldExp.getMethodName(), newArgs); + newExp.loader = oldExp.loader; + return newExp; } /** diff --git a/jdk/src/share/classes/java/beans/MetaData.java b/jdk/src/share/classes/java/beans/MetaData.java index f4d307090a5..96607db806f 100644 --- a/jdk/src/share/classes/java/beans/MetaData.java +++ b/jdk/src/share/classes/java/beans/MetaData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -219,7 +219,9 @@ class java_lang_Class_PersistenceDelegate extends PersistenceDelegate { return new Expression(oldInstance, String.class, "getClass", new Object[]{}); } else { - return new Expression(oldInstance, Class.class, "forName", new Object[]{c.getName()}); + Expression newInstance = new Expression(oldInstance, Class.class, "forName", new Object[] { c.getName() }); + newInstance.loader = c.getClassLoader(); + return newInstance; } } } diff --git a/jdk/src/share/classes/java/beans/Statement.java b/jdk/src/share/classes/java/beans/Statement.java index 7bf2fccda56..6169f92742f 100644 --- a/jdk/src/share/classes/java/beans/Statement.java +++ b/jdk/src/share/classes/java/beans/Statement.java @@ -66,6 +66,7 @@ public class Statement { Object target; String methodName; Object[] arguments; + ClassLoader loader; /** * Creates a new Statement object with a target, @@ -157,7 +158,7 @@ public class Statement { // of core from a class inside core. Special // case this method. if (target == Class.class && methodName.equals("forName")) { - return ClassFinder.resolveClass((String)arguments[0]); + return ClassFinder.resolveClass((String)arguments[0], this.loader); } Class[] argClasses = new Class[arguments.length]; for(int i = 0; i < arguments.length; i++) { diff --git a/jdk/test/java/beans/XMLEncoder/6329581/Test6329581.java b/jdk/test/java/beans/XMLEncoder/6329581/Test6329581.java new file mode 100644 index 00000000000..c307dab1267 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6329581/Test6329581.java @@ -0,0 +1,75 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6329581 + * @summary Tests encoding of a class with custom ClassLoader + * @author Sergey Malenkov + */ + +import java.beans.ExceptionListener; +import java.beans.XMLDecoder; +import java.beans.XMLEncoder; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +public class Test6329581 implements ExceptionListener { + + public static void main(String[] args) throws Exception { + ExceptionListener listener = new Test6329581(); + // write bean to byte array + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XMLEncoder encoder = new XMLEncoder(out); + encoder.setExceptionListener(listener); + encoder.writeObject(getClassLoader("beans.jar").loadClass("test.Bean").newInstance()); + encoder.close(); + // read bean from byte array + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + XMLDecoder decoder = new XMLDecoder(in, null, listener, getClassLoader("beans.jar")); + Object object = decoder.readObject(); + decoder.close(); + + if (!object.getClass().getClassLoader().getClass().equals(URLClassLoader.class)) { + throw new Error("bean is loaded with unexpected class loader"); + } + } + + private static ClassLoader getClassLoader(String name) throws Exception { + StringBuilder sb = new StringBuilder(256); + sb.append("file:"); + sb.append(System.getProperty("test.src", ".")); + sb.append(File.separatorChar); + sb.append(name); + + URL[] url = { new URL(sb.toString()) }; + return new URLClassLoader(url); + } + + public void exceptionThrown(Exception exception) { + throw new Error("unexpected exception", exception); + } +} From 839196d14e119c182b745f417b48d4816d3d4d48 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Fri, 3 Jul 2009 07:24:43 -0700 Subject: [PATCH 20/61] 6857287: (file) Clarifications for symbolic link related javadoc Fix up jsr203 file javadoc related to symbolic links Reviewed-by: alanb --- .../classes/java/nio/file/LinkPermission.java | 2 +- .../java/nio/file/NotLinkException.java | 2 +- jdk/src/share/classes/java/nio/file/Path.java | 79 ++++++++++--------- .../java/nio/file/SecureDirectoryStream.java | 11 +-- .../java/nio/file/attribute/Attributes.java | 10 +-- .../file/attribute/BasicFileAttributes.java | 4 +- 6 files changed, 55 insertions(+), 53 deletions(-) diff --git a/jdk/src/share/classes/java/nio/file/LinkPermission.java b/jdk/src/share/classes/java/nio/file/LinkPermission.java index 01949114761..a318903365a 100644 --- a/jdk/src/share/classes/java/nio/file/LinkPermission.java +++ b/jdk/src/share/classes/java/nio/file/LinkPermission.java @@ -46,7 +46,7 @@ import java.security.BasicPermission; * known as creating a link, or hard link. * Extreme care should be taken when granting this permission. It allows * linking to any file or directory in the file system thus allowing the - * attacker to access to all files. + * attacker access to all files. * * * symbolic diff --git a/jdk/src/share/classes/java/nio/file/NotLinkException.java b/jdk/src/share/classes/java/nio/file/NotLinkException.java index bdc1fc354ad..fafdeee6cc6 100644 --- a/jdk/src/share/classes/java/nio/file/NotLinkException.java +++ b/jdk/src/share/classes/java/nio/file/NotLinkException.java @@ -27,7 +27,7 @@ package java.nio.file; /** * Checked exception thrown when a file system operation fails because a file - * is not a link. + * is not a symbolic link. * * @since 1.7 */ diff --git a/jdk/src/share/classes/java/nio/file/Path.java b/jdk/src/share/classes/java/nio/file/Path.java index e00c96144d9..113a7c58067 100644 --- a/jdk/src/share/classes/java/nio/file/Path.java +++ b/jdk/src/share/classes/java/nio/file/Path.java @@ -91,8 +91,8 @@ import java.util.Set; * iterate over the entries in the directory.

*
  • Files can be {@link #copyTo(Path,CopyOption[]) copied} or * {@link #moveTo(Path,CopyOption[]) moved}.

  • - *
  • Symbolic-links may be {@link #createSymbolicLink created}, or the - * target of a link may be {@link #readSymbolicLink read}.

  • + *
  • Symbolic links may be {@link #createSymbolicLink created}, or the + * target of a symbolic link may be {@link #readSymbolicLink read}.

  • *
  • The {@link #toRealPath real} path of an existing file may be * obtained.

  • * @@ -403,12 +403,12 @@ public abstract class Path * p.relativize(p.resolve(q)).equals(q) * * - *

    When symbolic-links are supported, then whether the resulting path, + *

    When symbolic links are supported, then whether the resulting path, * when resolved against this path, yields a path that can be used to locate * the {@link #isSameFile same} file as {@code other} is implementation * dependent. For example, if this path is {@code "/a/b"} and the given * path is {@code "/a/x"} then the resulting relative path may be {@code - * "../x"}. If {@code "b"} is a symbolic-link then is implementation + * "../x"}. If {@code "b"} is a symbolic link then is implementation * dependent if {@code "a/b/../x"} would locate the same file as {@code "/a/x"}. * * @param other @@ -430,8 +430,8 @@ public abstract class Path * *

    An implementation may require to examine the file to determine if the * file is a directory. Consequently this method may not be atomic with respect - * to other file system operations. If the file is a symbolic-link then the - * link is deleted and not the final target of the link. + * to other file system operations. If the file is a symbolic link then the + * symbolic link itself, not the final target of the link, is deleted. * *

    If the file is a directory then the directory must be empty. In some * implementations a directory has entries for special files or links that @@ -459,11 +459,11 @@ public abstract class Path /** * Deletes the file located by this path, if it exists. * - *

    As with the {@link #delete delete()} method, an implementation - * may require to examine the file to determine if the file is a directory. + *

    As with the {@link #delete delete()} method, an implementation may + * need to examine the file to determine if the file is a directory. * Consequently this method may not be atomic with respect to other file - * system operations. If the file is a symbolic-link then the link is - * deleted and not the final target of the link. + * system operations. If the file is a symbolic link, then the symbolic + * link itself, not the final target of the link, is deleted. * *

    If the file is a directory then the directory must be empty. In some * implementations a directory has entries for special files or links that @@ -507,7 +507,7 @@ public abstract class Path * create symbolic links, in which case this method may throw {@code IOException}. * * @param target - * the target of the link + * the target of the symbolic link * @param attrs * the array of attributes to set atomically when creating the * symbolic link @@ -573,9 +573,9 @@ public abstract class Path * Reads the target of a symbolic link (optional operation). * *

    If the file system supports symbolic - * links then this method is used read the target of the link, failing - * if the file is not a link. The target of the link need not exist. The - * returned {@code Path} object will be associated with the same file + * links then this method is used to read the target of the link, failing + * if the file is not a symbolic link. The target of the link need not exist. + * The returned {@code Path} object will be associated with the same file * system as this {@code Path}. * * @return a {@code Path} object representing the target of the link @@ -584,7 +584,7 @@ public abstract class Path * if the implementation does not support symbolic links * @throws NotLinkException * if the target could otherwise not be read because the file - * is not a link (optional specific exception) + * is not a symbolic link (optional specific exception) * @throws IOException * if an I/O error occurs * @throws SecurityException @@ -724,8 +724,8 @@ public abstract class Path * exists, except if the source and target are the {@link #isSameFile same} * file, in which case this method has no effect. File attributes are not * required to be copied to the target file. If symbolic links are supported, - * and the file is a link, then the final target of the link is copied. If - * the file is a directory then it creates an empty directory in the target + * and the file is a symbolic link, then the final target of the link is copied. + * If the file is a directory then it creates an empty directory in the target * location (entries in the directory are not copied). This method can be * used with the {@link Files#walkFileTree Files.walkFileTree} utility * method to copy a directory and all entries in the directory, or an entire @@ -740,8 +740,8 @@ public abstract class Path * {@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} * If the target file exists, then the target file is replaced if it * is not a non-empty directory. If the target file exists and is a - * symbolic-link then the symbolic-link is replaced (not the target of - * the link. + * symbolic link, then the symbolic link itself, not the target of + * the link, is replaced. * * * {@link StandardCopyOption#COPY_ATTRIBUTES COPY_ATTRIBUTES} @@ -755,11 +755,11 @@ public abstract class Path * * * {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} - * Symbolic-links are not followed. If the file, located by this path, - * is a symbolic-link then the link is copied rather than the target of - * the link. It is implementation specific if file attributes can be - * copied to the new link. In other words, the {@code COPY_ATTRIBUTES} - * option may be ignored when copying a link. + * Symbolic links are not followed. If the file, located by this path, + * is a symbolic link, then the symbolic link itself, not the target of + * the link, is copied. It is implementation specific if file attributes + * can be copied to the new link. In other words, the {@code + * COPY_ATTRIBUTES} option may be ignored when copying a symbolic link. * * * @@ -807,18 +807,19 @@ public abstract class Path *

    By default, this method attempts to move the file to the target * location, failing if the target file exists except if the source and * target are the {@link #isSameFile same} file, in which case this method - * has no effect. If the file is a symbolic link then the link is moved and - * not the target of the link. This method may be invoked to move an empty - * directory. In some implementations a directory has entries for special - * files or links that are created when the directory is created. In such - * implementations a directory is considered empty when only the special - * entries exist. When invoked to move a directory that is not empty then the - * directory is moved if it does not require moving the entries in the directory. - * For example, renaming a directory on the same {@link FileStore} will usually - * not require moving the entries in the directory. When moving a directory - * requires that its entries be moved then this method fails (by throwing - * an {@code IOException}). To move a file tree may involve copying - * rather than moving directories and this can be done using the {@link + * has no effect. If the file is a symbolic link then the symbolic link + * itself, not the target of the link, is moved. This method may be + * invoked to move an empty directory. In some implementations a directory + * has entries for special files or links that are created when the + * directory is created. In such implementations a directory is considered + * empty when only the special entries exist. When invoked to move a + * directory that is not empty then the directory is moved if it does not + * require moving the entries in the directory. For example, renaming a + * directory on the same {@link FileStore} will usually not require moving + * the entries in the directory. When moving a directory requires that its + * entries be moved then this method fails (by throwing an {@code + * IOException}). To move a file tree may involve copying rather + * than moving directories and this can be done using the {@link * #copyTo copyTo} method in conjunction with the {@link * Files#walkFileTree Files.walkFileTree} utility method. * @@ -831,8 +832,8 @@ public abstract class Path * {@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} * If the target file exists, then the target file is replaced if it * is not a non-empty directory. If the target file exists and is a - * symbolic-link then the symbolic-link is replaced and not the target of - * the link. + * symbolic link, then the symbolic link itself, not the target of + * the link, is replaced. * * * {@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} @@ -1495,7 +1496,7 @@ public abstract class Path * *

    Where a file is registered with a watch service by means of a symbolic * link then it is implementation specific if the watch continues to depend - * on the existence of the link after it is registered. + * on the existence of the symbolic link after it is registered. * * @param watcher * the watch service to which this object is to be registered diff --git a/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java b/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java index 9655695d301..9667a3cf5ce 100644 --- a/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java +++ b/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java @@ -166,12 +166,13 @@ public abstract class SecureDirectoryStream /** * Deletes a file. * - *

    Unlike the {@link Path#delete delete()} method, this method - * does not first examine the file to determine if the file is a directory. + *

    Unlike the {@link Path#delete delete()} method, this method does + * not first examine the file to determine if the file is a directory. * Whether a directory is deleted by this method is system dependent and - * therefore not specified. If the file is a symbolic-link then the link is - * deleted (not the final target of the link). When the parameter is a - * relative path then the file to delete is relative to this open directory. + * therefore not specified. If the file is a symbolic link, then the link + * itself, not the final target of the link, is deleted. When the + * parameter is a relative path then the file to delete is relative to + * this open directory. * * @param path * the path of the file to delete diff --git a/jdk/src/share/classes/java/nio/file/attribute/Attributes.java b/jdk/src/share/classes/java/nio/file/attribute/Attributes.java index 3ffa6389b43..cfcbf44a708 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/Attributes.java +++ b/jdk/src/share/classes/java/nio/file/attribute/Attributes.java @@ -48,9 +48,9 @@ public final class Attributes { * symbolic links are followed and the file attributes of the final target * of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attributes of the symbolic link. This option - * should be used where there is a need to determine if a file is a - * symbolic link: + * the method returns the file attributes of the symbolic link itself. + * This option should be used where there is a need to determine if a + * file is a symbolic link: *

          *    boolean isSymbolicLink = Attributes.readBasicFileAttributes(file, NOFOLLOW_LINKS).isSymbolicLink();
          * 
    @@ -98,7 +98,7 @@ public final class Attributes { * symbolic links are followed and the file attributes of the final target * of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attributes of the symbolic link. + * the method returns the file attributes of the symbolic link itself. * * @param file * A file reference that locates the file @@ -145,7 +145,7 @@ public final class Attributes { * symbolic links are followed and the file attributes of the final target * of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attributes of the symbolic link. + * the method returns the file attributes of the symbolic link itself. * * @param file * A file reference that locates the file diff --git a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java index 6fb3bbf7ee9..4e45711292a 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java +++ b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java @@ -81,13 +81,13 @@ public interface BasicFileAttributes { boolean isDirectory(); /** - * Tells whether the file is a symbolic-link. + * Tells whether the file is a symbolic link. */ boolean isSymbolicLink(); /** * Tells whether the file is something other than a regular file, directory, - * or link. + * or symbolic link. */ boolean isOther(); From 8a5359c35b6c2af54520afd00bc6b86c3b43eb86 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 6 Jul 2009 14:32:04 +0400 Subject: [PATCH 21/61] 6723447: Introspector doesn't check return type for indexed property setters Reviewed-by: rupashka --- .../java/beans/IndexedPropertyDescriptor.java | 7 +- .../classes/java/beans/Introspector.java | 6 +- .../java/beans/PropertyDescriptor.java | 7 +- .../java/beans/Introspector/Test6723447.java | 88 +++++++++++++++++++ 4 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 jdk/test/java/beans/Introspector/Test6723447.java diff --git a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java index fa5b404c239..e0d2bb4bb4f 100644 --- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -274,6 +274,11 @@ perty. } indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 2, (type == null) ? null : new Class[] { int.class, type }); + if (indexedWriteMethod != null) { + if (!indexedWriteMethod.getReturnType().equals(void.class)) { + indexedWriteMethod = null; + } + } setIndexedWriteMethod0(indexedWriteMethod); } return indexedWriteMethod; diff --git a/jdk/src/share/classes/java/beans/Introspector.java b/jdk/src/share/classes/java/beans/Introspector.java index b43911cf123..1c90f205a88 100644 --- a/jdk/src/share/classes/java/beans/Introspector.java +++ b/jdk/src/share/classes/java/beans/Introspector.java @@ -524,9 +524,9 @@ public class Introspector { pd = new PropertyDescriptor(this.beanClass, name.substring(2), method, null); } } else if (argCount == 1) { - if (argTypes[0] == int.class && name.startsWith(GET_PREFIX)) { + if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) { pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null); - } else if (resultType == void.class && name.startsWith(SET_PREFIX)) { + } else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) { // Simple setter pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method); if (throwsException(method, PropertyVetoException.class)) { @@ -534,7 +534,7 @@ public class Introspector { } } } else if (argCount == 2) { - if (argTypes[0] == int.class && name.startsWith(SET_PREFIX)) { + if (void.class.equals(resultType) && int.class.equals(argTypes[0]) && name.startsWith(SET_PREFIX)) { pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, null, method); if (throwsException(method, PropertyVetoException.class)) { pd.setConstrained(true); diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index 08ae9a45f42..70a539c81fd 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -294,6 +294,11 @@ public class PropertyDescriptor extends FeatureDescriptor { writeMethod = Introspector.findMethod(cls, writeMethodName, 1, (type == null) ? null : new Class[] { type }); + if (writeMethod != null) { + if (!writeMethod.getReturnType().equals(void.class)) { + writeMethod = null; + } + } try { setWriteMethod(writeMethod); } catch (IntrospectionException ex) { diff --git a/jdk/test/java/beans/Introspector/Test6723447.java b/jdk/test/java/beans/Introspector/Test6723447.java new file mode 100644 index 00000000000..04a3ca632d0 --- /dev/null +++ b/jdk/test/java/beans/Introspector/Test6723447.java @@ -0,0 +1,88 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6723447 + * @summary Tests return type for property setters + * @author Sergey Malenkov + */ + +import java.beans.IndexedPropertyDescriptor; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.math.BigDecimal; + +public class Test6723447 { + + public static void main(String[] args) { + test(Test6723447.class); + test(BigDecimal.class); + } + + private static void test(Class type) { + for (PropertyDescriptor pd : getPropertyDescriptors(type)) { + test(pd.getWriteMethod()); + if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; + test(ipd.getIndexedWriteMethod()); + } + } + } + + private static void test(Method method) { + if (method != null) { + Class type = method.getReturnType(); + if (!type.equals(void.class)) { + throw new Error("unexpected return type: " + type); + } + } + } + + private static PropertyDescriptor[] getPropertyDescriptors(Class type) { + try { + return Introspector.getBeanInfo(type).getPropertyDescriptors(); + } + catch (IntrospectionException exception) { + throw new Error("unexpected exception", exception); + } + } + + public Object getValue() { + return null; + } + + public Object setValue(Object value) { + return value; + } + + public Object getValues(int index) { + return null; + } + + public Object setValues(int index, Object value) { + return value; + } +} From d8a3c0970652cd914ae4d1ce945f5ff86f15435a Mon Sep 17 00:00:00 2001 From: Jean-Christophe Collet Date: Mon, 6 Jul 2009 15:13:48 +0200 Subject: [PATCH 22/61] 6856856: NPE in HTTP protocol handler logging Fixed the NPE and Moved the java.util.logging dependency to a single class and used reflection to make it a soft one. Reviewed-by: chegar --- .../classes/sun/net/www/http/HttpCapture.java | 72 +++++++++++++++++++ .../classes/sun/net/www/http/HttpClient.java | 10 +-- .../www/protocol/http/HttpLogFormatter.java | 3 +- .../www/protocol/http/HttpURLConnection.java | 65 ++++++++--------- 4 files changed, 105 insertions(+), 45 deletions(-) diff --git a/jdk/src/share/classes/sun/net/www/http/HttpCapture.java b/jdk/src/share/classes/sun/net/www/http/HttpCapture.java index 873c0dcc398..78debed415f 100644 --- a/jdk/src/share/classes/sun/net/www/http/HttpCapture.java +++ b/jdk/src/share/classes/sun/net/www/http/HttpCapture.java @@ -25,6 +25,8 @@ package sun.net.www.http; import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; @@ -60,6 +62,76 @@ public class HttpCapture { private static boolean initialized = false; private static volatile ArrayList patterns = null; private static volatile ArrayList capFiles = null; + /* Logging is done in an ugly way so that it does not require the presence + * the java.util.logging package. If the Logger class is not available, then + * logging is turned off. This is for helping the modularization effort. + */ + private static Object logger = null; + private static boolean logging = false; + + static { + Class cl; + try { + cl = Class.forName("java.util.logging.Logger"); + } catch (ClassNotFoundException ex) { + cl = null; + } + if (cl != null) { + try { + Method m = cl.getMethod("getLogger", String.class); + logger = m.invoke(null, "sun.net.www.protocol.http.HttpURLConnection"); + logging = true; + } catch (NoSuchMethodException noSuchMethodException) { + } catch (SecurityException securityException) { + } catch (IllegalAccessException illegalAccessException) { + } catch (IllegalArgumentException illegalArgumentException) { + } catch (InvocationTargetException invocationTargetException) { + } + } + } + + public static void fine(String s) { + if (logging) { + ((Logger)logger).fine(s); + } + } + + public static void finer(String s) { + if (logging) { + ((Logger)logger).finer(s); + } + } + + public static void finest(String s) { + if (logging) { + ((Logger)logger).finest(s); + } + } + + public static void severe(String s) { + if (logging) { + ((Logger)logger).finest(s); + } + } + + public static void info(String s) { + if (logging) { + ((Logger)logger).info(s); + } + } + + public static void warning(String s) { + if (logging) { + ((Logger)logger).warning(s); + } + } + + public static boolean isLoggable(String level) { + if (!logging) { + return false; + } + return ((Logger)logger).isLoggable(Level.parse(level)); + } private static synchronized void init() { initialized = true; diff --git a/jdk/src/share/classes/sun/net/www/http/HttpClient.java b/jdk/src/share/classes/sun/net/www/http/HttpClient.java index f170ff1cca0..c4ff7552c18 100644 --- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java +++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java @@ -28,8 +28,6 @@ package sun.net.www.http; import java.io.*; import java.net.*; import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; import sun.net.NetworkClient; import sun.net.ProgressSource; import sun.net.www.MessageHeader; @@ -66,10 +64,6 @@ public class HttpClient extends NetworkClient { /** Default port number for http daemons. REMIND: make these private */ static final int httpPortNumber = 80; - // Use same logger as HttpURLConnection since we want to combine both event - // streams into one single HTTP log - private static Logger logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); - /** return default port number (subclasses may override) */ protected int getDefaultPort () { return httpPortNumber; } @@ -810,8 +804,8 @@ public class HttpClient extends NetworkClient { if (isKeepingAlive()) { // Wrap KeepAliveStream if keep alive is enabled. - if (logger.isLoggable(Level.FINEST)) { - logger.finest("KeepAlive stream used: " + url); + if (HttpCapture.isLoggable("FINEST")) { + HttpCapture.finest("KeepAlive stream used: " + url); } serverInput = new KeepAliveStream(serverInput, pi, cl, this); failedOnce = false; diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java index 0163d42eda0..97b9be64ed1 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java @@ -49,8 +49,7 @@ public class HttpLogFormatter extends java.util.logging.SimpleFormatter { @Override public String format(LogRecord record) { - if (!"sun.net.www.protocol.http.HttpURLConnection".equalsIgnoreCase(record.getSourceClassName()) - && !"sun.net.www.http.HttpClient".equalsIgnoreCase(record.getSourceClassName())) { + if (!"sun.net.www.http.HttpCapture".equalsIgnoreCase(record.getSourceClassName())) { // Don't change format for stuff that doesn't concern us return super.format(record); } diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index afd35f0d72e..accd8295503 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -51,14 +51,13 @@ import java.util.List; import java.util.Locale; import java.util.StringTokenizer; import java.util.Iterator; -import java.util.logging.Level; -import java.util.logging.Logger; import sun.net.*; import sun.net.www.*; import sun.net.www.http.HttpClient; import sun.net.www.http.PosterOutputStream; import sun.net.www.http.ChunkedInputStream; import sun.net.www.http.ChunkedOutputStream; +import sun.net.www.http.HttpCapture; import java.text.SimpleDateFormat; import java.util.TimeZone; import java.net.MalformedURLException; @@ -71,8 +70,6 @@ import java.nio.ByteBuffer; public class HttpURLConnection extends java.net.HttpURLConnection { - private static Logger logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); - static String HTTP_CONNECT = "CONNECT"; static final String version; @@ -304,14 +301,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { return java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public PasswordAuthentication run() { - if (logger.isLoggable(Level.FINEST)) { - logger.finest("Requesting Authentication: host =" + host + " url = " + url); + if (HttpCapture.isLoggable("FINEST")) { + HttpCapture.finest("Requesting Authentication: host =" + host + " url = " + url); } PasswordAuthentication pass = Authenticator.requestPasswordAuthentication( host, addr, port, protocol, prompt, scheme, url, authType); - if (pass != null && logger.isLoggable(Level.FINEST)) { - logger.finest("Authentication returned: " + pass.toString()); + if (HttpCapture.isLoggable("FINEST")) { + HttpCapture.finest("Authentication returned: " + (pass != null ? pass.toString() : "null")); } return pass; } @@ -466,8 +463,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { setRequests=true; } - if (logger.isLoggable(Level.FINE)) { - logger.fine(requests.toString()); + if (HttpCapture.isLoggable("FINE")) { + HttpCapture.fine(requests.toString()); } http.writeRequests(requests, poster); if (ps.checkError()) { @@ -723,11 +720,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { && !(cachedResponse instanceof SecureCacheResponse)) { cachedResponse = null; } - if (logger.isLoggable(Level.FINEST)) { - logger.finest("Cache Request for " + uri + " / " + getRequestMethod()); - if (cachedResponse != null) { - logger.finest("From cache: "+cachedResponse.toString()); - } + if (HttpCapture.isLoggable("FINEST")) { + HttpCapture.finest("Cache Request for " + uri + " / " + getRequestMethod()); + HttpCapture.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null")); } if (cachedResponse != null) { cachedHeaders = mapToMessageHeader(cachedResponse.getHeaders()); @@ -766,8 +761,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { }); if (sel != null) { URI uri = sun.net.www.ParseUtil.toURI(url); - if (logger.isLoggable(Level.FINEST)) { - logger.finest("ProxySelector Request for " + uri); + if (HttpCapture.isLoggable("FINEST")) { + HttpCapture.finest("ProxySelector Request for " + uri); } Iterator it = sel.select(uri).iterator(); Proxy p; @@ -783,9 +778,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { http = getNewHttpClient(url, p, connectTimeout, false); http.setReadTimeout(readTimeout); } - if (logger.isLoggable(Level.FINEST)) { + if (HttpCapture.isLoggable("FINEST")) { if (p != null) { - logger.finest("Proxy used: " + p.toString()); + HttpCapture.finest("Proxy used: " + p.toString()); } } break; @@ -1015,15 +1010,15 @@ public class HttpURLConnection extends java.net.HttpURLConnection { URI uri = ParseUtil.toURI(url); if (uri != null) { - if (logger.isLoggable(Level.FINEST)) { - logger.finest("CookieHandler request for " + uri); + if (HttpCapture.isLoggable("FINEST")) { + HttpCapture.finest("CookieHandler request for " + uri); } Map> cookies = cookieHandler.get( uri, requests.getHeaders(EXCLUDE_HEADERS)); if (!cookies.isEmpty()) { - if (logger.isLoggable(Level.FINEST)) { - logger.finest("Cookies retrieved: " + cookies.toString()); + if (HttpCapture.isLoggable("FINEST")) { + HttpCapture.finest("Cookies retrieved: " + cookies.toString()); } for (Map.Entry> entry : cookies.entrySet()) { @@ -1154,8 +1149,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { writeRequests(); } http.parseHTTP(responses, pi, this); - if (logger.isLoggable(Level.FINE)) { - logger.fine(responses.toString()); + if (HttpCapture.isLoggable("FINE")) { + HttpCapture.fine(responses.toString()); } inputStream = http.getInputStream(); @@ -1599,8 +1594,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { http.parseHTTP(responses, null, this); /* Log the response to the CONNECT */ - if (logger.isLoggable(Level.FINE)) { - logger.fine(responses.toString()); + if (HttpCapture.isLoggable("FINE")) { + HttpCapture.fine(responses.toString()); } statusLine = responses.getValue(0); @@ -1727,8 +1722,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { setPreemptiveProxyAuthentication(requests); /* Log the CONNECT request */ - if (logger.isLoggable(Level.FINE)) { - logger.fine(requests.toString()); + if (HttpCapture.isLoggable("FINE")) { + HttpCapture.fine(requests.toString()); } http.writeRequests(requests, null); @@ -1872,8 +1867,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } } } - if (logger.isLoggable(Level.FINER)) { - logger.finer("Proxy Authentication for " + authhdr.toString() +" returned " + ret.toString()); + if (HttpCapture.isLoggable("FINER")) { + HttpCapture.finer("Proxy Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null")); } return ret; } @@ -2002,8 +1997,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } } } - if (logger.isLoggable(Level.FINER)) { - logger.finer("Server Authentication for " + authhdr.toString() +" returned " + ret.toString()); + if (HttpCapture.isLoggable("FINER")) { + HttpCapture.finer("Server Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null")); } return ret; } @@ -2078,8 +2073,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { if (streaming()) { throw new HttpRetryException (RETRY_MSG3, stat, loc); } - if (logger.isLoggable(Level.FINE)) { - logger.fine("Redirected from " + url + " to " + locUrl); + if (HttpCapture.isLoggable("FINE")) { + HttpCapture.fine("Redirected from " + url + " to " + locUrl); } // clear out old response headers!!!! From cab876d8d1dea4bb41278315342d50db85f65da9 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Mon, 6 Jul 2009 11:30:40 -0700 Subject: [PATCH 23/61] 6854795: Miscellaneous improvements to "jar" Cleanup of jar/Main.java (Initial patch by tobyr@google.com, additional review by jeremymanson@google.com, ulf.zibis@gmx.de) Reviewed-by: sherman, alanb --- jdk/src/share/classes/sun/tools/jar/Main.java | 349 +++++++++++------- jdk/test/tools/jar/index/MetaInf.java | 75 +++- 2 files changed, 263 insertions(+), 161 deletions(-) diff --git a/jdk/src/share/classes/sun/tools/jar/Main.java b/jdk/src/share/classes/sun/tools/jar/Main.java index ecd76d6e800..99f60f94c7a 100644 --- a/jdk/src/share/classes/sun/tools/jar/Main.java +++ b/jdk/src/share/classes/sun/tools/jar/Main.java @@ -26,12 +26,16 @@ package sun.tools.jar; import java.io.*; +import java.nio.file.Path; import java.util.*; import java.util.zip.*; import java.util.jar.*; import java.util.jar.Manifest; import java.text.MessageFormat; import sun.misc.JarIndex; +import static sun.misc.JarIndex.INDEX_NAME; +import static java.util.jar.JarFile.MANIFEST_NAME; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; /** * This class implements a simple utility for creating files in the JAR @@ -58,7 +62,6 @@ class Main { // Directories specified by "-C" operation. Set paths = new HashSet(); - CRC32 crc32 = new CRC32(); /* * cflag: create * uflag: update @@ -71,10 +74,8 @@ class Main { */ boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag; - static final String MANIFEST = JarFile.MANIFEST_NAME; static final String MANIFEST_DIR = "META-INF/"; static final String VERSION = "1.0"; - static final String INDEX = JarIndex.INDEX_NAME; private static ResourceBundle rsrc; @@ -126,9 +127,21 @@ class Main { this.program = program; } + /** + * Creates a new empty temporary file in the same directory as the + * specified file. A variant of File.createTempFile. + */ + private static File createTempFileInSameDirectoryAs(File file) + throws IOException { + File dir = file.getParentFile(); + if (dir == null) + dir = new File("."); + return File.createTempFile("jartmp", null, dir); + } + private boolean ok; - /* + /** * Starts main program with the specified arguments. */ public synchronized boolean run(String args[]) { @@ -161,7 +174,7 @@ class Main { } addVersion(manifest); addCreatedBy(manifest); - if (isAmbigousMainClass(manifest)) { + if (isAmbiguousMainClass(manifest)) { if (in != null) { in.close(); } @@ -195,9 +208,7 @@ class Main { FileOutputStream out; if (fname != null) { inputFile = new File(fname); - String path = inputFile.getParent(); - tmpFile = File.createTempFile("tmp", null, - new File((path == null) ? "." : path)); + tmpFile = createTempFileInSameDirectoryAs(inputFile); in = new FileInputStream(inputFile); out = new FileOutputStream(tmpFile); } else { @@ -208,7 +219,8 @@ class Main { InputStream manifest = (!Mflag && (mname != null)) ? (new FileInputStream(mname)) : null; expand(null, files, true); - boolean updateOk = update(in, new BufferedOutputStream(out), manifest, null); + boolean updateOk = update(in, new BufferedOutputStream(out), + manifest, null); if (ok) { ok = updateOk; } @@ -270,8 +282,8 @@ class Main { return ok; } - /* - * Parse command line arguments. + /** + * Parses command line arguments. */ boolean parseArgs(String args[]) { /* Preprocess and expand @file arguments */ @@ -405,7 +417,7 @@ class Main { return true; } - /* + /** * Expands list of files to process into full list of all files that * can be found by recursively descending directories. */ @@ -442,7 +454,7 @@ class Main { } } - /* + /** * Creates a new JAR file. */ void create(OutputStream out, Manifest manifest) @@ -461,7 +473,7 @@ class Main { e.setSize(0); e.setCrc(0); zos.putNextEntry(e); - e = new ZipEntry(MANIFEST); + e = new ZipEntry(MANIFEST_NAME); e.setTime(System.currentTimeMillis()); if (flag0) { crc32Manifest(e, manifest); @@ -476,8 +488,32 @@ class Main { zos.close(); } - /* - * update an existing jar file. + private char toUpperCaseASCII(char c) { + return (c < 'a' || c > 'z') ? c : (char) (c + 'A' - 'a'); + } + + /** + * Compares two strings for equality, ignoring case. The second + * argument must contain only upper-case ASCII characters. + * We don't want case comparison to be locale-dependent (else we + * have the notorious "turkish i bug"). + */ + private boolean equalsIgnoreCase(String s, String upper) { + assert upper.toUpperCase(java.util.Locale.ENGLISH).equals(upper); + int len; + if ((len = s.length()) != upper.length()) + return false; + for (int i = 0; i < len; i++) { + char c1 = s.charAt(i); + char c2 = upper.charAt(i); + if (c1 != c2 && toUpperCaseASCII(c1) != c2) + return false; + } + return true; + } + + /** + * Updates an existing jar file. */ boolean update(InputStream in, OutputStream out, InputStream newManifest, @@ -487,8 +523,6 @@ class Main { ZipOutputStream zos = new JarOutputStream(out); ZipEntry e = null; boolean foundManifest = false; - byte[] buf = new byte[1024]; - int n = 0; boolean updateOk = true; if (jarIndex != null) { @@ -499,10 +533,9 @@ class Main { while ((e = zis.getNextEntry()) != null) { String name = e.getName(); - boolean isManifestEntry = name.toUpperCase( - java.util.Locale.ENGLISH). - equals(MANIFEST); - if ((name.toUpperCase().equals(INDEX) && jarIndex != null) + boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME); + + if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME)) || (Mflag && isManifestEntry)) { continue; } else if (isManifestEntry && ((newManifest != null) || @@ -513,9 +546,9 @@ class Main { // might need it below, and we can't re-read the same data // twice. FileInputStream fis = new FileInputStream(mname); - boolean ambigous = isAmbigousMainClass(new Manifest(fis)); + boolean ambiguous = isAmbiguousMainClass(new Manifest(fis)); fis.close(); - if (ambigous) { + if (ambiguous) { return false; } } @@ -539,9 +572,7 @@ class Main { e2.setCrc(e.getCrc()); } zos.putNextEntry(e2); - while ((n = zis.read(buf, 0, buf.length)) != -1) { - zos.write(buf, 0, n); - } + copy(zis, zos); } else { // replace with the new files File f = entryMap.get(name); addFile(zos, f); @@ -558,7 +589,7 @@ class Main { if (!foundManifest) { if (newManifest != null) { Manifest m = new Manifest(newManifest); - updateOk = !isAmbigousMainClass(m); + updateOk = !isAmbiguousMainClass(m); if (updateOk) { updateManifest(m, zos); } @@ -575,23 +606,16 @@ class Main { private void addIndex(JarIndex index, ZipOutputStream zos) throws IOException { - ZipEntry e = new ZipEntry(INDEX); + ZipEntry e = new ZipEntry(INDEX_NAME); e.setTime(System.currentTimeMillis()); if (flag0) { - e.setMethod(ZipEntry.STORED); - File ifile = File.createTempFile("index", null, new File(".")); - BufferedOutputStream bos = new BufferedOutputStream - (new FileOutputStream(ifile)); - index.write(bos); - crc32File(e, ifile); - bos.close(); - ifile.delete(); + CRC32OutputStream os = new CRC32OutputStream(); + index.write(os); + os.updateEntry(e); } zos.putNextEntry(e); index.write(zos); - if (vflag) { - // output(getMsg("out.update.manifest")); - } + zos.closeEntry(); } private void updateManifest(Manifest m, ZipOutputStream zos) @@ -602,10 +626,9 @@ class Main { if (ename != null) { addMainClass(m, ename); } - ZipEntry e = new ZipEntry(MANIFEST); + ZipEntry e = new ZipEntry(MANIFEST_NAME); e.setTime(System.currentTimeMillis()); if (flag0) { - e.setMethod(ZipEntry.STORED); crc32Manifest(e, m); } zos.putNextEntry(e); @@ -620,7 +643,8 @@ class Main { name = name.replace(File.separatorChar, '/'); String matchPath = ""; for (String path : paths) { - if (name.startsWith(path) && (path.length() > matchPath.length())) { + if (name.startsWith(path) + && (path.length() > matchPath.length())) { matchPath = path; } } @@ -658,7 +682,7 @@ class Main { global.put(Attributes.Name.MAIN_CLASS, mainApp); } - private boolean isAmbigousMainClass(Manifest m) { + private boolean isAmbiguousMainClass(Manifest m) { if (ename != null) { Attributes global = m.getMainAttributes(); if ((global.get(Attributes.Name.MAIN_CLASS) != null)) { @@ -670,7 +694,7 @@ class Main { return false; } - /* + /** * Adds a new file entry to the ZIP output stream. */ void addFile(ZipOutputStream zos, File file) throws IOException { @@ -684,7 +708,7 @@ class Main { if (name.equals("") || name.equals(".") || name.equals(zname)) { return; - } else if ((name.equals(MANIFEST_DIR) || name.equals(MANIFEST)) + } else if ((name.equals(MANIFEST_DIR) || name.equals(MANIFEST_NAME)) && !Mflag) { if (vflag) { output(formatMsg("out.ignore.entry", name)); @@ -704,19 +728,11 @@ class Main { e.setSize(0); e.setCrc(0); } else if (flag0) { - e.setSize(size); - e.setMethod(ZipEntry.STORED); crc32File(e, file); } zos.putNextEntry(e); if (!isDir) { - byte[] buf = new byte[8192]; - int len; - InputStream is = new BufferedInputStream(new FileInputStream(file)); - while ((len = is.read(buf, 0, buf.length)) != -1) { - zos.write(buf, 0, len); - } - is.close(); + copy(file, zos); } zos.closeEntry(); /* report how much compression occurred. */ @@ -737,39 +753,83 @@ class Main { } } - /* - * compute the crc32 of a file. This is necessary when the ZipOutputStream - * is in STORED mode. + /** + * A buffer for use only by copy(InputStream, OutputStream). + * Not as clean as allocating a new buffer as needed by copy, + * but significantly more efficient. */ - private void crc32Manifest(ZipEntry e, Manifest m) throws IOException { - crc32.reset(); - CRC32OutputStream os = new CRC32OutputStream(crc32); - m.write(os); - e.setSize((long) os.n); - e.setCrc(crc32.getValue()); + private byte[] copyBuf = new byte[8192]; + + /** + * Copies all bytes from the input stream to the output stream. + * Does not close or flush either stream. + * + * @param from the input stream to read from + * @param to the output stream to write to + * @throws IOException if an I/O error occurs + */ + private void copy(InputStream from, OutputStream to) throws IOException { + int n; + while ((n = from.read(copyBuf)) != -1) + to.write(copyBuf, 0, n); } - /* - * compute the crc32 of a file. This is necessary when the ZipOutputStream - * is in STORED mode. + /** + * Copies all bytes from the input file to the output stream. + * Does not close or flush the output stream. + * + * @param from the input file to read from + * @param to the output stream to write to + * @throws IOException if an I/O error occurs + */ + private void copy(File from, OutputStream to) throws IOException { + InputStream in = new FileInputStream(from); + try { + copy(in, to); + } finally { + in.close(); + } + } + + /** + * Copies all bytes from the input stream to the output file. + * Does not close the input stream. + * + * @param from the input stream to read from + * @param to the output file to write to + * @throws IOException if an I/O error occurs + */ + private void copy(InputStream from, File to) throws IOException { + OutputStream out = new FileOutputStream(to); + try { + copy(from, out); + } finally { + out.close(); + } + } + + /** + * Computes the crc32 of a Manifest. This is necessary when the + * ZipOutputStream is in STORED mode. + */ + private void crc32Manifest(ZipEntry e, Manifest m) throws IOException { + CRC32OutputStream os = new CRC32OutputStream(); + m.write(os); + os.updateEntry(e); + } + + /** + * Computes the crc32 of a File. This is necessary when the + * ZipOutputStream is in STORED mode. */ private void crc32File(ZipEntry e, File f) throws IOException { - InputStream is = new BufferedInputStream(new FileInputStream(f)); - byte[] buf = new byte[8192]; - crc32.reset(); - int r = 0; - int nread = 0; - long len = f.length(); - while ((r = is.read(buf)) != -1) { - nread += r; - crc32.update(buf, 0, r); - } - is.close(); - if (nread != (int) len) { + CRC32OutputStream os = new CRC32OutputStream(); + copy(f, os); + if (os.n != f.length()) { throw new JarException(formatMsg( "error.incorrect.length", f.getPath())); } - e.setCrc(crc32.getValue()); + os.updateEntry(e); } void replaceFSC(String files[]) { @@ -780,6 +840,7 @@ class Main { } } + @SuppressWarnings("serial") Set newDirSet() { return new HashSet() { public boolean add(ZipEntry e) { @@ -797,7 +858,7 @@ class Main { } } - /* + /** * Extracts specified entries from JAR file. */ void extract(InputStream in, String files[]) throws IOException { @@ -827,7 +888,7 @@ class Main { updateLastModifiedTime(dirs); } - /* + /** * Extracts specified entries from JAR file, via ZipFile. */ void extract(String fname, String files[]) throws IOException { @@ -853,7 +914,7 @@ class Main { updateLastModifiedTime(dirs); } - /* + /** * Extracts next entry from JAR file, creating directories as needed. If * the entry is for a directory which doesn't exist prior to this * invocation, returns that entry, otherwise returns null. @@ -888,19 +949,13 @@ class Main { "error.create.dir", d.getPath())); } } - OutputStream os = new FileOutputStream(f); - byte[] b = new byte[8192]; - int len; try { - while ((len = is.read(b, 0, b.length)) != -1) { - os.write(b, 0, len); - } + copy(is, f); } finally { if (is instanceof ZipInputStream) ((ZipInputStream)is).closeEntry(); else is.close(); - os.close(); } if (vflag) { if (e.getMethod() == ZipEntry.DEFLATED) { @@ -919,7 +974,7 @@ class Main { return rc; } - /* + /** * Lists contents of JAR file. */ void list(InputStream in, String files[]) throws IOException { @@ -937,7 +992,7 @@ class Main { } } - /* + /** * Lists contents of JAR file, via ZipFile. */ void list(String fname, String files[]) throws IOException { @@ -950,32 +1005,38 @@ class Main { } /** - * Output the class index table to the INDEX.LIST file of the + * Outputs the class index table to the INDEX.LIST file of the * root jar file. */ void dumpIndex(String rootjar, JarIndex index) throws IOException { - File scratchFile = File.createTempFile("scratch", null, new File(".")); File jarFile = new File(rootjar); - boolean updateOk = update(new FileInputStream(jarFile), - new FileOutputStream(scratchFile), - null, index); - jarFile.delete(); - if (!scratchFile.renameTo(jarFile)) { - scratchFile.delete(); - throw new IOException(getMsg("error.write.file")); + Path jarPath = jarFile.toPath(); + Path tmpPath = createTempFileInSameDirectoryAs(jarFile).toPath(); + try { + if (update(jarPath.newInputStream(), + tmpPath.newOutputStream(), + null, index)) { + try { + tmpPath.moveTo(jarPath, REPLACE_EXISTING); + } catch (IOException e) { + throw new IOException(getMsg("error.write.file"), e); + } + } + } finally { + tmpPath.deleteIfExists(); } - scratchFile.delete(); } - private Hashtable jarTable = new Hashtable(); - /* - * Generate the transitive closure of the Class-Path attribute for + private HashSet jarPaths = new HashSet(); + + /** + * Generates the transitive closure of the Class-Path attribute for * the specified jar file. */ - Vector getJarPath(String jar) throws IOException { - Vector files = new Vector(); + List getJarPath(String jar) throws IOException { + List files = new ArrayList(); files.add(jar); - jarTable.put(jar, jar); + jarPaths.add(jar); // take out the current path String path = jar.substring(0, Math.max(0, jar.lastIndexOf('/') + 1)); @@ -998,7 +1059,7 @@ class Main { if (!ajar.endsWith("/")) { // it is a jar file ajar = path.concat(ajar); /* check on cyclic dependency */ - if (jarTable.get(ajar) == null) { + if (! jarPaths.contains(ajar)) { files.addAll(getJarPath(ajar)); } } @@ -1012,10 +1073,10 @@ class Main { } /** - * Generate class index file for the specified root jar file. + * Generates class index file for the specified root jar file. */ void genIndex(String rootjar, String[] files) throws IOException { - Vector jars = getJarPath(rootjar); + List jars = getJarPath(rootjar); int njars = jars.size(); String[] jarfiles; @@ -1027,12 +1088,12 @@ class Main { } njars = jars.size(); } - jarfiles = (String[])jars.toArray(new String[njars]); + jarfiles = jars.toArray(new String[njars]); JarIndex index = new JarIndex(jarfiles); dumpIndex(rootjar, index); } - /* + /** * Prints entry information, if requested. */ void printEntry(ZipEntry e, String[] files) throws IOException { @@ -1049,7 +1110,7 @@ class Main { } } - /* + /** * Prints entry information. */ void printEntry(ZipEntry e) throws IOException { @@ -1067,21 +1128,21 @@ class Main { } } - /* - * Print usage message and die. + /** + * Prints usage message. */ void usageError() { error(getMsg("usage")); } - /* + /** * A fatal exception has been caught. No recovery possible */ void fatalError(Exception e) { e.printStackTrace(); } - /* + /** * A fatal condition has been detected; message is "s". * No recovery possible */ @@ -1103,39 +1164,43 @@ class Main { err.println(s); } - /* + /** * Main routine to start program. */ public static void main(String args[]) { Main jartool = new Main(System.out, System.err, "jar"); System.exit(jartool.run(args) ? 0 : 1); } -} -/* - * an OutputStream that doesn't send its output anywhere, (but could). - * It's here to find the CRC32 of a manifest, necessary for STORED only - * mode in ZIP. - */ -final class CRC32OutputStream extends java.io.OutputStream { - CRC32 crc; - int n = 0; - CRC32OutputStream(CRC32 crc) { - this.crc = crc; - } + /** + * An OutputStream that doesn't send its output anywhere, (but could). + * It's here to find the CRC32 of an input file, necessary for STORED + * mode in ZIP. + */ + private static class CRC32OutputStream extends java.io.OutputStream { + final CRC32 crc = new CRC32(); + long n = 0; - public void write(int r) throws IOException { - crc.update(r); - n++; - } + CRC32OutputStream() {} - public void write(byte[] b) throws IOException { - crc.update(b, 0, b.length); - n += b.length; - } + public void write(int r) throws IOException { + crc.update(r); + n++; + } - public void write(byte[] b, int off, int len) throws IOException { - crc.update(b, off, len); - n += len - off; + public void write(byte[] b, int off, int len) throws IOException { + crc.update(b, off, len); + n += len; + } + + /** + * Updates a ZipEntry which describes the data read by this + * output stream, in STORED mode. + */ + public void updateEntry(ZipEntry e) { + e.setMethod(ZipEntry.STORED); + e.setSize(n); + e.setCrc(crc.getValue()); + } } } diff --git a/jdk/test/tools/jar/index/MetaInf.java b/jdk/test/tools/jar/index/MetaInf.java index dae74836938..9e05a8d4fb4 100644 --- a/jdk/test/tools/jar/index/MetaInf.java +++ b/jdk/test/tools/jar/index/MetaInf.java @@ -23,13 +23,15 @@ /* * @test - * @bug 4408526 + * @bug 4408526 6854795 * @summary Index the non-meta files in META-INF, such as META-INF/services. */ import java.io.*; +import java.util.Arrays; import java.util.jar.*; import sun.tools.jar.Main; +import java.util.zip.ZipFile; public class MetaInf { @@ -39,29 +41,51 @@ public class MetaInf { static String contents = System.getProperty("test.src") + File.separatorChar + "jarcontents"; - // Options passed to "jar" command. - static String[] jarArgs1 = new String[] { - "cf", jarName, "-C", contents, SERVICES - }; - static String[] jarArgs2 = new String[] { - "i", jarName - }; + static void run(String ... args) { + if (! new Main(System.out, System.err, "jar").run(args)) + throw new Error("jar failed: args=" + Arrays.toString(args)); + } - public static void main(String[] args) throws IOException { + static void copy(File from, File to) throws IOException { + FileInputStream in = new FileInputStream(from); + FileOutputStream out = new FileOutputStream(to); + try { + byte[] buf = new byte[8192]; + int n; + while ((n = in.read(buf)) != -1) + out.write(buf, 0, n); + } finally { + in.close(); + out.close(); + } + } + + static boolean contains(File jarFile, String entryName) + throws IOException { + return new ZipFile(jarFile).getEntry(entryName) != null; + } + + static void checkContains(File jarFile, String entryName) + throws IOException { + if (! contains(jarFile, entryName)) + throw new Error(String.format("expected jar %s to contain %s", + jarFile, entryName)); + } + + static void testIndex(String jarName) throws IOException { + System.err.printf("jarName=%s%n", jarName); + + File jar = new File(jarName); // Create a jar to be indexed. - Main jarTool = new Main(System.out, System.err, "jar"); - if (!jarTool.run(jarArgs1)) { - throw new Error("Could not create jar file."); + run("cf", jarName, "-C", contents, SERVICES); + + for (int i = 0; i < 2; i++) { + run("i", jarName); + checkContains(jar, INDEX); + checkContains(jar, SERVICES); } - // Index the jar. - jarTool = new Main(System.out, System.err, "jar"); - if (!jarTool.run(jarArgs2)) { - throw new Error("Could not index jar file."); - } - - // Read the index. Verify that META-INF/services is indexed. JarFile f = new JarFile(jarName); BufferedReader index = new BufferedReader( @@ -75,4 +99,17 @@ public class MetaInf { } throw new Error(SERVICES + " not indexed."); } + + public static void main(String[] args) throws IOException { + testIndex("a.jar"); // a path with parent == null + testIndex("./a.zip"); // a path with parent != null + + // Try indexing a jar in the default temp directory. + File tmpFile = File.createTempFile("MetaInf", null, null); + try { + testIndex(tmpFile.getPath()); + } finally { + tmpFile.delete(); + } + } } From 92d332e08b7adf54d18b39f6a5541ab644c67d62 Mon Sep 17 00:00:00 2001 From: Changpeng Fang Date: Mon, 6 Jul 2009 12:54:17 -0700 Subject: [PATCH 24/61] 6857707: Add missing test case for CR 6855164 from its bug description Add missing test case for CR 6855164 from its bug description. Reviewed-by: never --- hotspot/test/compiler/6855164/Test.java | 55 +++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 hotspot/test/compiler/6855164/Test.java diff --git a/hotspot/test/compiler/6855164/Test.java b/hotspot/test/compiler/6855164/Test.java new file mode 100644 index 00000000000..e8113adf783 --- /dev/null +++ b/hotspot/test/compiler/6855164/Test.java @@ -0,0 +1,55 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6855164 + * @summary SIGSEGV during compilation of method involving loop over CharSequence + * @run main/othervm -Xbatch Test + */ + +public class Test{ + public static void main(String[] args) throws Exception { + StringBuffer builder = new StringBuffer(); + + for(int i = 0; i < 100; i++) + builder.append("I am the very model of a modern major general\n"); + + for(int j = 0; j < builder.length(); j++){ + previousSpaceIndex(builder, j); + } + } + + private static final int previousSpaceIndex(CharSequence sb, int seek) { + seek--; + while (seek > 0) { + if (sb.charAt(seek) == ' ') { + while (seek > 0 && sb.charAt(seek - 1) == ' ') + seek--; + return seek; + } + seek--; + } + return 0; + } +} From 5a1032d9e6c08151737f032f9981f3081caab69f Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Mon, 6 Jul 2009 15:53:30 -0700 Subject: [PATCH 25/61] 6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class") Move the secondary raw memory barrier to the correct place in generate_arraycopy(). Reviewed-by: never --- hotspot/src/share/vm/opto/library_call.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 2894cf9a505..4fd8f5044a7 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -4500,27 +4500,27 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, generate_negative_guard(copy_length, slow_region); } + // copy_length is 0. if (!stopped() && must_clear_dest) { Node* dest_length = alloc->in(AllocateNode::ALength); if (_gvn.eqv_uncast(copy_length, dest_length) || _gvn.find_int_con(dest_length, 1) <= 0) { - // There is no zeroing to do. + // There is no zeroing to do. No need for a secondary raw memory barrier. } else { // Clear the whole thing since there are no source elements to copy. generate_clear_array(adr_type, dest, basic_elem_type, intcon(0), NULL, alloc->in(AllocateNode::AllocSize)); + // Use a secondary InitializeNode as raw memory barrier. + // Currently it is needed only on this path since other + // paths have stub or runtime calls as raw memory barriers. + InitializeNode* init = insert_mem_bar_volatile(Op_Initialize, + Compile::AliasIdxRaw, + top())->as_Initialize(); + init->set_complete(&_gvn); // (there is no corresponding AllocateNode) } } - // Use a secondary InitializeNode as raw memory barrier. - // Currently it is needed only on this path since other - // paths have stub or runtime calls as raw memory barriers. - InitializeNode* init = insert_mem_bar_volatile(Op_Initialize, - Compile::AliasIdxRaw, - top())->as_Initialize(); - init->set_complete(&_gvn); // (there is no corresponding AllocateNode) - // Present the results of the fast call. result_region->init_req(zero_path, control()); result_i_o ->init_req(zero_path, i_o()); From f3358ba3db77de135e196b2b2dc57617420c5b06 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Tue, 7 Jul 2009 14:11:06 +0400 Subject: [PATCH 26/61] 6489447: Apply the more robust fix for 6449933 to dolphin and 6ux Reviewed-by: malenkov --- jdk/src/windows/native/sun/windows/ShellFolder2.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jdk/src/windows/native/sun/windows/ShellFolder2.cpp b/jdk/src/windows/native/sun/windows/ShellFolder2.cpp index 6799b098218..64eea69bced 100644 --- a/jdk/src/windows/native/sun/windows/ShellFolder2.cpp +++ b/jdk/src/windows/native/sun/windows/ShellFolder2.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -981,6 +981,15 @@ JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileChooserB hBitmap = (HBITMAP)LoadImage(libShell32, IS_WINVISTA ? TEXT("IDB_TB_SH_DEF_16") : MAKEINTRESOURCE(216), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); + + if (hBitmap == NULL) { + // version of shell32.dll doesn't match OS version. + // So we either are in a Vista Compatibility Mode + // or shell32.dll was copied from OS of another version + hBitmap = (HBITMAP)LoadImage(libShell32, + IS_WINVISTA ? MAKEINTRESOURCE(216) : TEXT("IDB_TB_SH_DEF_16"), + IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); + } } if (hBitmap == NULL) { libComCtl32 = LoadLibrary(TEXT("comctl32.dll")); From b3f3644fea86f475e02ba7b139f30e7a0e191695 Mon Sep 17 00:00:00 2001 From: Anthony Petrov Date: Tue, 7 Jul 2009 17:05:50 +0400 Subject: [PATCH 27/61] 6853916: java.awt.Window.setBackground(null) throws NullPointerException Window.setBackground() should check for null. Reviewed-by: art, dcherepanov --- jdk/src/share/classes/java/awt/Window.java | 2 +- .../SetBackgroundNPE/SetBackgroundNPE.java | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/awt/Window/SetBackgroundNPE/SetBackgroundNPE.java diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index aac5d3789da..31c94ca77e5 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -3597,7 +3597,7 @@ public class Window extends Container implements Accessible { return; } int oldAlpha = oldBg != null ? oldBg.getAlpha() : 255; - int alpha = bgColor.getAlpha(); + int alpha = bgColor != null ? bgColor.getAlpha() : 255; if ((oldAlpha == 255) && (alpha < 255)) { // non-opaque window GraphicsConfiguration gc = getGraphicsConfiguration(); GraphicsDevice gd = gc.getDevice(); diff --git a/jdk/test/java/awt/Window/SetBackgroundNPE/SetBackgroundNPE.java b/jdk/test/java/awt/Window/SetBackgroundNPE/SetBackgroundNPE.java new file mode 100644 index 00000000000..10c9ac72e0f --- /dev/null +++ b/jdk/test/java/awt/Window/SetBackgroundNPE/SetBackgroundNPE.java @@ -0,0 +1,38 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test + @bug 6853916 + @summary Window.setBackground() should not throw NPE + @author anthony.petrov@sun.com: area=awt.toplevel + @run main SetBackgroundNPE +*/ + +import java.awt.Window; + +public class SetBackgroundNPE { + public static void main(String args[]) { + new Window(null).setBackground(null); + } +} From 1215bc6717e86914234311924df59c8c958b40b3 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Tue, 7 Jul 2009 14:23:00 -0400 Subject: [PATCH 28/61] 6855834: G1: minimize the output when -XX:+PrintHeapAtGC is set Changing the behavior of -XX:+PrintHeapAtGC for G1 from printing lengthy, per-region information to instead printing a concise summary. Reviewed-by: ysr, apetrusenko, jcoomes --- .../gc_implementation/g1/g1CollectedHeap.cpp | 473 ++++++++++-------- .../gc_implementation/g1/g1CollectedHeap.hpp | 6 + .../g1/g1CollectorPolicy.hpp | 4 + .../vm/gc_implementation/g1/heapRegion.cpp | 2 +- hotspot/src/share/vm/runtime/globals.hpp | 4 + 5 files changed, 269 insertions(+), 220 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 1c7a5442bfb..a42ace5ecac 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -902,6 +902,10 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, size_t word_size) { ResourceMark rm; + if (PrintHeapAtGC) { + Universe::print_heap_before_gc(); + } + if (full && DisableExplicitGC) { gclog_or_tty->print("\n\n\nDisabling Explicit GC\n\n\n"); return; @@ -927,7 +931,7 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, g1_policy()->record_full_collection_start(); gc_prologue(true); - increment_total_collections(); + increment_total_collections(true /* full gc */); size_t g1h_prev_used = used(); assert(used() == recalculate_used(), "Should be equal"); @@ -1066,6 +1070,10 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, assert( check_young_list_empty(false, false), "young list should be empty at this point"); } + + if (PrintHeapAtGC) { + Universe::print_heap_after_gc(); + } } void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) { @@ -2325,9 +2333,37 @@ public: } }; -void G1CollectedHeap::print() const { print_on(gclog_or_tty); } +void G1CollectedHeap::print() const { print_on(tty); } void G1CollectedHeap::print_on(outputStream* st) const { + print_on(st, PrintHeapAtGCExtended); +} + +void G1CollectedHeap::print_on(outputStream* st, bool extended) const { + st->print(" %-20s", "garbage-first heap"); + st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K", + capacity()/K, used()/K); + st->print(" [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")", + _g1_storage.low_boundary(), + _g1_storage.high(), + _g1_storage.high_boundary()); + st->cr(); + st->print(" region size " SIZE_FORMAT "K, ", + HeapRegion::GrainBytes/K); + size_t young_regions = _young_list->length(); + st->print(SIZE_FORMAT " young (" SIZE_FORMAT "K), ", + young_regions, young_regions * HeapRegion::GrainBytes / K); + size_t survivor_regions = g1_policy()->recorded_survivor_regions(); + st->print(SIZE_FORMAT " survivors (" SIZE_FORMAT "K)", + survivor_regions, survivor_regions * HeapRegion::GrainBytes / K); + st->cr(); + perm()->as_gen()->print_on(st); + if (extended) { + print_on_extended(st); + } +} + +void G1CollectedHeap::print_on_extended(outputStream* st) const { PrintRegionClosure blk(st); _hrs->iterate(&blk); } @@ -2408,10 +2444,6 @@ G1CollectedHeap* G1CollectedHeap::heap() { } void G1CollectedHeap::gc_prologue(bool full /* Ignored */) { - if (PrintHeapAtGC){ - gclog_or_tty->print_cr(" {Heap before GC collections=%d:", total_collections()); - Universe::print(); - } assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); // Call allocation profiler AllocationProfiler::iterate_since_last_gc(); @@ -2425,12 +2457,6 @@ void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) { // is set. COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(), "derived pointer present")); - - if (PrintHeapAtGC){ - gclog_or_tty->print_cr(" Heap after GC collections=%d:", total_collections()); - Universe::print(); - gclog_or_tty->print("} "); - } } void G1CollectedHeap::do_collection_pause() { @@ -2559,241 +2585,250 @@ G1CollectedHeap::cleanup_surviving_young_words() { void G1CollectedHeap::do_collection_pause_at_safepoint() { - char verbose_str[128]; - sprintf(verbose_str, "GC pause "); - if (g1_policy()->in_young_gc_mode()) { - if (g1_policy()->full_young_gcs()) - strcat(verbose_str, "(young)"); - else - strcat(verbose_str, "(partial)"); - } - if (g1_policy()->should_initiate_conc_mark()) - strcat(verbose_str, " (initial-mark)"); - - GCCauseSetter x(this, GCCause::_g1_inc_collection_pause); - - // if PrintGCDetails is on, we'll print long statistics information - // in the collector policy code, so let's not print this as the output - // is messy if we do. - gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); - TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty); - - ResourceMark rm; - assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); - assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread"); - guarantee(!is_gc_active(), "collection is not reentrant"); - assert(regions_accounted_for(), "Region leakage!"); - - increment_gc_time_stamp(); - - if (g1_policy()->in_young_gc_mode()) { - assert(check_young_list_well_formed(), - "young list should be well formed"); + if (PrintHeapAtGC) { + Universe::print_heap_before_gc(); } - if (GC_locker::is_active()) { - return; // GC is disabled (e.g. JNI GetXXXCritical operation) - } + { + char verbose_str[128]; + sprintf(verbose_str, "GC pause "); + if (g1_policy()->in_young_gc_mode()) { + if (g1_policy()->full_young_gcs()) + strcat(verbose_str, "(young)"); + else + strcat(verbose_str, "(partial)"); + } + if (g1_policy()->should_initiate_conc_mark()) + strcat(verbose_str, " (initial-mark)"); - bool abandoned = false; - { // Call to jvmpi::post_class_unload_events must occur outside of active GC - IsGCActiveMark x; + GCCauseSetter x(this, GCCause::_g1_inc_collection_pause); - gc_prologue(false); - increment_total_collections(); + // if PrintGCDetails is on, we'll print long statistics information + // in the collector policy code, so let's not print this as the output + // is messy if we do. + gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); + TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); + TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty); + + ResourceMark rm; + assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); + assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread"); + guarantee(!is_gc_active(), "collection is not reentrant"); + assert(regions_accounted_for(), "Region leakage!"); + + increment_gc_time_stamp(); + + if (g1_policy()->in_young_gc_mode()) { + assert(check_young_list_well_formed(), + "young list should be well formed"); + } + + if (GC_locker::is_active()) { + return; // GC is disabled (e.g. JNI GetXXXCritical operation) + } + + bool abandoned = false; + { // Call to jvmpi::post_class_unload_events must occur outside of active GC + IsGCActiveMark x; + + gc_prologue(false); + increment_total_collections(false /* full gc */); #if G1_REM_SET_LOGGING - gclog_or_tty->print_cr("\nJust chose CS, heap:"); - print(); -#endif - - if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) { - HandleMark hm; // Discard invalid handles created during verification - prepare_for_verify(); - gclog_or_tty->print(" VerifyBeforeGC:"); - Universe::verify(false); - } - - COMPILER2_PRESENT(DerivedPointerTable::clear()); - - // We want to turn off ref discovery, if necessary, and turn it back on - // on again later if we do. - bool was_enabled = ref_processor()->discovery_enabled(); - if (was_enabled) ref_processor()->disable_discovery(); - - // Forget the current alloc region (we might even choose it to be part - // of the collection set!). - abandon_cur_alloc_region(); - - // The elapsed time induced by the start time below deliberately elides - // the possible verification above. - double start_time_sec = os::elapsedTime(); - GCOverheadReporter::recordSTWStart(start_time_sec); - size_t start_used_bytes = used(); - if (!G1ConcMark) { - do_sync_mark(); - } - - g1_policy()->record_collection_pause_start(start_time_sec, - start_used_bytes); - - guarantee(_in_cset_fast_test == NULL, "invariant"); - guarantee(_in_cset_fast_test_base == NULL, "invariant"); - _in_cset_fast_test_length = max_regions(); - _in_cset_fast_test_base = - NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length); - memset(_in_cset_fast_test_base, false, - _in_cset_fast_test_length * sizeof(bool)); - // We're biasing _in_cset_fast_test to avoid subtracting the - // beginning of the heap every time we want to index; basically - // it's the same with what we do with the card table. - _in_cset_fast_test = _in_cset_fast_test_base - - ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); - -#if SCAN_ONLY_VERBOSE - _young_list->print(); -#endif // SCAN_ONLY_VERBOSE - - if (g1_policy()->should_initiate_conc_mark()) { - concurrent_mark()->checkpointRootsInitialPre(); - } - save_marks(); - - // We must do this before any possible evacuation that should propagate - // marks. - if (mark_in_progress()) { - double start_time_sec = os::elapsedTime(); - - _cm->drainAllSATBBuffers(); - double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0; - g1_policy()->record_satb_drain_time(finish_mark_ms); - - } - // Record the number of elements currently on the mark stack, so we - // only iterate over these. (Since evacuation may add to the mark - // stack, doing more exposes race conditions.) If no mark is in - // progress, this will be zero. - _cm->set_oops_do_bound(); - - assert(regions_accounted_for(), "Region leakage."); - - if (mark_in_progress()) - concurrent_mark()->newCSet(); - - // Now choose the CS. - g1_policy()->choose_collection_set(); - - // We may abandon a pause if we find no region that will fit in the MMU - // pause. - bool abandoned = (g1_policy()->collection_set() == NULL); - - // Nothing to do if we were unable to choose a collection set. - if (!abandoned) { -#if G1_REM_SET_LOGGING - gclog_or_tty->print_cr("\nAfter pause, heap:"); + gclog_or_tty->print_cr("\nJust chose CS, heap:"); print(); #endif - setup_surviving_young_words(); + if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) { + HandleMark hm; // Discard invalid handles created during verification + prepare_for_verify(); + gclog_or_tty->print(" VerifyBeforeGC:"); + Universe::verify(false); + } - // Set up the gc allocation regions. - get_gc_alloc_regions(); + COMPILER2_PRESENT(DerivedPointerTable::clear()); - // Actually do the work... - evacuate_collection_set(); - free_collection_set(g1_policy()->collection_set()); - g1_policy()->clear_collection_set(); + // We want to turn off ref discovery, if necessary, and turn it back on + // on again later if we do. + bool was_enabled = ref_processor()->discovery_enabled(); + if (was_enabled) ref_processor()->disable_discovery(); - FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); - // this is more for peace of mind; we're nulling them here and - // we're expecting them to be null at the beginning of the next GC - _in_cset_fast_test = NULL; - _in_cset_fast_test_base = NULL; + // Forget the current alloc region (we might even choose it to be part + // of the collection set!). + abandon_cur_alloc_region(); - release_gc_alloc_regions(false /* totally */); + // The elapsed time induced by the start time below deliberately elides + // the possible verification above. + double start_time_sec = os::elapsedTime(); + GCOverheadReporter::recordSTWStart(start_time_sec); + size_t start_used_bytes = used(); + if (!G1ConcMark) { + do_sync_mark(); + } - cleanup_surviving_young_words(); + g1_policy()->record_collection_pause_start(start_time_sec, + start_used_bytes); - if (g1_policy()->in_young_gc_mode()) { - _young_list->reset_sampled_info(); - assert(check_young_list_empty(true), - "young list should be empty"); + guarantee(_in_cset_fast_test == NULL, "invariant"); + guarantee(_in_cset_fast_test_base == NULL, "invariant"); + _in_cset_fast_test_length = max_regions(); + _in_cset_fast_test_base = + NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length); + memset(_in_cset_fast_test_base, false, + _in_cset_fast_test_length * sizeof(bool)); + // We're biasing _in_cset_fast_test to avoid subtracting the + // beginning of the heap every time we want to index; basically + // it's the same with what we do with the card table. + _in_cset_fast_test = _in_cset_fast_test_base - + ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); #if SCAN_ONLY_VERBOSE - _young_list->print(); + _young_list->print(); #endif // SCAN_ONLY_VERBOSE - g1_policy()->record_survivor_regions(_young_list->survivor_length(), - _young_list->first_survivor_region(), - _young_list->last_survivor_region()); - _young_list->reset_auxilary_lists(); + if (g1_policy()->should_initiate_conc_mark()) { + concurrent_mark()->checkpointRootsInitialPre(); } - } else { - COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); - } + save_marks(); - if (evacuation_failed()) { - _summary_bytes_used = recalculate_used(); - } else { - // The "used" of the the collection set have already been subtracted - // when they were freed. Add in the bytes evacuated. - _summary_bytes_used += g1_policy()->bytes_in_to_space(); - } + // We must do this before any possible evacuation that should propagate + // marks. + if (mark_in_progress()) { + double start_time_sec = os::elapsedTime(); - if (g1_policy()->in_young_gc_mode() && - g1_policy()->should_initiate_conc_mark()) { - concurrent_mark()->checkpointRootsInitialPost(); - set_marking_started(); - doConcurrentMark(); - } - -#if SCAN_ONLY_VERBOSE - _young_list->print(); -#endif // SCAN_ONLY_VERBOSE - - double end_time_sec = os::elapsedTime(); - double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; - g1_policy()->record_pause_time_ms(pause_time_ms); - GCOverheadReporter::recordSTWEnd(end_time_sec); - g1_policy()->record_collection_pause_end(abandoned); - - assert(regions_accounted_for(), "Region leakage."); - - if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { - HandleMark hm; // Discard invalid handles created during verification - gclog_or_tty->print(" VerifyAfterGC:"); - prepare_for_verify(); - Universe::verify(false); - } - - if (was_enabled) ref_processor()->enable_discovery(); - - { - size_t expand_bytes = g1_policy()->expansion_amount(); - if (expand_bytes > 0) { - size_t bytes_before = capacity(); - expand(expand_bytes); + _cm->drainAllSATBBuffers(); + double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0; + g1_policy()->record_satb_drain_time(finish_mark_ms); } - } + // Record the number of elements currently on the mark stack, so we + // only iterate over these. (Since evacuation may add to the mark + // stack, doing more exposes race conditions.) If no mark is in + // progress, this will be zero. + _cm->set_oops_do_bound(); - if (mark_in_progress()) { - concurrent_mark()->update_g1_committed(); - } + assert(regions_accounted_for(), "Region leakage."); -#ifdef TRACESPINNING - ParallelTaskTerminator::print_termination_counts(); + if (mark_in_progress()) + concurrent_mark()->newCSet(); + + // Now choose the CS. + g1_policy()->choose_collection_set(); + + // We may abandon a pause if we find no region that will fit in the MMU + // pause. + bool abandoned = (g1_policy()->collection_set() == NULL); + + // Nothing to do if we were unable to choose a collection set. + if (!abandoned) { +#if G1_REM_SET_LOGGING + gclog_or_tty->print_cr("\nAfter pause, heap:"); + print(); #endif - gc_epilogue(false); + setup_surviving_young_words(); + + // Set up the gc allocation regions. + get_gc_alloc_regions(); + + // Actually do the work... + evacuate_collection_set(); + free_collection_set(g1_policy()->collection_set()); + g1_policy()->clear_collection_set(); + + FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); + // this is more for peace of mind; we're nulling them here and + // we're expecting them to be null at the beginning of the next GC + _in_cset_fast_test = NULL; + _in_cset_fast_test_base = NULL; + + release_gc_alloc_regions(false /* totally */); + + cleanup_surviving_young_words(); + + if (g1_policy()->in_young_gc_mode()) { + _young_list->reset_sampled_info(); + assert(check_young_list_empty(true), + "young list should be empty"); + +#if SCAN_ONLY_VERBOSE + _young_list->print(); +#endif // SCAN_ONLY_VERBOSE + + g1_policy()->record_survivor_regions(_young_list->survivor_length(), + _young_list->first_survivor_region(), + _young_list->last_survivor_region()); + _young_list->reset_auxilary_lists(); + } + } else { + COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); + } + + if (evacuation_failed()) { + _summary_bytes_used = recalculate_used(); + } else { + // The "used" of the the collection set have already been subtracted + // when they were freed. Add in the bytes evacuated. + _summary_bytes_used += g1_policy()->bytes_in_to_space(); + } + + if (g1_policy()->in_young_gc_mode() && + g1_policy()->should_initiate_conc_mark()) { + concurrent_mark()->checkpointRootsInitialPost(); + set_marking_started(); + doConcurrentMark(); + } + +#if SCAN_ONLY_VERBOSE + _young_list->print(); +#endif // SCAN_ONLY_VERBOSE + + double end_time_sec = os::elapsedTime(); + double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; + g1_policy()->record_pause_time_ms(pause_time_ms); + GCOverheadReporter::recordSTWEnd(end_time_sec); + g1_policy()->record_collection_pause_end(abandoned); + + assert(regions_accounted_for(), "Region leakage."); + + if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { + HandleMark hm; // Discard invalid handles created during verification + gclog_or_tty->print(" VerifyAfterGC:"); + prepare_for_verify(); + Universe::verify(false); + } + + if (was_enabled) ref_processor()->enable_discovery(); + + { + size_t expand_bytes = g1_policy()->expansion_amount(); + if (expand_bytes > 0) { + size_t bytes_before = capacity(); + expand(expand_bytes); + } + } + + if (mark_in_progress()) { + concurrent_mark()->update_g1_committed(); + } + +#ifdef TRACESPINNING + ParallelTaskTerminator::print_termination_counts(); +#endif + + gc_epilogue(false); + } + + assert(verify_region_lists(), "Bad region lists."); + + if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) { + gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum); + print_tracing_info(); + vm_exit(-1); + } } - assert(verify_region_lists(), "Bad region lists."); - - if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) { - gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum); - print_tracing_info(); - vm_exit(-1); + if (PrintHeapAtGC) { + Universe::print_heap_after_gc(); } } @@ -5357,7 +5392,7 @@ void G1CollectedHeap::tear_down_region_lists() { assert(_free_region_list == NULL, "Postcondition of loop."); if (_free_region_list_size != 0) { gclog_or_tty->print_cr("Size is %d.", _free_region_list_size); - print(); + print_on(gclog_or_tty, true /* extended */); } assert(_free_region_list_size == 0, "Postconditions of loop."); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index bc68d7f7804..82cfc8488f3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1061,8 +1061,14 @@ public: // Override; it uses the "prev" marking information virtual void verify(bool allow_dirty, bool silent); + // Default behavior by calling print(tty); virtual void print() const; + // This calls print_on(st, PrintHeapAtGCExtended). virtual void print_on(outputStream* st) const; + // If extended is true, it will print out information for all + // regions in the heap by calling print_on_extended(st). + virtual void print_on(outputStream* st, bool extended) const; + virtual void print_on_extended(outputStream* st) const; virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index 8b8927571a8..8fa4ef4a8a1 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -1097,6 +1097,10 @@ public: _recorded_survivor_tail = tail; } + size_t recorded_survivor_regions() { + return _recorded_survivor_regions; + } + void record_thread_age_table(ageTable* age_table) { _survivors_age_table.merge_par(age_table); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index b844b2e70be..43af2b52cb7 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -703,7 +703,7 @@ void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const { } if (vl_cl.failures()) { gclog_or_tty->print_cr("Heap:"); - G1CollectedHeap::heap()->print(); + G1CollectedHeap::heap()->print_on(gclog_or_tty, true /* extended */); gclog_or_tty->print_cr(""); } if (VerifyDuringGC && diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 85d55ea382a..781bc93aae5 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1994,6 +1994,10 @@ class CommandLineFlags { product_rw(bool, PrintHeapAtGC, false, \ "Print heap layout before and after each GC") \ \ + product_rw(bool, PrintHeapAtGCExtended, false, \ + "Prints extended information about the layout of the heap " \ + "when -XX:+PrintHeapAtGC is set") \ + \ product(bool, PrintHeapAtSIGBREAK, true, \ "Print heap layout in response to SIGBREAK") \ \ From 21aa3652d44605eb6a91fcfddc1d206398295503 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 7 Jul 2009 16:12:34 -0700 Subject: [PATCH 29/61] 6857803: Missing links to exceptions in javadoc for Class.getGeneric{Superclass, Interfaces} Reviewed-by: chegar --- jdk/src/share/classes/java/lang/Class.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 4ba497c64cf..ddf57631790 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -627,7 +627,7 @@ public final * * @return an array of {@code TypeVariable} objects that represent * the type variables declared by this generic declaration - * @throws GenericSignatureFormatError if the generic + * @throws java.lang.reflect.GenericSignatureFormatError if the generic * signature of this generic declaration does not conform to * the format specified in the Java Virtual Machine Specification, * 3rd edition @@ -673,12 +673,12 @@ public final * {@code Class} object representing the {@code Object} class is * returned. * - * @throws GenericSignatureFormatError if the generic + * @throws java.lang.reflect.GenericSignatureFormatError if the generic * class signature does not conform to the format specified in the * Java Virtual Machine Specification, 3rd edition * @throws TypeNotPresentException if the generic superclass * refers to a non-existent type declaration - * @throws MalformedParameterizedTypeException if the + * @throws java.lang.reflect.MalformedParameterizedTypeException if the * generic superclass refers to a parameterized type that cannot be * instantiated for any reason * @return the superclass of the class represented by this object @@ -795,14 +795,14 @@ public final *

    If this object represents a primitive type or void, the * method returns an array of length 0. * - * @throws GenericSignatureFormatError + * @throws java.lang.reflect.GenericSignatureFormatError * if the generic class signature does not conform to the format * specified in the Java Virtual Machine Specification, 3rd edition * @throws TypeNotPresentException if any of the generic * superinterfaces refers to a non-existent type declaration - * @throws MalformedParameterizedTypeException if any of the - * generic superinterfaces refer to a parameterized type that cannot - * be instantiated for any reason + * @throws java.lang.reflect.MalformedParameterizedTypeException + * if any of the generic superinterfaces refer to a parameterized + * type that cannot be instantiated for any reason * @return an array of interfaces implemented by this class * @since 1.5 */ From 96a8d1a9f8805de2786eee08b3352b49a6dacb16 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Wed, 8 Jul 2009 12:07:16 +0800 Subject: [PATCH 30/61] 6857802: GSS getRemainingInitLifetime method returns milliseconds not seconds Reviewed-by: xuelei --- .../jgss/krb5/Krb5InitCredential.java | 2 +- .../security/krb5/auto/LifeTimeInSeconds.java | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 jdk/test/sun/security/krb5/auto/LifeTimeInSeconds.java diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java index 1aac87223e1..4718f57e7d3 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java @@ -238,7 +238,7 @@ public class Krb5InitCredential retVal = (int)(getEndTime().getTime() - (new Date().getTime())); - return retVal; + return retVal/1000; } /** diff --git a/jdk/test/sun/security/krb5/auto/LifeTimeInSeconds.java b/jdk/test/sun/security/krb5/auto/LifeTimeInSeconds.java new file mode 100644 index 00000000000..2d20fc415bb --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/LifeTimeInSeconds.java @@ -0,0 +1,50 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6857802 + * @summary GSS getRemainingInitLifetime method returns milliseconds not seconds + */ +import org.ietf.jgss.GSSCredential; +import org.ietf.jgss.GSSManager; + +public class LifeTimeInSeconds { + public static void main(String[] args) throws Exception { + new OneKDC(null).writeJAASConf(); + System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); + + GSSManager gm = GSSManager.getInstance(); + GSSCredential cred = gm.createCredential(GSSCredential.INITIATE_AND_ACCEPT); + int time = cred.getRemainingLifetime(); + int time2 = cred.getRemainingInitLifetime(null); + // The test KDC issues a TGT with a default lifetime of 11 hours + int elevenhrs = 11*3600; + if (time > elevenhrs+60 || time < elevenhrs-60) { + throw new Exception("getRemainingLifetime returns wrong value."); + } + if (time2 > elevenhrs+60 || time2 < elevenhrs-60) { + throw new Exception("getRemainingInitLifetime returns wrong value."); + } + } +} From 9148ed61cfd3c9f22826249ea3639e90e23c73ab Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Wed, 8 Jul 2009 12:07:43 +0800 Subject: [PATCH 31/61] 6857795: krb5.conf ignored if system properties on realm and kdc are provided Reviewed-by: xuelei --- .../classes/sun/security/krb5/Config.java | 35 ++++--- jdk/test/sun/security/krb5/ConfPlusProp.java | 94 +++++++++++++++++++ jdk/test/sun/security/krb5/confplusprop.conf | 11 +++ jdk/test/sun/security/krb5/confplusprop2.conf | 7 ++ 4 files changed, 133 insertions(+), 14 deletions(-) create mode 100644 jdk/test/sun/security/krb5/ConfPlusProp.java create mode 100644 jdk/test/sun/security/krb5/confplusprop.conf create mode 100644 jdk/test/sun/security/krb5/confplusprop2.conf diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java index e036776f53e..8adcba81f53 100644 --- a/jdk/src/share/classes/sun/security/krb5/Config.java +++ b/jdk/src/share/classes/sun/security/krb5/Config.java @@ -123,7 +123,7 @@ public class Config { java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction ("java.security.krb5.kdc")); - defaultRealm = + defaultRealm = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction ("java.security.krb5.realm")); @@ -134,6 +134,16 @@ public class Config { "java.security.krb5.realm both must be set or " + "neither must be set."); } + + // Read the Kerberos configuration file + try { + Vector configFile; + configFile = loadConfigFile(); + stanzaTable = parseStanzaTable(configFile); + } catch (IOException ioe) { + // No krb5.conf, no problem. We'll use DNS etc. + } + if (kdchost != null) { /* * If configuration information is only specified by @@ -141,22 +151,19 @@ public class Config { * java.security.krb5.realm, we put both in the hashtable * under [libdefaults]. */ - Hashtable kdcs = new Hashtable (); + if (stanzaTable == null) { + stanzaTable = new Hashtable (); + } + Hashtable kdcs = + (Hashtable)stanzaTable.get("libdefaults"); + if (kdcs == null) { + kdcs = new Hashtable (); + stanzaTable.put("libdefaults", kdcs); + } kdcs.put("default_realm", defaultRealm); // The user can specify a list of kdc hosts separated by ":" kdchost = kdchost.replace(':', ' '); kdcs.put("kdc", kdchost); - stanzaTable = new Hashtable (); - stanzaTable.put("libdefaults", kdcs); - } else { - // Read the Kerberos configuration file - try { - Vector configFile; - configFile = loadConfigFile(); - stanzaTable = parseStanzaTable(configFile); - } catch (IOException ioe) { - // No krb5.conf, no problem. We'll use DNS etc. - } } } @@ -294,7 +301,7 @@ public class Config { * hashtable. */ if (name.equalsIgnoreCase("kdc") && - (!section.equalsIgnoreCase("libdefaults")) && + (section.equalsIgnoreCase(getDefault("default_realm", "libdefaults"))) && (java.security.AccessController.doPrivileged( new sun.security.action. GetPropertyAction("java.security.krb5.kdc")) != null)) { diff --git a/jdk/test/sun/security/krb5/ConfPlusProp.java b/jdk/test/sun/security/krb5/ConfPlusProp.java new file mode 100644 index 00000000000..b1ea2ca5e75 --- /dev/null +++ b/jdk/test/sun/security/krb5/ConfPlusProp.java @@ -0,0 +1,94 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @test + * @bug 6857795 + * @summary krb5.conf ignored if system properties on realm and kdc are provided + */ + +import sun.security.krb5.Config; +import sun.security.krb5.KrbException; + +public class ConfPlusProp { + public static void main(String[] args) throws Exception { + System.setProperty("java.security.krb5.realm", "R2"); + System.setProperty("java.security.krb5.kdc", "k2"); + + // Point to a file with existing default_realm + System.setProperty("java.security.krb5.conf", + System.getProperty("test.src", ".") +"/confplusprop.conf"); + Config config = Config.getInstance(); + + if (!config.getDefaultRealm().equals("R2")) { + throw new Exception("Default realm error"); + } + if (!config.getKDCList("R1").equals("k1")) { + throw new Exception("R1 kdc error"); + } + if (!config.getKDCList("R2").equals("k2")) { + throw new Exception("R2 kdc error"); + } + if (!config.getDefault("forwardable", "libdefaults").equals("well")) { + throw new Exception("Extra config error"); + } + + // Point to a file with no libdefaults + System.setProperty("java.security.krb5.conf", + System.getProperty("test.src", ".") +"/confplusprop2.conf"); + Config.refresh(); + + config = Config.getInstance(); + + if (!config.getDefaultRealm().equals("R2")) { + throw new Exception("Default realm error again"); + } + if (!config.getKDCList("R1").equals("k12")) { + throw new Exception("R1 kdc error"); + } + if (!config.getKDCList("R2").equals("k2")) { + throw new Exception("R2 kdc error"); + } + + // Point to a non-existing file + System.setProperty("java.security.krb5.conf", "i-am-not-a file"); + Config.refresh(); + + config = Config.getInstance(); + + if (!config.getDefaultRealm().equals("R2")) { + throw new Exception("Default realm error"); + } + try { + config.getKDCList("R1"); + throw new Exception("R1 is nowhere"); + } catch (KrbException ke) { + // OK + } + if (!config.getKDCList("R2").equals("k2")) { + throw new Exception("R2 kdc error"); + } + if (config.getDefault("forwardable", "libdefaults") != null) { + throw new Exception("Extra config error"); + } + } +} diff --git a/jdk/test/sun/security/krb5/confplusprop.conf b/jdk/test/sun/security/krb5/confplusprop.conf new file mode 100644 index 00000000000..80c925b14cd --- /dev/null +++ b/jdk/test/sun/security/krb5/confplusprop.conf @@ -0,0 +1,11 @@ +[libdefaults] +default_realm = R1 +forwardable = well + +[realms] +R1 = { + kdc = k1 +} +R2 = { + kdc = old +} diff --git a/jdk/test/sun/security/krb5/confplusprop2.conf b/jdk/test/sun/security/krb5/confplusprop2.conf new file mode 100644 index 00000000000..df00eccbccf --- /dev/null +++ b/jdk/test/sun/security/krb5/confplusprop2.conf @@ -0,0 +1,7 @@ +[realms] +R1 = { + kdc = k12 +} +R2 = { + kdc = old +} From 529e9065c2026ba0d359af78d1b8f0c6d0596371 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Wed, 8 Jul 2009 09:11:24 -0700 Subject: [PATCH 32/61] 6858127: Missing -DNDEBUG on Linux and Windows native code compiles Reviewed-by: tbell, dcubed --- jdk/make/common/Defs-linux.gmk | 2 +- jdk/make/common/Defs-windows.gmk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/make/common/Defs-linux.gmk b/jdk/make/common/Defs-linux.gmk index 672affde32b..424eaf0a7db 100644 --- a/jdk/make/common/Defs-linux.gmk +++ b/jdk/make/common/Defs-linux.gmk @@ -193,7 +193,7 @@ ifeq ($(ARCH_DATA_MODEL), 64) CPPFLAGS_COMMON += -D_LP64=1 endif -CPPFLAGS_OPT = +CPPFLAGS_OPT = -DNDEBUG CPPFLAGS_DBG = -DDEBUG ifneq ($(PRODUCT), java) CPPFLAGS_DBG += -DLOGGING diff --git a/jdk/make/common/Defs-windows.gmk b/jdk/make/common/Defs-windows.gmk index 00b8ea71e2a..0c220107df2 100644 --- a/jdk/make/common/Defs-windows.gmk +++ b/jdk/make/common/Defs-windows.gmk @@ -363,7 +363,7 @@ ifeq ($(COMPILER_WARNINGS_FATAL),true) CFLAGS_COMMON += -WX endif -CPPFLAGS_OPT = +CPPFLAGS_OPT = -DNDEBUG CPPFLAGS_DBG = -DDEBUG -DLOGGING CXXFLAGS_COMMON = $(CFLAGS_COMMON) From 64697c3e7ac7741b9b62373bcca0fcb5a08e730d Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Wed, 8 Jul 2009 09:12:17 -0700 Subject: [PATCH 33/61] 6855551: java -Xrunhprof crashes when running with classes compiled with targed=7 Reviewed-by: tbell, dcubed --- jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c | 4 ++-- jdk/test/demo/jvmti/hprof/HelloWorld.java | 2 +- jdk/test/demo/jvmti/hprof/StackMapTableTest.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c b/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c index 6d43d9baa90..d241e80dafa 100644 --- a/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c +++ b/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c @@ -263,8 +263,8 @@ assert_error(CrwClassImage *ci, const char *condition, (void)sprintf(buf, "CRW ASSERTION FAILURE: %s (%s:%s:%d)", condition, - ci->name==0?"?":ci->name, - mi->name==0?"?":mi->name, + ci->name==NULL?"?":ci->name, + (mi==NULL||mi->name==NULL)?"?":mi->name, byte_code_offset); fatal_error(ci, buf, file, line); } diff --git a/jdk/test/demo/jvmti/hprof/HelloWorld.java b/jdk/test/demo/jvmti/hprof/HelloWorld.java index e349bbd08e9..ae8ec5c1482 100644 --- a/jdk/test/demo/jvmti/hprof/HelloWorld.java +++ b/jdk/test/demo/jvmti/hprof/HelloWorld.java @@ -24,7 +24,7 @@ /* HelloWorld: * - * Sample target appluication for HPROF tests + * Sample target application for HPROF tests * */ diff --git a/jdk/test/demo/jvmti/hprof/StackMapTableTest.java b/jdk/test/demo/jvmti/hprof/StackMapTableTest.java index a34614dfccb..0acc6fe61dc 100644 --- a/jdk/test/demo/jvmti/hprof/StackMapTableTest.java +++ b/jdk/test/demo/jvmti/hprof/StackMapTableTest.java @@ -23,11 +23,11 @@ /* @test - * @bug 6266289 6299047 + * @bug 6266289 6299047 6855180 6855551 * @summary Test jvmti hprof and java_crw_demo with StackMapTable attributes * * @compile ../DemoRun.java - * @compile -source 1.6 -g:lines HelloWorld.java + * @compile -source 7 -g:lines HelloWorld.java * @build StackMapTableTest * @run main StackMapTableTest HelloWorld */ From 74d89957476c683d095d1d99325184e82b4cd1fc Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Thu, 9 Jul 2009 15:15:28 -0400 Subject: [PATCH 34/61] 6855323: Robot(GraphicsDevice) constructor initializes LEGAL_BUTTON_MASK variable improperly Reviewed-by: art --- jdk/src/share/classes/java/awt/Robot.java | 41 ++++++----- .../java/awt/Robot/CtorTest/CtorTest.java | 71 +++++++++++++++++++ 2 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 jdk/test/java/awt/Robot/CtorTest/CtorTest.java diff --git a/jdk/src/share/classes/java/awt/Robot.java b/jdk/src/share/classes/java/awt/Robot.java index f7a40c740bc..1233c291a3e 100644 --- a/jdk/src/share/classes/java/awt/Robot.java +++ b/jdk/src/share/classes/java/awt/Robot.java @@ -70,7 +70,7 @@ public class Robot { private RobotPeer peer; private boolean isAutoWaitForIdle = false; private int autoDelay = 0; - private static int LEGAL_BUTTON_MASK; + private static int LEGAL_BUTTON_MASK = 0; // location of robot's GC, used in mouseMove(), getPixelColor() and captureScreenImage() private Point gdLoc; @@ -95,23 +95,6 @@ public class Robot { } init(GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice()); - int tmpMask = 0; - - if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ - if (Toolkit.getDefaultToolkit() instanceof SunToolkit) { - final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons(); - for (int i = 0; i < buttonsNumber; i++){ - tmpMask |= InputEvent.getMaskForButton(i+1); - } - } - } - tmpMask |= InputEvent.BUTTON1_MASK| - InputEvent.BUTTON2_MASK| - InputEvent.BUTTON3_MASK| - InputEvent.BUTTON1_DOWN_MASK| - InputEvent.BUTTON2_DOWN_MASK| - InputEvent.BUTTON3_DOWN_MASK; - LEGAL_BUTTON_MASK = tmpMask; } /** @@ -156,6 +139,28 @@ public class Robot { disposer = new RobotDisposer(peer); sun.java2d.Disposer.addRecord(anchor, disposer); } + initLegalButtonMask(); + } + + private static synchronized void initLegalButtonMask() { + if (LEGAL_BUTTON_MASK != 0) return; + + int tmpMask = 0; + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + if (Toolkit.getDefaultToolkit() instanceof SunToolkit) { + final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons(); + for (int i = 0; i < buttonsNumber; i++){ + tmpMask |= InputEvent.getMaskForButton(i+1); + } + } + } + tmpMask |= InputEvent.BUTTON1_MASK| + InputEvent.BUTTON2_MASK| + InputEvent.BUTTON3_MASK| + InputEvent.BUTTON1_DOWN_MASK| + InputEvent.BUTTON2_DOWN_MASK| + InputEvent.BUTTON3_DOWN_MASK; + LEGAL_BUTTON_MASK = tmpMask; } /* determine if the security policy allows Robot's to be created */ diff --git a/jdk/test/java/awt/Robot/CtorTest/CtorTest.java b/jdk/test/java/awt/Robot/CtorTest/CtorTest.java new file mode 100644 index 00000000000..ea9c56fa2d5 --- /dev/null +++ b/jdk/test/java/awt/Robot/CtorTest/CtorTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test + @bug 6855323 + @summary Robot(GraphicsDevice) constructor initializes LEGAL_BUTTON_MASK variable improperly + @author Dmitry Cherepanov area=awt.robot + @run main CtorTest +*/ + +/** + * CtorRobot.java + * + * summary: creates Robot using one parameter constructor + */ + +import java.awt.*; +import java.awt.event.*; + +import sun.awt.SunToolkit; + +public class CtorTest +{ + public static void main(String []s) throws Exception + { + // one parameter constructor + GraphicsDevice graphicsDevice = GraphicsEnvironment. + getLocalGraphicsEnvironment().getDefaultScreenDevice(); + Robot robot = new Robot(graphicsDevice); + clickOnFrame(robot); + } + + // generate mouse events + private static void clickOnFrame(Robot robot) { + Frame frame = new Frame(); + frame.setBounds(100, 100, 100, 100); + frame.setVisible(true); + + ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); + + // click in the middle of the frame + robot.mouseMove(150, 150); + robot.delay(50); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); + } +} From 4d337f68e85eda235757611ebc1dbadfe92da276 Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Thu, 9 Jul 2009 15:18:50 -0400 Subject: [PATCH 35/61] 6759726: TrayIcon constructor throws NPE instead of documented IAE Reviewed-by: art --- jdk/src/share/classes/java/awt/TrayIcon.java | 3 ++ .../java/awt/TrayIcon/CtorTest/CtorTest.java | 53 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 jdk/test/java/awt/TrayIcon/CtorTest/CtorTest.java diff --git a/jdk/src/share/classes/java/awt/TrayIcon.java b/jdk/src/share/classes/java/awt/TrayIcon.java index 9fcdd2a6af1..e0c31f8c3ee 100644 --- a/jdk/src/share/classes/java/awt/TrayIcon.java +++ b/jdk/src/share/classes/java/awt/TrayIcon.java @@ -143,6 +143,9 @@ public class TrayIcon { */ public TrayIcon(Image image) { this(); + if (image == null) { + throw new IllegalArgumentException("creating TrayIcon with null Image"); + } setImage(image); } diff --git a/jdk/test/java/awt/TrayIcon/CtorTest/CtorTest.java b/jdk/test/java/awt/TrayIcon/CtorTest/CtorTest.java new file mode 100644 index 00000000000..d16034a1a01 --- /dev/null +++ b/jdk/test/java/awt/TrayIcon/CtorTest/CtorTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test + @bug 6759726 + @summary TrayIcon constructor throws NPE instead of documented IAE + @author Dmitry Cherepanov area=awt.tray + @run main CtorTest +*/ + +/** + * CtorTest.java + * + * summary: TrayIcon ctor throws IAE if image is null + */ + +import java.awt.*; + +public class CtorTest +{ + public static void main(String []s) + { + boolean isSupported = SystemTray.isSupported(); + if (isSupported) { + try { + TrayIcon tray = new TrayIcon(null); + } catch(IllegalArgumentException e) { + // ctor should throw IAE + } + } + } +} From cd90c35e8f20b3b53ed9ed87d480c501aa6750c3 Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Thu, 9 Jul 2009 15:23:22 -0400 Subject: [PATCH 36/61] 6847958: MouseWheel event is getting triggered for the disabled Textarea in jdk7 b60 pit build Reviewed-by: art --- .../classes/sun/awt/X11/XBaseWindow.java | 5 +- .../DisabledComponent/DisabledComponent.java | 107 ++++++++++++++++++ 2 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 jdk/test/java/awt/event/MouseWheelEvent/DisabledComponent/DisabledComponent.java diff --git a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java index 07a4fc7c265..0cd25523538 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java @@ -1000,10 +1000,7 @@ public class XBaseWindow { int buttonState = 0; final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons(); for (int i = 0; i Date: Thu, 9 Jul 2009 15:53:07 +0400 Subject: [PATCH 37/61] 6847149: test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java fails Reviewed-by: art --- jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java b/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java index 44f43c1b3bf..dda735cb7f3 100644 --- a/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java +++ b/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java @@ -65,6 +65,7 @@ public class OwnedWindowsLeak break; } } + garbage = null; // Third, make sure all the weak references are null for (WeakReference ref : children) From 40a7ea7c9c6ded29c0774c04f561698f5c163e43 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 9 Jul 2009 12:31:30 -0700 Subject: [PATCH 38/61] 6628737: Specification of wrapper class valueOf static factories should require caching Reviewed-by: mr --- jdk/src/share/classes/java/lang/Byte.java | 4 ++-- jdk/src/share/classes/java/lang/Character.java | 4 ++++ jdk/src/share/classes/java/lang/Integer.java | 3 +++ jdk/src/share/classes/java/lang/Long.java | 5 +++++ jdk/src/share/classes/java/lang/Short.java | 3 +++ 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Byte.java b/jdk/src/share/classes/java/lang/Byte.java index 2bb6480c539..ba7486377d6 100644 --- a/jdk/src/share/classes/java/lang/Byte.java +++ b/jdk/src/share/classes/java/lang/Byte.java @@ -90,8 +90,8 @@ public final class Byte extends Number implements Comparable { * If a new {@code Byte} instance is not required, this method * should generally be used in preference to the constructor * {@link #Byte(byte)}, as this method is likely to yield - * significantly better space and time performance by caching - * frequently requested values. + * significantly better space and time performance since + * all byte values are cached. * * @param b a byte value. * @return a {@code Byte} instance representing {@code b}. diff --git a/jdk/src/share/classes/java/lang/Character.java b/jdk/src/share/classes/java/lang/Character.java index e33052ee170..9b9c938fa1e 100644 --- a/jdk/src/share/classes/java/lang/Character.java +++ b/jdk/src/share/classes/java/lang/Character.java @@ -2571,6 +2571,10 @@ class Character extends Object implements java.io.Serializable, ComparableCharacter instance representing c. * @since 1.5 diff --git a/jdk/src/share/classes/java/lang/Integer.java b/jdk/src/share/classes/java/lang/Integer.java index 50863dd7e9f..da35d2f7a4e 100644 --- a/jdk/src/share/classes/java/lang/Integer.java +++ b/jdk/src/share/classes/java/lang/Integer.java @@ -638,6 +638,9 @@ public final class Integer extends Number implements Comparable { * to yield significantly better space and time performance by * caching frequently requested values. * + * This method will always cache values in the range -128 to 127, + * inclusive, and may cache other values outside of this range. + * * @param i an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 diff --git a/jdk/src/share/classes/java/lang/Long.java b/jdk/src/share/classes/java/lang/Long.java index c632d5df2d9..a2fe09c959d 100644 --- a/jdk/src/share/classes/java/lang/Long.java +++ b/jdk/src/share/classes/java/lang/Long.java @@ -560,6 +560,11 @@ public final class Long extends Number implements Comparable { * significantly better space and time performance by caching * frequently requested values. * + * Note that unlike the {@linkplain Integer#valueOf(int) + * corresponding method} in the {@code Integer} class, this method + * is not required to cache values within a particular + * range. + * * @param l a long value. * @return a {@code Long} instance representing {@code l}. * @since 1.5 diff --git a/jdk/src/share/classes/java/lang/Short.java b/jdk/src/share/classes/java/lang/Short.java index 8abbf65d61a..a5d72120dfb 100644 --- a/jdk/src/share/classes/java/lang/Short.java +++ b/jdk/src/share/classes/java/lang/Short.java @@ -219,6 +219,9 @@ public final class Short extends Number implements Comparable { * significantly better space and time performance by caching * frequently requested values. * + * This method will always cache values in the range -128 to 127, + * inclusive, and may cache other values outside of this range. + * * @param s a short value. * @return a {@code Short} instance representing {@code s}. * @since 1.5 From 5ba2fd7d33d98a75b94044fcdc0b099bd9d74ba3 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Fri, 10 Jul 2009 17:27:13 +0800 Subject: [PATCH 39/61] 6852744: PIT b61: PKI test suite fails because self signed certificates are beingrejected Make the builder aware of SKID/AKID, break the internal circular dependences Reviewed-by: mullan --- .../certpath/DistributionPointFetcher.java | 96 ++++- .../provider/certpath/ForwardBuilder.java | 176 +++++++- .../selfIssued/DisableRevocation.java | 260 ++++++++++++ .../selfIssued/KeyUsageMatters.java | 303 ++++++++++++++ .../cert/CertPathBuilder/selfIssued/README | 382 ++++++++++++++++++ .../selfIssued/StatusLoopDependency.java | 309 ++++++++++++++ .../CertPathBuilder/selfIssued/generate.sh | 221 ++++++++++ .../CertPathBuilder/selfIssued/openssl.cnf | 205 ++++++++++ 8 files changed, 1940 insertions(+), 12 deletions(-) create mode 100644 jdk/test/java/security/cert/CertPathBuilder/selfIssued/DisableRevocation.java create mode 100644 jdk/test/java/security/cert/CertPathBuilder/selfIssued/KeyUsageMatters.java create mode 100644 jdk/test/java/security/cert/CertPathBuilder/selfIssued/README create mode 100644 jdk/test/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java create mode 100644 jdk/test/java/security/cert/CertPathBuilder/selfIssued/generate.sh create mode 100644 jdk/test/java/security/cert/CertPathBuilder/selfIssued/openssl.cnf diff --git a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java index 34f26f64a0f..39ee1f1dad6 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import javax.security.auth.x500.X500Principal; import sun.security.action.GetPropertyAction; import sun.security.util.Debug; +import sun.security.util.DerOutputStream; import sun.security.x509.*; /** @@ -333,7 +334,15 @@ class DistributionPointFetcher { if (match == false) { return false; } - indirectCRL = true; + + // we accept the case that a CRL issuer provide status + // information for itself. + if (ForwardBuilder.issues(certImpl, crlImpl, provider)) { + // reset the public key used to verify the CRL's signature + prevKey = certImpl.getPublicKey(); + } else { + indirectCRL = true; + } } else if (crlIssuer.equals(certIssuer) == false) { if (debug != null) { debug.println("crl issuer does not equal cert issuer"); @@ -347,7 +356,14 @@ class DistributionPointFetcher { PKIXExtensions.AuthorityKey_Id.toString()); if (!Arrays.equals(certAKID, crlAKID)) { - indirectCRL = true; + // we accept the case that a CRL issuer provide status + // information for itself. + if (ForwardBuilder.issues(certImpl, crlImpl, provider)) { + // reset the public key used to verify the CRL's signature + prevKey = certImpl.getPublicKey(); + } else { + indirectCRL = true; + } } } @@ -542,10 +558,80 @@ class DistributionPointFetcher { certSel.setSubject(crlIssuer.asX500Principal()); boolean[] crlSign = {false,false,false,false,false,false,true}; certSel.setKeyUsage(crlSign); + + // Currently by default, forward builder does not enable + // subject/authority key identifier identifying for target + // certificate, instead, it only compares the CRL issuer and + // the target certificate subject. If the certificate of the + // delegated CRL issuer is a self-issued certificate, the + // builder is unable to find the proper CRL issuer by issuer + // name only, there is a potential dead loop on finding the + // proper issuer. It is of great help to narrow the target + // scope down to aware of authority key identifiers in the + // selector, for the purposes of breaking the dead loop. + AuthorityKeyIdentifierExtension akidext = + crlImpl.getAuthKeyIdExtension(); + if (akidext != null) { + KeyIdentifier akid = (KeyIdentifier)akidext.get(akidext.KEY_ID); + if (akid != null) { + DerOutputStream derout = new DerOutputStream(); + derout.putOctetString(akid.getIdentifier()); + certSel.setSubjectKeyIdentifier(derout.toByteArray()); + } + + SerialNumber asn = + (SerialNumber)akidext.get(akidext.SERIAL_NUMBER); + if (asn != null) { + certSel.setSerialNumber(asn.getNumber()); + } + // the subject criterion will be set by builder automatically. + } + + // by far, we have validated the previous certificate, we can + // trust it during validating the CRL issuer. + // Except the performance improvement, another benefit is to break + // the dead loop while looking for the issuer back and forth + // between the delegated self-issued certificate and its issuer. + Set trustAnchors = new HashSet(); + if (anchor != null) { + trustAnchors.add(anchor); + } + + if (prevKey != null) { + // if the previous key is of the anchor, don't bother to + // duplicate the trust. + boolean duplicated = false; + PublicKey publicKey = prevKey; + X500Principal principal = certImpl.getIssuerX500Principal(); + + if (anchor != null) { + X509Certificate trustedCert = anchor.getTrustedCert(); + X500Principal trustedPrincipal; + PublicKey trustedPublicKey; + if (trustedCert != null) { + trustedPrincipal = trustedCert.getSubjectX500Principal(); + trustedPublicKey = trustedCert.getPublicKey(); + } else { + trustedPrincipal = anchor.getCA(); + trustedPublicKey = anchor.getCAPublicKey(); + } + + if (principal.equals(trustedPrincipal) && + publicKey.equals(trustedPublicKey)) { + duplicated = true; + } + } + + if (!duplicated) { + TrustAnchor temporary = + new TrustAnchor(principal, publicKey, null); + trustAnchors.add(temporary); + } + } + PKIXBuilderParameters params = null; try { - params = new PKIXBuilderParameters - (Collections.singleton(anchor), certSel); + params = new PKIXBuilderParameters(trustAnchors, certSel); } catch (InvalidAlgorithmParameterException iape) { throw new CRLException(iape); } diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java index d8713cdcac4..393a7663c91 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.util.*; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; +import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; import java.security.cert.PKIXReason; @@ -43,12 +44,22 @@ import java.security.cert.X509CertSelector; import javax.security.auth.x500.X500Principal; import sun.security.util.Debug; +import sun.security.util.DerOutputStream; import sun.security.x509.AccessDescription; import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.PKIXExtensions; import sun.security.x509.PolicyMappingsExtension; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; +import sun.security.x509.X509CRLImpl; +import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.KeyIdentifier; +import sun.security.x509.SubjectKeyIdentifierExtension; +import sun.security.x509.SerialNumber; +import sun.security.x509.GeneralNames; +import sun.security.x509.GeneralName; +import sun.security.x509.GeneralNameInterface; +import java.math.BigInteger; /** * This class represents a forward builder, which is able to retrieve @@ -237,7 +248,7 @@ class ForwardBuilder extends Builder { } else { if (caSelector == null) { - caSelector = new X509CertSelector(); + caSelector = new AdaptableX509CertSelector(); /* * Match on certificate validity date. @@ -269,6 +280,29 @@ class ForwardBuilder extends Builder { * at least as many CA certs that have already been traversed */ caSelector.setBasicConstraints(currentState.traversedCACerts); + + /* + * Facilitate certification path construction with authority + * key identifier and subject key identifier. + */ + AuthorityKeyIdentifierExtension akidext = + currentState.cert.getAuthorityKeyIdentifierExtension(); + if (akidext != null) { + KeyIdentifier akid = (KeyIdentifier)akidext.get(akidext.KEY_ID); + if (akid != null) { + DerOutputStream derout = new DerOutputStream(); + derout.putOctetString(akid.getIdentifier()); + caSelector.setSubjectKeyIdentifier(derout.toByteArray()); + } + + SerialNumber asn = + (SerialNumber)akidext.get(akidext.SERIAL_NUMBER); + if (asn != null) { + caSelector.setSerialNumber(asn.getNumber()); + } + // the subject criterion was set previously. + } + sel = caSelector; } @@ -817,13 +851,25 @@ class ForwardBuilder extends Builder { } else { continue; } - } + } else { + X500Principal principal = anchor.getCA(); + java.security.PublicKey publicKey = anchor.getCAPublicKey(); - X500Principal trustedCAName = anchor.getCA(); + if (principal != null && publicKey != null && + principal.equals(cert.getSubjectX500Principal())) { + if (publicKey.equals(cert.getPublicKey())) { + // the cert itself is a trust anchor + this.trustAnchor = anchor; + return true; + } + // else, it is a self-issued certificate of the anchor + } - /* Check subject/issuer name chaining */ - if (!trustedCAName.equals(cert.getIssuerX500Principal())) { - continue; + // Check subject/issuer name chaining + if (principal == null || + !principal.equals(cert.getIssuerX500Principal())) { + continue; + } } /* Check revocation if it is enabled */ @@ -890,4 +936,120 @@ class ForwardBuilder extends Builder { void removeFinalCertFromPath(LinkedList certPathList) { certPathList.removeFirst(); } + + /** Verifies whether a CRL is issued by a certain certificate + * + * @param cert the certificate + * @param crl the CRL to be verified + * @param provider the name of the signature provider + */ + static boolean issues(X509CertImpl cert, X509CRLImpl crl, String provider) + throws IOException { + + boolean kidmatched = false; + + // check certificate's key usage + boolean[] usages = cert.getKeyUsage(); + if (usages != null && !usages[6]) { + return false; + } + + // check certificate's SKID and CRL's AKID + AuthorityKeyIdentifierExtension akidext = crl.getAuthKeyIdExtension(); + if (akidext != null) { + // the highest priority, matching KID + KeyIdentifier akid = (KeyIdentifier)akidext.get(akidext.KEY_ID); + if (akid != null) { + SubjectKeyIdentifierExtension skidext = + cert.getSubjectKeyIdentifierExtension(); + if (skidext != null) { + KeyIdentifier skid = + (KeyIdentifier)skidext.get(skidext.KEY_ID); + if (!akid.equals(skid)) { + return false; + } + + kidmatched = true; + } + // conservatively, in case of X509 V1 certificate, + // does return false here if no SKID extension. + } + + // the medium priority, matching issuer name/serial number + SerialNumber asn = (SerialNumber)akidext.get(akidext.SERIAL_NUMBER); + GeneralNames anames = (GeneralNames)akidext.get(akidext.AUTH_NAME); + if (asn != null && anames != null) { + X500Name subject = (X500Name)cert.getSubjectDN(); + BigInteger serial = cert.getSerialNumber(); + + if (serial != null && subject != null) { + if (serial.equals(asn.getNumber())) { + return false; + } + + for (GeneralName name : anames.names()) { + GeneralNameInterface gni = name.getName(); + if (subject.equals(gni)) { + return true; + } + } + } + + return false; + } + + if (kidmatched) { + return true; + } + } + + // the last priority, verify the CRL signature with the cert. + X500Principal crlIssuer = crl.getIssuerX500Principal(); + X500Principal certSubject = cert.getSubjectX500Principal(); + if (certSubject != null && certSubject.equals(crlIssuer)) { + try { + crl.verify(cert.getPublicKey(), provider); + return true; + } catch (Exception e) { + // ignore all exceptions. + } + } + + return false; + } + + /** + * An adaptable X509 certificate selector for forward certification path + * building. + */ + private static class AdaptableX509CertSelector extends X509CertSelector { + public AdaptableX509CertSelector() { + super(); + } + + /** + * Decides whether a Certificate should be selected. + * + * For the purpose of compatibility, when a certificate is of + * version 1 and version 2, or the certificate does not include + * a subject key identifier extension, the selection criterion + * of subjectKeyIdentifier will be disabled. + * + * @Override + */ + public boolean match(Certificate cert) { + if (!(cert instanceof X509Certificate)) { + return false; + } + X509Certificate xcert = (X509Certificate)cert; + + if (xcert.getVersion() < 3 || + xcert.getExtensionValue("2.5.29.14") == null) { + // disable the subjectKeyIdentifier criterion + setSubjectKeyIdentifier(null); + } + + return super.match(cert); + } + } } diff --git a/jdk/test/java/security/cert/CertPathBuilder/selfIssued/DisableRevocation.java b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/DisableRevocation.java new file mode 100644 index 00000000000..236ec77a4ab --- /dev/null +++ b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/DisableRevocation.java @@ -0,0 +1,260 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6852744 + * @summary PIT b61: PKI test suite fails because self signed certificates + * are being rejected + * @run main/othervm DisableRevocation subca + * @run main/othervm DisableRevocation subci + * @run main/othervm DisableRevocation alice + * @author Xuelei Fan + */ + +import java.io.*; +import java.net.SocketException; +import java.util.*; +import java.security.Security; +import java.security.cert.*; +import java.security.cert.CertPathValidatorException.BasicReason; +import sun.security.util.DerInputStream; + +/** + * A test case helps to ensure that a certification path building process is + * able to identify a self-issued certificate from its issuer when disable + * revocation checking. + */ +public final class DisableRevocation { + + // the trust anchor + static String selfSignedCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMThaFw0zMDA2MDgxMzMyMTha\n" + + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" + + "AQUAA4GNADCBiQKBgQDInJhXi0655bPXAVkz1n5I6fAcZejzPnOPuwq3hU3OxFw8\n" + + "81Uf6o9oKI1h4w4XAD8u1cUNOgiX+wPwojronlp68bIfO6FVhNf287pLtLhNJo+7\n" + + "m6Qxw3ymFvEKy+PVj20CHSggdKHxUa4MBZBmHMFNBuxfYmjwzn+yTMmCCXOvSwID\n" + + "AQABo4GJMIGGMB0GA1UdDgQWBBSQ52Dpau+gtL+Kc31dusYnKj16ZTBHBgNVHSME\n" + + "QDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" + + "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYw\n" + + "DQYJKoZIhvcNAQEEBQADgYEAjBt6ea65HCqbGsS2rs/HhlGusYXtThRVC5vwXSey\n" + + "ZFYwSgukuq1KDzckqZFu1meNImEwdZjwxdN0e2p/nVREPC42rZliSj6V1ThayKXj\n" + + "DWEZW1U5aR8T+3NYfDrdKcJGx4Hzfz0qKz1j4ssV1M9ptJxYYv4y2Da+592IN1S9\n" + + "v/E=\n" + + "-----END CERTIFICATE-----"; + + // the sub-ca + static String subCaCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICUDCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjRaFw0yOTAzMTUxMzMyMjRa\n" + + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" + + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPFv24SK78VI0gWlyIrq/X\n" + + "srl1431K5hJJxMYZtaQunyPmrYg3oI9KvKFykxnR0N4XDPaIi75p9dXGppVu80BA\n" + + "+csvIPBwlBQoNmKDQWTziDOqfK4tE+IMuL/Y7pxnH6CDMY7VGpvatty2zcmH+m/v\n" + + "E/n+HPyeELJQT2rT/3T+7wIDAQABo4GJMIGGMB0GA1UdDgQWBBRidC8Dt3dBzYES\n" + + "KpR2tR560sZ0+zBHBgNVHSMEQDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEw\n" + + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" + + "AwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQADgYEAMeMKqrMr5d3eTQsv\n" + + "MYOD15Dl3THQGLAa4ad5Eyq5/1eUeEOpztzCgDfi0iPD8YCubIEVasBTSqTiGXqb\n" + + "RpGuPHOwwfWvHrTeHSludiFBAUiKj7aEV+oQa0FBn4U4TT8HA62HQ93FhzTDI3jP\n" + + "iil34GktVl6gfMKGzUEW/Dh8OM4=\n" + + "-----END CERTIFICATE-----"; + + // a delegated CRL issuer, it's a self-issued certificate of trust anchor + static String topCrlIssuerCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICPjCCAaegAwIBAgIBAjANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjNaFw0yOTAzMTUxMzMyMjNa\n" + + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" + + "AQUAA4GNADCBiQKBgQC99u93trf+WmpfiqunJy/P31ej1l4rESxft2JSGNjKuLFN\n" + + "/BO3SAugGJSkCARAwXjB0c8eeXhXWhVVWdNpbKepRJTxrjDfnFIavLgtUvmFwn/3\n" + + "hPXe+RQeA8+AJ99Y+o+10kY8JAZLa2j93C2FdmwOjUbo8aIz85yhbiV1tEDjLwID\n" + + "AQABo4GJMIGGMB0GA1UdDgQWBBSyFyA3XWLbdL6W6hksmBn7RKsQmDBHBgNVHSME\n" + + "QDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" + + "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYw\n" + + "DQYJKoZIhvcNAQEEBQADgYEAHTm8aRTeakgCfEBCgSWK9wvMW1c18ANGMm8OFDBk\n" + + "xabVy9BT0MVFHlaneh89oIxTZN0FMTpg21GZMAvIzhEt7DGdO7HLsW7JniN7/OZ0\n" + + "rACmpK5frmZrLS03zUm8c+rTbazNfYLoZVG3/mDZbKIi+4y8IGnFcgLVsHsYoBNP\n" + + "G0c=\n" + + "-----END CERTIFICATE-----"; + + // a delegated CRL issuer, it's a self-issued certificate of sub-ca + static String subCrlIssuerCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICUDCCAbmgAwIBAgIBBDANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjdaFw0yOTAzMTUxMzMyMjda\n" + + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" + + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+8AcLJtGAVUWvv3ifcyQw\n" + + "OGqwzcPrBw/XCs6vTMlcdtFzcH1M+Z3/QHN9+5VT1gqeTIZ+b8g9005Og3XKy/HX\n" + + "obXZeLv20VZsr+jm52ySghEYOVCTJ9OyFOAp5adp6nf0cA66Feh3LsmVhpTEcDOG\n" + + "GnyntQm0DBYxRoOT/GBlvQIDAQABo4GJMIGGMB0GA1UdDgQWBBSRWhMuZLQoHSDN\n" + + "xhxr+vdDmfAY8jBHBgNVHSMEQDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEw\n" + + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" + + "AwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQADgYEAMIDZLdOLFiPyS1bh\n" + + "Ch4eUYHT+K1WG93skbga3kVYg3GSe+gctwkKwKK13bwfi8zc7wwz6MtmQwEYhppc\n" + + "pKKKEwi5QirBCP54rihLCvRQaj6ZqUJ6VP+zPAqHYMDbzlBbHtVF/1lQUP30I6SV\n" + + "Fu987DvLmZ2GuQA9FKJsnlD9pbU=\n" + + "-----END CERTIFICATE-----"; + + // the target EE certificate + static String targetCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQQFADAxMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA2MjgxMzMy\n" + + "MzBaFw0yOTAzMTUxMzMyMzBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" + + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" + + "9w0BAQEFAAOBjQAwgYkCgYEA7wnsvR4XEOfVznf40l8ClLod+7L0y2/+smVV+GM/\n" + + "T1/QF/stajAJxXNy08gK00WKZ6ruTHhR9vh/Z6+EQM2RZDCpU0A7LPa3kLE/XTmS\n" + + "1MLDu8ntkdlpURpvhdDWem+rl2HU5oZgzV8Jkcov9vXuSjqEDfr45FlPuV40T8+7\n" + + "cxsCAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSBwsAhi6Z1kriOs3ty\n" + + "uSIujv9a3DAfBgNVHSMEGDAWgBRidC8Dt3dBzYESKpR2tR560sZ0+zANBgkqhkiG\n" + + "9w0BAQQFAAOBgQDEiBqd5AMy2SQopFaS3dYkzj8MHlwtbCSoNVYkOfDnewcatrbk\n" + + "yFcp6FX++PMdOQFHWvvnDdkCUAzZQp8kCkF9tGLVLBtOK7XxQ1us1LZym7kOPzsd\n" + + "G93Dcf0U1JRO77juc61Br5paAy8Bok18Y/MeG7uKgB2MAEJYKhGKbCrfMw==\n" + + "-----END CERTIFICATE-----"; + + private static Set generateTrustAnchors() + throws CertificateException { + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + ByteArrayInputStream is = + new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); + + // generate a trust anchor + TrustAnchor anchor = + new TrustAnchor((X509Certificate)selfSignedCert, null); + + return Collections.singleton(anchor); + } + + private static CertStore generateCertificateStore() throws Exception { + Collection entries = new HashSet(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + ByteArrayInputStream is; + + is = new ByteArrayInputStream(targetCertStr.getBytes()); + Certificate cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(selfSignedCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(topCrlIssuerCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + return CertStore.getInstance("Collection", + new CollectionCertStoreParameters(entries)); + } + + private static X509CertSelector generateSelector(String name) + throws Exception { + X509CertSelector selector = new X509CertSelector(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream is = null; + if (name.equals("subca")) { + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + } else if (name.equals("subci")) { + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + } else { + is = new ByteArrayInputStream(targetCertStr.getBytes()); + } + + X509Certificate target = (X509Certificate)cf.generateCertificate(is); + byte[] extVal = target.getExtensionValue("2.5.29.14"); + if (extVal != null) { + DerInputStream in = new DerInputStream(extVal); + byte[] subjectKID = in.getOctetString(); + selector.setSubjectKeyIdentifier(subjectKID); + } else { + // unlikely to happen. + throw new Exception("unexpected certificate: no SKID extension"); + } + + return selector; + } + + private static boolean match(String name, Certificate cert) + throws Exception { + X509CertSelector selector = new X509CertSelector(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream is = null; + if (name.equals("subca")) { + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + } else if (name.equals("subci")) { + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + } else { + is = new ByteArrayInputStream(targetCertStr.getBytes()); + } + X509Certificate target = (X509Certificate)cf.generateCertificate(is); + + return target.equals(cert); + } + + + public static void main(String[] args) throws Exception { + CertPathBuilder builder = CertPathBuilder.getInstance("PKIX"); + + X509CertSelector selector = generateSelector(args[0]); + + Set anchors = generateTrustAnchors(); + CertStore certs = generateCertificateStore(); + + + PKIXBuilderParameters params = + new PKIXBuilderParameters(anchors, selector); + params.addCertStore(certs); + params.setRevocationEnabled(false); + params.setDate(new Date(109, 7, 1)); // 2009-07-01 + Security.setProperty("ocsp.enable", "false"); + System.setProperty("com.sun.security.enableCRLDP", "false"); + + PKIXCertPathBuilderResult result = + (PKIXCertPathBuilderResult)builder.build(params); + + if (!match(args[0], result.getCertPath().getCertificates().get(0))) { + throw new Exception("unexpected certificate"); + } + } +} diff --git a/jdk/test/java/security/cert/CertPathBuilder/selfIssued/KeyUsageMatters.java b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/KeyUsageMatters.java new file mode 100644 index 00000000000..af977c3d8d2 --- /dev/null +++ b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/KeyUsageMatters.java @@ -0,0 +1,303 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6852744 + * @summary PIT b61: PKI test suite fails because self signed certificates + * are being rejected + * @run main/othervm KeyUsageMatters subca + * @run main/othervm KeyUsageMatters subci + * @run main/othervm KeyUsageMatters alice + * @author Xuelei Fan + */ + +import java.io.*; +import java.net.SocketException; +import java.util.*; +import java.security.Security; +import java.security.cert.*; +import java.security.cert.CertPathValidatorException.BasicReason; +import sun.security.util.DerInputStream; + +/** + * KeyUsage extension plays a important rule during looking for the issuer + * of a certificate or CRL. A certificate issuer should have the keyCertSign + * bit set, and a CRL issuer should have the cRLSign bit set. + * + * Sometime, a delegated CRL issuer would also have the keyCertSign bit set, + * as would be troublesome to find the proper CRL issuer during certificate + * path build if the delegated CRL issuer is a self-issued certificate, for + * it is hard to identify it from its issuer by the "issuer" field only. + * + * The fix of 6852744 should addresses above issue, and allow a delegated CRL + * issuer to have keyCertSign bit set. + * + * In the test case, the delegated CRL issuers have cRLSign bit set only, and + * the CAs have the keyCertSign bit set only, it is expected to work before + * and after the bug fix of 6852744. + */ +public final class KeyUsageMatters { + + // the trust anchor + static String selfSignedCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA0MjcwMjI0MzJaFw0zMDA0MDcwMjI0MzJa\n" + + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" + + "AQUAA4GNADCBiQKBgQC4OTag24sTxL2tXTNuvpmUEtdxrYAZoFsslFQ60T+WD9wQ\n" + + "Jeiw87FSPsR2vxRuv0j8DNm2a4h7LNNIFcLurfNldbz5pvgZ7VqdbbUMPE9qP85n\n" + + "jgDl4woyRTSUeRI4A7O0CO6NpES21dtbdhroWQrEkHxpnrDPxsxrz5gf2m3gqwID\n" + + "AQABo4GJMIGGMB0GA1UdDgQWBBSCJd0hpl5PdAD9IZS+Hzng4lXLGzBHBgNVHSME\n" + + "QDA+gBSCJd0hpl5PdAD9IZS+Hzng4lXLG6EjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" + + "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw\n" + + "DQYJKoZIhvcNAQEEBQADgYEAluy6HIjWcq009lTLmhp+Np6dxU78pInBK8RZkza0\n" + + "484qGaxFGD3UGyZkI5uWmsH2XuMbuox5khfIq6781gmkPBHXBIEtJN8eLusOHEye\n" + + "iE8h7WI+N3qa6Pj56WionMrioqC/3X+b06o147bbhx8U0vkYv/HyPaITOFfMXTdz\n" + + "Vjw=\n" + + "-----END CERTIFICATE-----"; + + // the sub-ca + static String subCaCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICUDCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA0MjcwMjI0MzRaFw0yOTAxMTIwMjI0MzRa\n" + + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" + + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiAJnAQW2ad3ZMKUhSJVZj\n" + + "8pBqxTcHSTwAVguQkDglsN/OIwUpvR5Jgp3lpRWUEt6idEp0FZzORpvtjt3pr5MG\n" + + "Eg2CDptekC5BSPS+fIAIKlncB3HwOiFFhH6b3wTydDCdEd2fvsi4QMOSVrIYMeA8\n" + + "P/mCz6kRhfUQPE0CMmOUewIDAQABo4GJMIGGMB0GA1UdDgQWBBT0/nNP8WpyxmYr\n" + + "IBp4tN8y08jw2jBHBgNVHSMEQDA+gBSCJd0hpl5PdAD9IZS+Hzng4lXLG6EjpCEw\n" + + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" + + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEEBQADgYEAS9PzI6B39R/U9fRj\n" + + "UExzN1FXNP5awnAPtiv34kSCL6n6MryqkfG+8aaAOdZsSjmTylNFaF7cW/Xp1VBF\n" + + "hq0bg/SbEAbK7+UwL8GSC3crhULHLbh+1iFdVTEwxCw5YmB8ji3BaZ/WKW/PkjCZ\n" + + "7cXP6VDeZMG6oRQ4hbOcixoFPXo=\n" + + "-----END CERTIFICATE-----"; + + // a delegated CRL issuer, it's a self-issued certificate of trust anchor + static String topCrlIssuerCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICKzCCAZSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA0MjcwMjI0MzNaFw0yOTAxMTIwMjI0MzNa\n" + + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" + + "AQUAA4GNADCBiQKBgQDMJeBMBybHykI/YpwUJ4O9euqDSLb1kpWpceBS8TVqvgBC\n" + + "SgUJWtFZL0i6bdvF6mMdlbuBkGzhXqHiVAi96/zRLbUC9F8SMEJ6MuD+YhQ0ZFTQ\n" + + "atKy8zf8O9XzztelLJ26Gqb7QPV133WY3haAqHtCXOhEKkCN16NOYNC37DTaJwID\n" + + "AQABo3cwdTAdBgNVHQ4EFgQULXSWzXzUOIpOJpzbSCpW42IJUugwRwYDVR0jBEAw\n" + + "PoAUgiXdIaZeT3QA/SGUvh854OJVyxuhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" + + "VQQKEwdFeGFtcGxlggEAMAsGA1UdDwQEAwIBAjANBgkqhkiG9w0BAQQFAAOBgQAY\n" + + "eMnf5AHSNlyUlzXk8o2S0h4gCuvKX6C3kFfKuZcWvFAbx4yQOWLS2s15/nzR4+AP\n" + + "FGX3lgJjROyAh7fGedTQK+NFWwkM2ag1g3hXktnlnT1qHohi0w31nVBJxXEDO/Ck\n" + + "uJTpJGt8XxxbFaw5v7cHy7XuTAeU/sekvjEiNHW00Q==\n" + + "-----END CERTIFICATE-----"; + + // a delegated CRL issuer, it's a self-issued certificate of sub-ca + static String subCrlIssuerCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICPTCCAaagAwIBAgIBBDANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA0MjcwMjI0MzRaFw0yOTAxMTIwMjI0MzRa\n" + + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" + + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDWUtDQx2MB/7arDiquMJyd\n" + + "LWwSg6p8sg5z6wKrC1v47MT4DBhFX+0RUgTMUdQgYpgxGpczn+6y4zfV76064S0N\n" + + "4L/IQ+SunTW1w4yRGjB+xkyyJmWAqijG1nr+Dgkv5nxPI+9Er5lHcoVWVMEcvvRm\n" + + "6jIBQdldVlSgv+VgUnFm5wIDAQABo3cwdTAdBgNVHQ4EFgQUkV3Qqtk7gIot9n60\n" + + "jX6dloxrfMEwRwYDVR0jBEAwPoAUgiXdIaZeT3QA/SGUvh854OJVyxuhI6QhMB8x\n" + + "CzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMAsGA1UdDwQEAwIBAjAN\n" + + "BgkqhkiG9w0BAQQFAAOBgQADu4GM8EdmIKhC7FRvk5jF90zfvZ38wbXBzCjKI4jX\n" + + "QJrhne1bfyeNNm5c1w+VKidT+XzBzBGH7ZqYzoZmzRIfcbLKX2brEBKiukeeAyL3\n" + + "bctQtbp19tX+uu2dQberD188AAysKTkHcJUV+rRsTwVJ9vcYKxoRxKk8DhH7ZS3M\n" + + "rg==\n" + + "-----END CERTIFICATE-----"; + + // the target EE certificate + static String targetCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQQFADAxMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA0MjcwMjI0\n" + + "MzZaFw0yOTAxMTIwMjI0MzZaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" + + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" + + "9w0BAQEFAAOBjQAwgYkCgYEAvYSaU3oiE4Pxp/aUIXwMqOwSiWkZ+O3aTu13hRtK\n" + + "ZyR+Wtj63IuvaigAC4uC+zBypF93ThjwCzVR2qKDQaQzV8CLleO96gStt7Y+i3G2\n" + + "V3IUGgrVCqeK7N6nNYu0wW84sibcPqG/TIy0UoaQMqgB21xtRF+1DUVlFh4Z89X/\n" + + "pskCAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSynMEdcal/e9TmvlNE\n" + + "4suXGA4+hjAfBgNVHSMEGDAWgBT0/nNP8WpyxmYrIBp4tN8y08jw2jANBgkqhkiG\n" + + "9w0BAQQFAAOBgQB/jru7E/+piSmUwByw5qbZsoQZVcgR97pd2TErNJpJMAX2oIHR\n" + + "wJH6w4NuYs27+fEAX7wK4whc6EUH/w1SI6o28F2rG6HqYQPPZ2E2WqwbBQL9nYE3\n" + + "Vfzu/G9axTUQXFbf90h80UErA+mZVxqc2xtymLuH0YEaMZImtRZ2MXHfXg==\n" + + "-----END CERTIFICATE-----"; + + // CRL issued by the delegated CRL issuer, topCrlIssuerCertStr + static String topCrlStr = + "-----BEGIN X509 CRL-----\n" + + "MIIBGzCBhQIBATANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQMA4GA1UE\n" + + "ChMHRXhhbXBsZRcNMDkwNDI3MDIzODA0WhcNMjgwNjI2MDIzODA0WjAiMCACAQUX\n" + + "DTA5MDQyNzAyMzgwMFowDDAKBgNVHRUEAwoBBKAOMAwwCgYDVR0UBAMCAQIwDQYJ\n" + + "KoZIhvcNAQEEBQADgYEAoarfzXEtw3ZDi4f9U8eSvRIipHSyxOrJC7HR/hM5VhmY\n" + + "CErChny6x9lBVg9s57tfD/P9PSzBLusCcHwHMAbMOEcTltVVKUWZnnbumpywlYyg\n" + + "oKLrE9+yCOkYUOpiRlz43/3vkEL5hjIKMcDSZnPKBZi1h16Yj2hPe9GMibNip54=\n" + + "-----END X509 CRL-----"; + + // CRL issued by the delegated CRL issuer, subCrlIssuerCertStr + static String subCrlStr = + "-----BEGIN X509 CRL-----\n" + + "MIIBLTCBlwIBATANBgkqhkiG9w0BAQQFADAxMQswCQYDVQQGEwJVUzEQMA4GA1UE\n" + + "ChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMRcNMDkwNDI3MDIzODA0WhcNMjgw\n" + + "NjI2MDIzODA0WjAiMCACAQQXDTA5MDQyNzAyMzgwMVowDDAKBgNVHRUEAwoBBKAO\n" + + "MAwwCgYDVR0UBAMCAQIwDQYJKoZIhvcNAQEEBQADgYEAeS+POqYEIHIIJcsLxuUr\n" + + "aJFzQ/ujH0QmnyMNEL3Uavyq4VQuAahF+w6aTPb5UBzms0uX8NAvD2vNoUJvmJOX\n" + + "nGKuq4Q1DFj82E7/9d25nXdWGOmFvFCRVO+St2Xe5n8CJuZNBiz388FDSIOiFSCa\n" + + "ARGr6Qu68MYGtLMC6ZqP3u0=\n" + + "-----END X509 CRL-----"; + + private static Set generateTrustAnchors() + throws CertificateException { + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + ByteArrayInputStream is = + new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); + + // generate a trust anchor + TrustAnchor anchor = + new TrustAnchor((X509Certificate)selfSignedCert, null); + + return Collections.singleton(anchor); + } + + private static CertStore generateCertificateStore() throws Exception { + Collection entries = new HashSet(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + ByteArrayInputStream is; + + is = new ByteArrayInputStream(targetCertStr.getBytes()); + Certificate cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(selfSignedCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(topCrlIssuerCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + // generate CRL from CRL string + is = new ByteArrayInputStream(topCrlStr.getBytes()); + Collection mixes = cf.generateCRLs(is); + entries.addAll(mixes); + + is = new ByteArrayInputStream(subCrlStr.getBytes()); + mixes = cf.generateCRLs(is); + entries.addAll(mixes); + + return CertStore.getInstance("Collection", + new CollectionCertStoreParameters(entries)); + } + + private static X509CertSelector generateSelector(String name) + throws Exception { + X509CertSelector selector = new X509CertSelector(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream is = null; + if (name.equals("subca")) { + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + } else if (name.equals("subci")) { + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + } else { + is = new ByteArrayInputStream(targetCertStr.getBytes()); + } + + X509Certificate target = (X509Certificate)cf.generateCertificate(is); + byte[] extVal = target.getExtensionValue("2.5.29.14"); + if (extVal != null) { + DerInputStream in = new DerInputStream(extVal); + byte[] subjectKID = in.getOctetString(); + selector.setSubjectKeyIdentifier(subjectKID); + } else { + // unlikely to happen. + throw new Exception("unexpected certificate: no SKID extension"); + } + + return selector; + } + + private static boolean match(String name, Certificate cert) + throws Exception { + X509CertSelector selector = new X509CertSelector(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream is = null; + if (name.equals("subca")) { + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + } else if (name.equals("subci")) { + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + } else { + is = new ByteArrayInputStream(targetCertStr.getBytes()); + } + X509Certificate target = (X509Certificate)cf.generateCertificate(is); + + return target.equals(cert); + } + + + public static void main(String[] args) throws Exception { + CertPathBuilder builder = CertPathBuilder.getInstance("PKIX"); + + X509CertSelector selector = generateSelector(args[0]); + + Set anchors = generateTrustAnchors(); + CertStore certs = generateCertificateStore(); + + + PKIXBuilderParameters params = + new PKIXBuilderParameters(anchors, selector); + params.addCertStore(certs); + params.setRevocationEnabled(true); + params.setDate(new Date(109, 5, 1)); // 2009-05-01 + Security.setProperty("ocsp.enable", "false"); + System.setProperty("com.sun.security.enableCRLDP", "true"); + + PKIXCertPathBuilderResult result = + (PKIXCertPathBuilderResult)builder.build(params); + + if (!match(args[0], result.getCertPath().getCertificates().get(0))) { + throw new Exception("unexpected certificate"); + } + } +} diff --git a/jdk/test/java/security/cert/CertPathBuilder/selfIssued/README b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/README new file mode 100644 index 00000000000..b0c1d6e0255 --- /dev/null +++ b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/README @@ -0,0 +1,382 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + Certificates and CRLs + +The certificates and CRLs used by KeyUsageMatters.java are copied from +test/java/security/cert/CertPathValidator/indirectCRL. + +Here lists the local generated certificates and CRLs used in the test cases. + +The generate.sh depends on openssl, and it should be run under ksh. The +script will create many directories and files, please run it in a +directory outside of JDK workspace. + +1. root certifiate and key +-----BEGIN CERTIFICATE----- +MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMThaFw0zMDA2MDgxMzMyMTha +MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDInJhXi0655bPXAVkz1n5I6fAcZejzPnOPuwq3hU3OxFw8 +81Uf6o9oKI1h4w4XAD8u1cUNOgiX+wPwojronlp68bIfO6FVhNf287pLtLhNJo+7 +m6Qxw3ymFvEKy+PVj20CHSggdKHxUa4MBZBmHMFNBuxfYmjwzn+yTMmCCXOvSwID +AQABo4GJMIGGMB0GA1UdDgQWBBSQ52Dpau+gtL+Kc31dusYnKj16ZTBHBgNVHSME +QDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEwHzELMAkGA1UEBhMCVVMxEDAO +BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYw +DQYJKoZIhvcNAQEEBQADgYEAjBt6ea65HCqbGsS2rs/HhlGusYXtThRVC5vwXSey +ZFYwSgukuq1KDzckqZFu1meNImEwdZjwxdN0e2p/nVREPC42rZliSj6V1ThayKXj +DWEZW1U5aR8T+3NYfDrdKcJGx4Hzfz0qKz1j4ssV1M9ptJxYYv4y2Da+592IN1S9 +v/E= +-----END CERTIFICATE----- + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,46F13CECA9B38323 + +AVNWPH7jiPyJVq9KfL3IlGVCwD41KVapg12yJR2t/WWlLaKr19/0oWNvimcrd040 +txFKvcFO9TFLxmaco33+actCoL0K/XbrCBICThZLybzcFTuYFMum8eqL61avQgBe +Kt4CCjcupWLzKWkKTMV/bP6nPnPUSB9U8QeGwutjJYnLDi0TuYx8YSqZo/36vM98 +r3OvtcSA5XEN4guxxHusZJnhbclVb/Z1WtLVb4v2d5yBtPM2p3R0hK17L4Dnusjl +n56z6Z0AIYmfAggM/Fpge2uT3D/5n//l1lZRNoSvsX5UZipKswZKLpvx7IJ+AqgA +UO9lcmNLGnIXME3IS3smd83wPi7nxH3NCYWHbGAKLm6mkFMs5LOhofUMOBS3Rxmm +2RjCGtuzDxBPKveo9/Y80B//6sEce2gdi7fCKgWwtR4VFuJd0hWODD6CarK3edHH +rUG62Kt2aqiI/y/NLEbfHCHbyM37c9/OzS5Zy695dDl22r5EirVFsVgejQR1JGtP +ANdc6kkkJW+s6GiqimShssMTp1x0L8twT/+wEa38LafiaPKk4OweleBuyz7k2FxA +Rr2u9IOvGU3eKAeH8HSFWvaNE9S2lYFPiWWZ6O/LzVvnb847+gungQ7SPRzOkt4k +L4PtHIoKmLWFr5tzML1Q8wiaKcTWMb5LZbRbo+2XYGoIpilxkBBuhX7cMJFwOHEf +YJJRixBI97doPsnIQ3GkA8xY+INzQ4LWNQbnEtS7L7t26NA9tDlg4ILU/UfMoQIp +Ol4EZY1U7gD8BeMwo2vX3x/WA+a7R2N95klBFNqn9jSkm6a5yoeCZw== +-----END RSA PRIVATE KEY----- + + +2. root crl issuer and key +-----BEGIN CERTIFICATE----- +MIICPjCCAaegAwIBAgIBAjANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjNaFw0yOTAzMTUxMzMyMjNa +MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQC99u93trf+WmpfiqunJy/P31ej1l4rESxft2JSGNjKuLFN +/BO3SAugGJSkCARAwXjB0c8eeXhXWhVVWdNpbKepRJTxrjDfnFIavLgtUvmFwn/3 +hPXe+RQeA8+AJ99Y+o+10kY8JAZLa2j93C2FdmwOjUbo8aIz85yhbiV1tEDjLwID +AQABo4GJMIGGMB0GA1UdDgQWBBSyFyA3XWLbdL6W6hksmBn7RKsQmDBHBgNVHSME +QDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEwHzELMAkGA1UEBhMCVVMxEDAO +BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYw +DQYJKoZIhvcNAQEEBQADgYEAHTm8aRTeakgCfEBCgSWK9wvMW1c18ANGMm8OFDBk +xabVy9BT0MVFHlaneh89oIxTZN0FMTpg21GZMAvIzhEt7DGdO7HLsW7JniN7/OZ0 +rACmpK5frmZrLS03zUm8c+rTbazNfYLoZVG3/mDZbKIi+4y8IGnFcgLVsHsYoBNP +G0c= +-----END CERTIFICATE----- + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,3881A5676C1AD5E5 + +KgaAtGlIQXVnsoifcd1oTi4hS1J+InHISFcZepI1h1hrU9KVAJAlwD1GIeM2qAkG +P1ABsA0TE0yRJpd3qHih2IPtD42osfc3HmNTw17nh4Trd3ESilrs4w/rrH8e6bR5 +WlqG0OKsw8x57t44m9yX94+pP3tdPaJwnFk5M7pDCO44IZskmy10S0NHBn7wMwM/ +mqlZ15mK6YZTwOuLzpdSDJqYPLiv77KpfeiqSN++ISXoNhIcNYHRVyErAS/DcBlx +mbrmBaGexhuagQYqVikEDIvg8kBDWD92EjOFbz94Z6eTvliauJ/+E1/Ffefe2cN5 +LaVwuUsiyW9GjarWwBJDFrXesTikklshC9V35j/ACHVdh5CuO8FGfVijIwlbZ14N +xKWJdSlZlJgEjkwUlWfi1KmrFrob+yK20fGMWr3oY1rTKWZdYkrqnnKEYcMQV/TH +XNY77D5idJ3FLtvJyziqIFuohdatQsu6xFP5UEOeUi6OhptJDjjS+zDhiBlL4cqA +klThzvuycxjZT+5xno0f8GEnZkQNcC6xxPoP6vstNMKLz1rI1CVUSXZBHc5nfMaF +m75rrLbvf6F2NLUspaNXnW8TUMHxcu8nNCnM4/u6hkqebQo/N8X1/v1HImsewwWO +P5uJwqmqfuRz0vZyMKAk3FzQIfrjJouxDfkNV2YHM9VP/grPlDgzmgiN0+6bCbn+ +RW2K8kvkSFZehQ1Ygdst9KYH3NEcEYVYY9pH1N1xRNAylcIDJNwrFwf9vfwjt9/q +AVsyDxUBT/KVCcqr15LNNq9HmmcP6IZZMRjdyf2BR+/cobxxDRZq1Q== +-----END RSA PRIVATE KEY----- + + +3. root CRL issued by root crl issuer. +-----BEGIN X509 CRL----- +MIIBGzCBhQIBATANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQMA4GA1UE +ChMHRXhhbXBsZRcNMDkwNjI4MTMzMjM4WhcNMjgwODI3MTMzMjM4WjAiMCACAQUX +DTA5MDYyODEzMzIzN1owDDAKBgNVHRUEAwoBBKAOMAwwCgYDVR0UBAMCAQEwDQYJ +KoZIhvcNAQEEBQADgYEAVUIeu2x7ZwsliafoCBOg+u8Q4S/VFfTe/SQnRyTM3/V1 +v+Vn5Acc7eo8Rh4AHcnFFbLNk38n6lllov/CaVR0IPZ6hnrNHVa7VYkNlRAwV2aN +GUUhkMMOLVLnN25UOrN9J637SHmRE6pB+TRMaEQ73V7UNlWxuSMK4KofWen0A34= +-----END X509 CRL----- + + +4. subca certificate and key +-----BEGIN CERTIFICATE----- +MIICUDCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjRaFw0yOTAzMTUxMzMyMjRa +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz +cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPFv24SK78VI0gWlyIrq/X +srl1431K5hJJxMYZtaQunyPmrYg3oI9KvKFykxnR0N4XDPaIi75p9dXGppVu80BA ++csvIPBwlBQoNmKDQWTziDOqfK4tE+IMuL/Y7pxnH6CDMY7VGpvatty2zcmH+m/v +E/n+HPyeELJQT2rT/3T+7wIDAQABo4GJMIGGMB0GA1UdDgQWBBRidC8Dt3dBzYES +KpR2tR560sZ0+zBHBgNVHSMEQDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEw +HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw +AwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQADgYEAMeMKqrMr5d3eTQsv +MYOD15Dl3THQGLAa4ad5Eyq5/1eUeEOpztzCgDfi0iPD8YCubIEVasBTSqTiGXqb +RpGuPHOwwfWvHrTeHSludiFBAUiKj7aEV+oQa0FBn4U4TT8HA62HQ93FhzTDI3jP +iil34GktVl6gfMKGzUEW/Dh8OM4= +-----END CERTIFICATE----- + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,35408AD3018F0049 + +4t6WfpFNqpOr47Wc/OAt8+KZK0+WX7d3nlJn47W+QN7AkPfBlLBpcQJkImhP4/eh +aJyk8fPOdUhT/4rgc5ORuKk4d9boD36KK5Iz/+/oNBxzuld6TybVb+Hvw41cIZTW +CtkvADQpR8XWbPre+3ZH2eAKoTeWX0xR7pYg1JsFk9vxee6U82iqsAYRdUOdot8D +9zdDbbeaLWs78UbZkxFtuXREuyNVX880Q17t8qszJL2KmmtMQpUvxTlW04Ope1Ug +uIuOxeannzpKRD+37fj+oacM3GRqVFOP47/NVaziOexDBn4b5nlW6OMro6t0qiHt +1GLJcw1oLXoFe8ycexfzYWUiHymSz5Vh3wIflsQY+Ik6dopL+fpk2cVD0bncKJlf +Ie9PvL04RwannRjgtPl9X05tzcgeyznp2Ix1/rsriZQQpdPTLGA6w6kUhQeK6TwT +eX7pXn3iLTGK+VoHRfbxBQR2Fvq1nRJbvsmJFhPOcJU5CYSaDPGGdA6NorbdVgbc +14DlkhzojhEpZ7DaUeFNUXUMlQOR5UUTZB+wL3zQoY/FzHci3JD1Gj4NlbC9mMEg +ncWZcpZWOnP2kHSz2o/UOxQM80gerukI7NOr020iJ+ZZRb/gyAAzLPnD+mCZ7/e2 +JJ3x6yHOtVA6WzZiQH1d9/bm79rtcWaRH83X/idG1lHuKXQJFAaw5f7Z2n2/yuF1 +9pZf7el1M7UoBf74oc68klAl46f4inroy8anAtc/qjSTXUYQrNvKZsWU9AZVS7oH +iEuYMVW4KiZh3SHsIg5TZdMbdVYtZpcTsl/Kh6XuY0o0Xsi+rTK5AA== +-----END RSA PRIVATE KEY----- + + +5. crl issuer of subca, the certificate and key +-----BEGIN CERTIFICATE----- +MIICUDCCAbmgAwIBAgIBBDANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjdaFw0yOTAzMTUxMzMyMjda +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz +cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+8AcLJtGAVUWvv3ifcyQw +OGqwzcPrBw/XCs6vTMlcdtFzcH1M+Z3/QHN9+5VT1gqeTIZ+b8g9005Og3XKy/HX +obXZeLv20VZsr+jm52ySghEYOVCTJ9OyFOAp5adp6nf0cA66Feh3LsmVhpTEcDOG +GnyntQm0DBYxRoOT/GBlvQIDAQABo4GJMIGGMB0GA1UdDgQWBBSRWhMuZLQoHSDN +xhxr+vdDmfAY8jBHBgNVHSMEQDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEw +HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw +AwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQADgYEAMIDZLdOLFiPyS1bh +Ch4eUYHT+K1WG93skbga3kVYg3GSe+gctwkKwKK13bwfi8zc7wwz6MtmQwEYhppc +pKKKEwi5QirBCP54rihLCvRQaj6ZqUJ6VP+zPAqHYMDbzlBbHtVF/1lQUP30I6SV +Fu987DvLmZ2GuQA9FKJsnlD9pbU= +-----END CERTIFICATE----- + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,4CD10EAA24AF8C25 + +6pTRc9jsn6CJ2EMYhuGX3aWrDThhacnqdtsKIqUzX8Ga7Jz9kq6HseTRlqPkzBfb +rCl+eVIkgugrPbf93375mP/ozY8LkEgD9TRAL1uXqha2N6TRLC2ozQJQSoIc441e +UZ9XkB6tPGRfPNvi1xE0WTP7bjOUkvkPU9wM9QFuBW6B7mRf3tG2nqkFiTpY6nz8 +5X5+h9jafcCvMwYhfJm0JFTGWmX4WJWubs8QeYndvIriDDw2zpVNcno45sClSQCb +YVekMLgGlKPmNGub5iRfXsozykE3jbMnXRokxrvzk20jjo0XYPVGfCRe9IhJh8Ud +iCG/kPaJspbUkUlKXfvIOdp2pnoDFZI5hbfc75YrFYJ8x8dwRYBUl6yRtBkw5Yo/ +VQDuNq3d7YpxiGxVTwFox6HQ5+rs6jwSGzOilgOCxPSs41fYcdAlogNqLzjvhn+e +0GU1XTVyMJbO0Ae6Sgm4PmxU7QM2bdzESuZWbYRFbH2ywwmoR8SahB3ICBhuIA/l +lsCrBbq+jL/K2IL1VXBKuaKBN1ShKUPZD/ABWNv4uENNg2AFq1XQ6kvTU8Glfhd9 +tyK8YnJ0ViY4VLGhdf0s2eEPmbfxOv0HCW0sz/57eASoQSTJTdVApYopWHBOwaNq +8qQUEPDMTKaPNqCjA2m/NwGrLPHhU0d5dHmp+9gTbCTmWy4sVenhBPbOy6wvFpNA +F+35tJVaZQOOurm/KC2dLOYkKyAvqnB7D2q4zducpWkiyCweg7uYL14Mo5JQmGuq +2DwfRiMxdqqoqHFKEOxsoAMrKSwJlYojUknfz/LEaqxtMePQtNwhjw== +-----END RSA PRIVATE KEY----- + + +6. CLR issued by subca CRL issuer +-----BEGIN X509 CRL----- +MIIBLTCBlwIBATANBgkqhkiG9w0BAQQFADAxMQswCQYDVQQGEwJVUzEQMA4GA1UE +ChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMRcNMDkwNjI4MTMzMjQzWhcNMjgw +ODI3MTMzMjQzWjAiMCACAQQXDTA5MDYyODEzMzIzOFowDDAKBgNVHRUEAwoBBKAO +MAwwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEEBQADgYEACQZEf6ydb3fKTMPJ8DBO +oo630MsrT3P0x0AC4+aQOueCBaGpNqW/H379uZxXAad7yr+aXUBwaeBMYVKUbwOe +5TrN5QWPe2eCkU+MSQvh1SHASDDMH4jhWFMRdO3aPMDKKPlO/Q3s0G72eD7Zo5dr +N9AvUXxGxU4DruoJuFPcrCI= +-----END X509 CRL----- + + +7. dumca certificate and key +-----BEGIN CERTIFICATE----- +MIICUDCCAbmgAwIBAgIBBTANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjhaFw0yOTAzMTUxMzMyMjha +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz +cy1EMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDeWn+ulgls9+dK3KzzfC1b +a9RMSf+gjv/Olw5386Vw6pJOVngR11RytWJoLiKbjYPyGhP1cms2FoUKuAEO31gD +3AoUCa+nXgaMLiDtmdC5ATqVv3Oap5aNgAqq0mxMxOylKgcUhfuH2icEnfBtHzEe +ST11S69zQr5GGfa/XslbDQIDAQABo4GJMIGGMB0GA1UdDgQWBBRCmXIsp4G3iP7Z +Qv4gS19W8W/cLzBHBgNVHSMEQDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEw +HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw +AwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQADgYEAkRiLpJesXyNQ34ZP +Oc4d0gvCl4pyNHx5gsV0yHtxP7oYoIa7Bw4setplQ9Y2YcH5xuXK84xvAby9csWp +cod1QOkFzZfb9qj10PXfD8bMoLOyrZfr5nsNAl2scvOtnM1TFL/ll5/S2PVcPthx +Z5t128UNQYMu93OmVjZANL5L6Jw= +-----END CERTIFICATE----- + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,11485599004D2482 + +R+TgUoQo1Ksqpnwh1B1x3u7jxd1qJsfG5st7WJaeJzSY3v+ZnmTS4O008eKgw6Z1 +eGJevsNW8Z8ButjChzlesCm+90jpKpOqA6MlvzeknAxtGdEfe8rUEytfNOorjJTy +1Mu9T8Tlk6tmmmXNTDX1lQytYaHA4e4VVEbYGNceMNcPonT1Y0SyebJwtfd4XKkG +Ty40kMnb+qrFr1ZxVRG+LWKDR/bS0S2K2zY6Ha45d8yoYZlgLZ7yVAlrp0T0PF4B +UWvSyNK9VOBLrvqXSofK5gNGkR/C63x8FU2V25ISicBQBXLNo9OgIsbrryHF330T +2TxhnOpFU1AwgTSfp4Fy/Htkvgo7/jmFRa3r4xelTdEUKvRrwaZeMjg0fT+24529 +8o8MMOF0YWNtIDNUVRFg9/DgAsD/LoXbOGc/E2ryJdq1D4N914s4m/D5Sox27iu4 +3op/dt+WMoA0g/YbjhWn2cAfWcH9P8p8/n/FUO8APmGI3aHbtOhJQ8qwxcalp6kO +fICWsW4ygWtdpnyJWzAY0Udtsl8mglTppGTl59OYZmlDQTLhJ1hWiXLeNKj0pGPz +bAJ5jGQN8zXAk83j019rI5WveAdWp+w1XRGvmPxLL3heojHrkutuYLQ0LOcFwNvg +OqmPvZneRBoy6Yshp0XyYy+qioxDm+Vd/NV1/aCWgQXJA3vFqUg3AURLFHHTh+7h +fa3DDCLtdg/wJkRtOWjFhq0hgx5sb9zVv8HCuMERbZJbWwDOfSrHJwXj4KaTHVqY +OWfBE9vzeAxRpdpe69SZWYg3tyu7uSf6a5Rp55iMI3kjuQMCanvsNA== +-----END RSA PRIVATE KEY----- + + +8. crl issuer for dumca, the certificate and key +-----BEGIN CERTIFICATE----- +MIICUDCCAbmgAwIBAgIBBjANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjlaFw0yOTAzMTUxMzMyMjla +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz +cy1EMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDF7NjUUWji4pPmFg3qx4HB +kjtInwe7i2lPjRUN0ZwTcWob2RaD1+fhc7seeNmnypjERTa9TXF5cs2PgSHWNISC +QbQpbobOUcSsV/6Lr0kvrHJuVowcX13VsApGSJavVs2oJqUiFGNpnch8yR/pMHJf +hsd/Go+nUXMOl2xN31DMFQIDAQABo4GJMIGGMB0GA1UdDgQWBBS1XVE2CYKHgO7t +1koYVTu2w7xgNTBHBgNVHSMEQDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEw +HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw +AwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQADgYEAHYraYtdetZFOiTUR +dhvUi556el1WT25O8pF21YAzRI7KI4yzl6deD29DtcIPiBc8H1A4U6OhwXSQsqTd +taOHHdZxnU+m078mb231OPVvo48uZwpnX35g/qItW+Nb/dIEb08537oQKoGgL0hV +sKZPWod70JBkJabDuUirorhlk4A= +-----END CERTIFICATE----- + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1E0E5983F90A10E0 + +KdPTRmJjeKXFTgdVIgP0eu+m0evwVD2QFMkT3pPI9HELRxtkgIQzjK8F0KIHK9vi +Ur0CMgJkX0zs2v7HIG7jvfQ2fREidRTk1g3xCjHXVbpwjWN2dbo+mR0J2zzxNILy +mSs13PlDPdV81Vkn1WkMY0lhdrEpR6senQ4KIiMJTMsWZabG3lyFM6d7ag7CDVC+ +jnsUFg2XW5dYP/kb09p14+CdiQwruNVeVEWhWPG1pAjl7hXCEM5ssz9fNk6Gyh2X +OXB2mMysqTkt+qB+OIqLKj3NTUs2ovVQZnaCaynsnMYTcIEFmv3lC0gJHYAZtBXf +IkySb+VaB7wmk1CI1+texDU8+B2sq7wmqX0SLY7dMwkbxP1kydn9U5i4Gqmdxpw5 +4+jn7dB6oKfVFlXIZTZzhmN44cIdai48qVmse1BRDxUdfmlgd9C2W1mw4N60BXbt +DeNr8ua5UtcUOXBGJk6VEJapDU/dnnANhVR4R48Y9t+g1qlhwHB4zbSrAIJ5Rsbg +6pvdt7BQmFXtm4flZbf21Lr8awWkNFdc/k/3uXA6xemgsFNxPZXlpXO26KpIP+nz +lt9Q82WxIkzE+BvO+qd5wMqQ/GC/ztO8GJeGdRIo6un7KkNKs2AZDoCELo2lO53B +EBWHeABtJpB1Fw3lW3iJn0A6YbYzK1omztoNMkesBIi0QI5L/e0tq4Mp+LUjLm+Y +ywdrofTiYTu8R7mgS1b5q3eFtwUR9MZuKJGvhsBcSfS41vH2hDezYHg8vW55UIE3 +h7EhOUnTkHY43OKZnmXHwh3pTEmHv1TfMpeaktiU/w0= +-----END RSA PRIVATE KEY----- + +9. end entity certificate issued by subca, Alice +-----BEGIN CERTIFICATE----- +MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQQFADAxMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA2MjgxMzMy +MzBaFw0yOTAzMTUxMzMyMzBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt +cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEA7wnsvR4XEOfVznf40l8ClLod+7L0y2/+smVV+GM/ +T1/QF/stajAJxXNy08gK00WKZ6ruTHhR9vh/Z6+EQM2RZDCpU0A7LPa3kLE/XTmS +1MLDu8ntkdlpURpvhdDWem+rl2HU5oZgzV8Jkcov9vXuSjqEDfr45FlPuV40T8+7 +cxsCAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSBwsAhi6Z1kriOs3ty +uSIujv9a3DAfBgNVHSMEGDAWgBRidC8Dt3dBzYESKpR2tR560sZ0+zANBgkqhkiG +9w0BAQQFAAOBgQDEiBqd5AMy2SQopFaS3dYkzj8MHlwtbCSoNVYkOfDnewcatrbk +yFcp6FX++PMdOQFHWvvnDdkCUAzZQp8kCkF9tGLVLBtOK7XxQ1us1LZym7kOPzsd +G93Dcf0U1JRO77juc61Br5paAy8Bok18Y/MeG7uKgB2MAEJYKhGKbCrfMw== +-----END CERTIFICATE----- + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,9E29E1901B338431 + +796Bj4/MwwHdy6+yZQcq3pS12EZPlEm7qsCCTl787y+DYEnnj+9W4WX4+1zWsUGV +1+39oe/KOUfi5O9ytMuKiroIrklmkskWHDoW6sr4VcDprnLYL+75AhTfgpOtY+gK +q+++N7P2o9V6YF7PiGxaBqGy/3bt0nTu0sjctfzbo4g0PniiId9sus2Y+iRHKebJ +r9V0b0jB8USuIsZ+4IQJFZ+/zeKuqqqPM/4v5VKNUahER8oykhRd4L9UactnVH5t +dsfowtHmOmKE6ObJX3m+HgJMvauMMf7zJVdqJquU2vy0bUk9ufCrA7t5ws7JDRzd +SG5gt7EVQzd5x/yXsQdKbDew5mXsYPB8vz4moTgj4YJU+m6k0t1PH00pz7LUrDHl +E8ZAmXIKLEBIih1AWkdASR/YZsfB3URIC8mLyDSZJN5iEVJxl/JWm6pbJlP3Xn3J +fraVEXP6uerf29CNhizq520AfGdsSqga6atdx6PXBVm67V0TZ+zmBMUQJrWmJUUC +NFGAac+M58lYX9uwsrO9x/x6GSZvhQQu1kfD1m8DHN3IV5m3uHxsEvhmuHaqFEMJ +uH336HbqWYENXwZfDHZvOU1o2FejsLZ7QmFjB72iAxhVNQt53pCXed2gF/bERGSn +qi0PsYtjyzfEUefqlVRSWVulbQfGwkvl8dX9s6BxmOG1q0BzlDu+cQLYXPS+XOww +H8GgkGp6XTd04qT/qCm8gcuxAvdkYkj2zgAIKaqeJ53S3Ua9lrIKnA3L3btiEG5F +JTYutSdRqB4liukkB1TciiDVSmOisszjrMHhRRYPfgeLfnRFdX9U9g== +-----END RSA PRIVATE KEY----- + +10. end entity certificate issued by subca, Bob +-----BEGIN CERTIFICATE----- +MIICNTCCAZ6gAwIBAgIBAzANBgkqhkiG9w0BAQQFADAxMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA2MjgxMzMy +MzVaFw0yOTAzMTUxMzMyMzVaMD8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt +cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQwwCgYDVQQDEwNCb2IwgZ8wDQYJKoZIhvcN +AQEBBQADgY0AMIGJAoGBALLrxd3DpXuH7yiAoyi/Rc1F7WsyyeNE1Ra2ymHpcee/ +3sbldekcgPl6lGQF/JJ5ARBbfeDtaf6ZtAK3j6aXqxVFxDKKu86r96v74gWJB7Vv +CHcUPvmE/EGESq3VNFI998DbmvqICLC97nFLUIrKWDH1rRFZjjkmouln40UxQXvV +AgMBAAGjTzBNMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUTXz1J2viNSKvRHIRVhD6 +cJE4lgYwHwYDVR0jBBgwFoAUYnQvA7d3Qc2BEiqUdrUeetLGdPswDQYJKoZIhvcN +AQEEBQADgYEApsKyLf4FbXb26KsQrxgFn/w0d/7ck4cE8a6oXQqi5OLheNSWfD3S +fgD1dR28mGmhBiyOkdLmrhA1+6BuEr4FsuyLgrFnEqKL0ZhVhiqvwKLGqvasWxfU +Edaw4WXvRcfRWXfgjtwB6PSj/3nqGKSGRPif/OFIjO6UqHwEM7JEWO4= +-----END CERTIFICATE----- + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,4A820975D251613F + +GseD8MIztC0oYMxwpxeBO4/YPs9ZFFjgncXXcy+1oYZdlEsrS1xw87unjeHigL8m +QPIn8Guv3DiOsBdvweuMAgPPaA1zlophPClbGZMk7BB3T2acEfjBQH1DZz7kd7Bf +OmI2DrqcEg1yDi7l7YutBuTQPiy3nj3d7pbScuFd5YVMu6yH0YpS7JsPvviabFk2 +eYVlkaiejtQwV+4rUb7sH/0iyqX2uqvnpnGAwVzGp+tfSOl71SByz240nOODBRgY +3Uvxkrw6XhCBAayJE0t7rkPMEe1KgZaGO2IU2jsJJbyHVjvNPSugdbsT28prZHN1 +5M1J1NSOssq/kAq6S3f9sC5j7OzP7oUlx8uMUUSaz09/Ttq22tUoqmTue2IqqxAt +lDaeR8duHP5VV1wWnDsW/XaVYlBFQ4eFPJcXqmWsNAkDQVJp327GrcT6ngevP8fD +BcIxyX6J0rETPruAE+1+PAGjqy+C+oB0ssyZvKcjzdajHcNxSlRpCuOO2ekDvNPO +h+mVukNpHCEBsh3jYmk3z9i7VPLCM0BI+vheJ1TbM+homWP6bXyTQxtLfaKzXZJH +jRJ+zGTMBNJoPVKkou03uXFpT6hdWr9nYwbMT6G9hmC0If3wEl8nRjDKbmyMS29B +p3im1kPxVJA0DjhghC+7tACy42ffw6KZPALwaVDKHGeitrQBc3xTGfrjOGQOTTcm +hZ8icYCY0cjl5KQ2kq2GpXa2zQMujNV/Oj7D4sE0xcASMRXl3tst77R/j0eowx1M +niCTRphxx4iTPkieIbjWWeFTpVmSzUBrm4hSw3tiRapVWf6Zo3aAIg== +-----END RSA PRIVATE KEY----- + +11. end entity certificate issued by subca, Susan +-----BEGIN CERTIFICATE----- +MIICNzCCAaCgAwIBAgIBBDANBgkqhkiG9w0BAQQFADAxMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA2MjgxMzMy +MzZaFw0yOTAzMTUxMzMyMzZaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt +cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVTdXNhbjCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAr2u6mdjqAVtfcgPze+9OUFZu3pi+HqoNBoygm2gq +qRAe+FVNSUeNAMQesQBo/eB0F1Iv/BjnYJ/7pYMLaf90MLoYr0Q5vNKYlBdcyUee +Jn1WmfN2Qk+UoUaiM4HAKHNJnZk13vWpZW54mcW1q09oj0oMjAZtaZsqpY6CtW6/ ++J8CAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBQVK9naug5W9pQlBqD2 +fVaCXooa1TAfBgNVHSMEGDAWgBRidC8Dt3dBzYESKpR2tR560sZ0+zANBgkqhkiG +9w0BAQQFAAOBgQDKYoM8EbP78ucjtsdvw4ywyo21hhSeP9PmRnNz/U3F9sQATmn+ +QBl6sBsrmbML2yrhkM1ctZTVUVp0S72fAbLgVjNk86p/CF+a2tmi0+lJh1aR7zQi +opt+68Nec2/52kgWi64ruF7YITmGHBxS/RDooFbscZbdrPgcow/Jw+5HnQ== +-----END CERTIFICATE----- + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,9025CDB2AB43B0DE + +q4hvYnqkhDSDCsbXfxtMjPvzT38ql5wscOsGwDM/xMANSyPk9h/aqAxvB8G+8v6E +63x9Q5jRi2YY6z2sOpvu0utu7Xn6KA/H1YrpYFURTEjBbK2Qd41vPQ/NYcIO3nQd +PR2Qm3kpNumBSZomyNfJk9oegGxfw+P0af2GIb6YqmTDot+LLCLwpqxrGyQQ1LYp +zc4A9D/b19Y0eD+TU9S2KEYszvfUo7RBxRFSZ6QN1rT2SEa7IJN9wb6TvgeB2lRB +Ds90tmLtkbuwLTZre+aqbM8mU40+RI9GHh+mPw0Qz55Kw2CUe+PnGsLQnOTm7p/I +mLiPTNMJKvwaR18Z88IE9UwL0zE/ND7vZfrhqTn9bHRnzHU4NtBCBsS8zloI+rXZ +EIWKMDyzMH3wpbNYq/AemSvvUz1wGOxit5TjG2QwwCNt8hPLl0Es6Q5aWdAPPrLM +EfX/6gL7bLTHNyLPz/U32o0H4hz5J7FQ7SuYUPLI3ybiPC2qL11jbtrZMesAYEAX +mvRnqO+6dPEpwGmKz8kUj2mC8X8FPKCCiy4kbc8NjLTMao+/vOgD+wBuIePaC3yE +vpuZrsUSFZWRJ824sDMmmZFoi2DKsp1zqCV1kXozaPGigaOxtkdp890nBcGkPijQ +8F+jCGwSFda6UfuJHCQ/eJB+8LQUWa8u1TeJ9zo98oD2OBfQ5maZU0Vfv1EXvwbp +pz2R6HXFaPrQDeGO0xVzD453AbY/fZCGnhIwrEYvPAbwpIKde397MP66gYFMNFhA +IaMimFnBv7IHL08Ka0KtqbVhLpEKWFpZ6LsOnyispeB4KF0md+lpGg== +-----END RSA PRIVATE KEY----- diff --git a/jdk/test/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java new file mode 100644 index 00000000000..ed0cf53ace1 --- /dev/null +++ b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java @@ -0,0 +1,309 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6852744 + * @summary PIT b61: PKI test suite fails because self signed certificates + * are being rejected + * @run main/othervm StatusLoopDependency subca + * @run main/othervm StatusLoopDependency subci + * @run main/othervm StatusLoopDependency alice + * @author Xuelei Fan + */ + +import java.io.*; +import java.net.SocketException; +import java.util.*; +import java.security.Security; +import java.security.cert.*; +import java.security.cert.CertPathValidatorException.BasicReason; +import sun.security.util.DerInputStream; + +/** + * KeyUsage extension plays a important rule during looking for the issuer + * of a certificate or CRL. A certificate issuer should have the keyCertSign + * bit set, and a CRL issuer should have the cRLSign bit set. + * + * Sometime, a delegated CRL issuer would also have the keyCertSign bit set, + * as would be troublesome to find the proper CRL issuer during certificate + * path build if the delegated CRL issuer is a self-issued certificate, for + * it is hard to identify it from its issuer by the "issuer" field only. + * + * In the test case, the delegated CRL issuers have keyCertSign bit set, and + * the CAs have the cRLSign bit set also. If we cannot identify the delegated + * CRL issuer from its issuer, there is a potential loop to find the correct + * CRL. + * + * And when revocation enabled, needs to check the status of the delegated + * CRL issuers. If the delegated CRL issuer issues itself status, there is + * a potential loop to verify the CRL and check the status of delegated CRL + * issuer. + * + * The fix of 6852744 should addresses above issues. + */ +public final class StatusLoopDependency { + + // the trust anchor + static String selfSignedCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMThaFw0zMDA2MDgxMzMyMTha\n" + + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" + + "AQUAA4GNADCBiQKBgQDInJhXi0655bPXAVkz1n5I6fAcZejzPnOPuwq3hU3OxFw8\n" + + "81Uf6o9oKI1h4w4XAD8u1cUNOgiX+wPwojronlp68bIfO6FVhNf287pLtLhNJo+7\n" + + "m6Qxw3ymFvEKy+PVj20CHSggdKHxUa4MBZBmHMFNBuxfYmjwzn+yTMmCCXOvSwID\n" + + "AQABo4GJMIGGMB0GA1UdDgQWBBSQ52Dpau+gtL+Kc31dusYnKj16ZTBHBgNVHSME\n" + + "QDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" + + "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYw\n" + + "DQYJKoZIhvcNAQEEBQADgYEAjBt6ea65HCqbGsS2rs/HhlGusYXtThRVC5vwXSey\n" + + "ZFYwSgukuq1KDzckqZFu1meNImEwdZjwxdN0e2p/nVREPC42rZliSj6V1ThayKXj\n" + + "DWEZW1U5aR8T+3NYfDrdKcJGx4Hzfz0qKz1j4ssV1M9ptJxYYv4y2Da+592IN1S9\n" + + "v/E=\n" + + "-----END CERTIFICATE-----"; + + // the sub-ca + static String subCaCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICUDCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjRaFw0yOTAzMTUxMzMyMjRa\n" + + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" + + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPFv24SK78VI0gWlyIrq/X\n" + + "srl1431K5hJJxMYZtaQunyPmrYg3oI9KvKFykxnR0N4XDPaIi75p9dXGppVu80BA\n" + + "+csvIPBwlBQoNmKDQWTziDOqfK4tE+IMuL/Y7pxnH6CDMY7VGpvatty2zcmH+m/v\n" + + "E/n+HPyeELJQT2rT/3T+7wIDAQABo4GJMIGGMB0GA1UdDgQWBBRidC8Dt3dBzYES\n" + + "KpR2tR560sZ0+zBHBgNVHSMEQDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEw\n" + + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" + + "AwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQADgYEAMeMKqrMr5d3eTQsv\n" + + "MYOD15Dl3THQGLAa4ad5Eyq5/1eUeEOpztzCgDfi0iPD8YCubIEVasBTSqTiGXqb\n" + + "RpGuPHOwwfWvHrTeHSludiFBAUiKj7aEV+oQa0FBn4U4TT8HA62HQ93FhzTDI3jP\n" + + "iil34GktVl6gfMKGzUEW/Dh8OM4=\n" + + "-----END CERTIFICATE-----"; + + // a delegated CRL issuer, it's a self-issued certificate of trust anchor + static String topCrlIssuerCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICPjCCAaegAwIBAgIBAjANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjNaFw0yOTAzMTUxMzMyMjNa\n" + + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" + + "AQUAA4GNADCBiQKBgQC99u93trf+WmpfiqunJy/P31ej1l4rESxft2JSGNjKuLFN\n" + + "/BO3SAugGJSkCARAwXjB0c8eeXhXWhVVWdNpbKepRJTxrjDfnFIavLgtUvmFwn/3\n" + + "hPXe+RQeA8+AJ99Y+o+10kY8JAZLa2j93C2FdmwOjUbo8aIz85yhbiV1tEDjLwID\n" + + "AQABo4GJMIGGMB0GA1UdDgQWBBSyFyA3XWLbdL6W6hksmBn7RKsQmDBHBgNVHSME\n" + + "QDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" + + "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYw\n" + + "DQYJKoZIhvcNAQEEBQADgYEAHTm8aRTeakgCfEBCgSWK9wvMW1c18ANGMm8OFDBk\n" + + "xabVy9BT0MVFHlaneh89oIxTZN0FMTpg21GZMAvIzhEt7DGdO7HLsW7JniN7/OZ0\n" + + "rACmpK5frmZrLS03zUm8c+rTbazNfYLoZVG3/mDZbKIi+4y8IGnFcgLVsHsYoBNP\n" + + "G0c=\n" + + "-----END CERTIFICATE-----"; + + // a delegated CRL issuer, it's a self-issued certificate of sub-ca + static String subCrlIssuerCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICUDCCAbmgAwIBAgIBBDANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA2MjgxMzMyMjdaFw0yOTAzMTUxMzMyMjda\n" + + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" + + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+8AcLJtGAVUWvv3ifcyQw\n" + + "OGqwzcPrBw/XCs6vTMlcdtFzcH1M+Z3/QHN9+5VT1gqeTIZ+b8g9005Og3XKy/HX\n" + + "obXZeLv20VZsr+jm52ySghEYOVCTJ9OyFOAp5adp6nf0cA66Feh3LsmVhpTEcDOG\n" + + "GnyntQm0DBYxRoOT/GBlvQIDAQABo4GJMIGGMB0GA1UdDgQWBBSRWhMuZLQoHSDN\n" + + "xhxr+vdDmfAY8jBHBgNVHSMEQDA+gBSQ52Dpau+gtL+Kc31dusYnKj16ZaEjpCEw\n" + + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" + + "AwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQADgYEAMIDZLdOLFiPyS1bh\n" + + "Ch4eUYHT+K1WG93skbga3kVYg3GSe+gctwkKwKK13bwfi8zc7wwz6MtmQwEYhppc\n" + + "pKKKEwi5QirBCP54rihLCvRQaj6ZqUJ6VP+zPAqHYMDbzlBbHtVF/1lQUP30I6SV\n" + + "Fu987DvLmZ2GuQA9FKJsnlD9pbU=\n" + + "-----END CERTIFICATE-----"; + + // the target EE certificate + static String targetCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQQFADAxMQswCQYDVQQGEwJVUzEQ\n" + + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA2MjgxMzMy\n" + + "MzBaFw0yOTAzMTUxMzMyMzBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" + + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" + + "9w0BAQEFAAOBjQAwgYkCgYEA7wnsvR4XEOfVznf40l8ClLod+7L0y2/+smVV+GM/\n" + + "T1/QF/stajAJxXNy08gK00WKZ6ruTHhR9vh/Z6+EQM2RZDCpU0A7LPa3kLE/XTmS\n" + + "1MLDu8ntkdlpURpvhdDWem+rl2HU5oZgzV8Jkcov9vXuSjqEDfr45FlPuV40T8+7\n" + + "cxsCAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSBwsAhi6Z1kriOs3ty\n" + + "uSIujv9a3DAfBgNVHSMEGDAWgBRidC8Dt3dBzYESKpR2tR560sZ0+zANBgkqhkiG\n" + + "9w0BAQQFAAOBgQDEiBqd5AMy2SQopFaS3dYkzj8MHlwtbCSoNVYkOfDnewcatrbk\n" + + "yFcp6FX++PMdOQFHWvvnDdkCUAzZQp8kCkF9tGLVLBtOK7XxQ1us1LZym7kOPzsd\n" + + "G93Dcf0U1JRO77juc61Br5paAy8Bok18Y/MeG7uKgB2MAEJYKhGKbCrfMw==\n" + + "-----END CERTIFICATE-----"; + + // CRL issued by the delegated CRL issuer, topCrlIssuerCertStr + static String topCrlStr = + "-----BEGIN X509 CRL-----\n" + + "MIIBGzCBhQIBATANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQMA4GA1UE\n" + + "ChMHRXhhbXBsZRcNMDkwNjI4MTMzMjM4WhcNMjgwODI3MTMzMjM4WjAiMCACAQUX\n" + + "DTA5MDYyODEzMzIzN1owDDAKBgNVHRUEAwoBBKAOMAwwCgYDVR0UBAMCAQEwDQYJ\n" + + "KoZIhvcNAQEEBQADgYEAVUIeu2x7ZwsliafoCBOg+u8Q4S/VFfTe/SQnRyTM3/V1\n" + + "v+Vn5Acc7eo8Rh4AHcnFFbLNk38n6lllov/CaVR0IPZ6hnrNHVa7VYkNlRAwV2aN\n" + + "GUUhkMMOLVLnN25UOrN9J637SHmRE6pB+TRMaEQ73V7UNlWxuSMK4KofWen0A34=\n" + + "-----END X509 CRL-----"; + + // CRL issued by the delegated CRL issuer, subCrlIssuerCertStr + static String subCrlStr = + "-----BEGIN X509 CRL-----\n" + + "MIIBLTCBlwIBATANBgkqhkiG9w0BAQQFADAxMQswCQYDVQQGEwJVUzEQMA4GA1UE\n" + + "ChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMRcNMDkwNjI4MTMzMjQzWhcNMjgw\n" + + "ODI3MTMzMjQzWjAiMCACAQQXDTA5MDYyODEzMzIzOFowDDAKBgNVHRUEAwoBBKAO\n" + + "MAwwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEEBQADgYEACQZEf6ydb3fKTMPJ8DBO\n" + + "oo630MsrT3P0x0AC4+aQOueCBaGpNqW/H379uZxXAad7yr+aXUBwaeBMYVKUbwOe\n" + + "5TrN5QWPe2eCkU+MSQvh1SHASDDMH4jhWFMRdO3aPMDKKPlO/Q3s0G72eD7Zo5dr\n" + + "N9AvUXxGxU4DruoJuFPcrCI=\n" + + "-----END X509 CRL-----"; + + private static Set generateTrustAnchors() + throws CertificateException { + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + ByteArrayInputStream is = + new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); + + // generate a trust anchor + TrustAnchor anchor = + new TrustAnchor((X509Certificate)selfSignedCert, null); + + return Collections.singleton(anchor); + } + + private static CertStore generateCertificateStore() throws Exception { + Collection entries = new HashSet(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + ByteArrayInputStream is; + + is = new ByteArrayInputStream(targetCertStr.getBytes()); + Certificate cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(selfSignedCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(topCrlIssuerCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + cert = cf.generateCertificate(is); + entries.add(cert); + + // generate CRL from CRL string + is = new ByteArrayInputStream(topCrlStr.getBytes()); + Collection mixes = cf.generateCRLs(is); + entries.addAll(mixes); + + is = new ByteArrayInputStream(subCrlStr.getBytes()); + mixes = cf.generateCRLs(is); + entries.addAll(mixes); + + return CertStore.getInstance("Collection", + new CollectionCertStoreParameters(entries)); + } + + private static X509CertSelector generateSelector(String name) + throws Exception { + X509CertSelector selector = new X509CertSelector(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream is = null; + if (name.equals("subca")) { + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + } else if (name.equals("subci")) { + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + } else { + is = new ByteArrayInputStream(targetCertStr.getBytes()); + } + + X509Certificate target = (X509Certificate)cf.generateCertificate(is); + byte[] extVal = target.getExtensionValue("2.5.29.14"); + if (extVal != null) { + DerInputStream in = new DerInputStream(extVal); + byte[] subjectKID = in.getOctetString(); + selector.setSubjectKeyIdentifier(subjectKID); + } else { + // unlikely to happen. + throw new Exception("unexpected certificate: no SKID extension"); + } + + return selector; + } + + private static boolean match(String name, Certificate cert) + throws Exception { + X509CertSelector selector = new X509CertSelector(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream is = null; + if (name.equals("subca")) { + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + } else if (name.equals("subci")) { + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + } else { + is = new ByteArrayInputStream(targetCertStr.getBytes()); + } + X509Certificate target = (X509Certificate)cf.generateCertificate(is); + + return target.equals(cert); + } + + + public static void main(String[] args) throws Exception { + CertPathBuilder builder = CertPathBuilder.getInstance("PKIX"); + + X509CertSelector selector = generateSelector(args[0]); + + Set anchors = generateTrustAnchors(); + CertStore certs = generateCertificateStore(); + + + PKIXBuilderParameters params = + new PKIXBuilderParameters(anchors, selector); + params.addCertStore(certs); + params.setRevocationEnabled(true); + params.setDate(new Date(109, 7, 1)); // 2009-07-01 + Security.setProperty("ocsp.enable", "false"); + System.setProperty("com.sun.security.enableCRLDP", "true"); + + PKIXCertPathBuilderResult result = + (PKIXCertPathBuilderResult)builder.build(params); + + if (!match(args[0], result.getCertPath().getCertificates().get(0))) { + throw new Exception("unexpected certificate"); + } + } +} diff --git a/jdk/test/java/security/cert/CertPathBuilder/selfIssued/generate.sh b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/generate.sh new file mode 100644 index 00000000000..06429d63ffa --- /dev/null +++ b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/generate.sh @@ -0,0 +1,221 @@ +# +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +#!/bin/ksh +# +# needs ksh to run the script. + +# generate a self-signed root certificate +if [ ! -f root/root_cert.pem ]; then + if [ ! -d root ]; then + mkdir root + fi + + openssl req -x509 -newkey rsa:1024 -keyout root/root_key.pem \ + -out root/root_cert.pem -subj "/C=US/O=Example" \ + -config openssl.cnf -reqexts cert_issuer -days 7650 \ + -passin pass:passphrase -passout pass:passphrase +fi + +# generate a sele-issued root crl issuer certificate +if [ ! -f root/top_crlissuer_cert.pem ]; then + if [ ! -d root ]; then + mkdir root + fi + + openssl req -newkey rsa:1024 -keyout root/top_crlissuer_key.pem \ + -out root/top_crlissuer_req.pem -subj "/C=US/O=Example" -days 7650 \ + -passin pass:passphrase -passout pass:passphrase + + openssl x509 -req -in root/top_crlissuer_req.pem -extfile openssl.cnf \ + -extensions crl_issuer -CA root/root_cert.pem \ + -CAkey root/root_key.pem -out root/top_crlissuer_cert.pem \ + -CAcreateserial -CAserial root/root_cert.srl -days 7200 \ + -passin pass:passphrase +fi + +# generate subca cert issuer and crl iuuser certificates +if [ ! -f subca/subca_cert.pem ]; then + if [ ! -d subca ]; then + mkdir subca + fi + + openssl req -newkey rsa:1024 -keyout subca/subca_key.pem \ + -out subca/subca_req.pem -subj "/C=US/O=Example/OU=Class-1" \ + -days 7650 -passin pass:passphrase -passout pass:passphrase + + openssl x509 -req -in subca/subca_req.pem -extfile openssl.cnf \ + -extensions cert_issuer -CA root/root_cert.pem \ + -CAkey root/root_key.pem -out subca/subca_cert.pem -CAcreateserial \ + -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase + + openssl req -newkey rsa:1024 -keyout subca/subca_crlissuer_key.pem \ + -out subca/subca_crlissuer_req.pem -subj "/C=US/O=Example/OU=Class-1" \ + -days 7650 -passin pass:passphrase -passout pass:passphrase + + openssl x509 -req -in subca/subca_crlissuer_req.pem -extfile openssl.cnf \ + -extensions crl_issuer -CA root/root_cert.pem \ + -CAkey root/root_key.pem -out subca/subca_crlissuer_cert.pem \ + -CAcreateserial -CAserial root/root_cert.srl -days 7200 \ + -passin pass:passphrase +fi + +# generate dumca cert issuer and crl iuuser certificates +if [ ! -f dumca/dumca_cert.pem ]; then + if [ ! -d sumca ]; then + mkdir dumca + fi + + openssl req -newkey rsa:1024 -keyout dumca/dumca_key.pem \ + -out dumca/dumca_req.pem -subj "/C=US/O=Example/OU=Class-D" \ + -days 7650 -passin pass:passphrase -passout pass:passphrase + + openssl x509 -req -in dumca/dumca_req.pem -extfile openssl.cnf \ + -extensions cert_issuer -CA root/root_cert.pem \ + -CAkey root/root_key.pem -out dumca/dumca_cert.pem \ + -CAcreateserial -CAserial root/root_cert.srl -days 7200 \ + -passin pass:passphrase + + openssl req -newkey rsa:1024 -keyout dumca/dumca_crlissuer_key.pem \ + -out dumca/dumca_crlissuer_req.pem -subj "/C=US/O=Example/OU=Class-D" \ + -days 7650 -passin pass:passphrase -passout pass:passphrase + + openssl x509 -req -in dumca/dumca_crlissuer_req.pem \ + -extfile openssl.cnf -extensions crl_issuer -CA root/root_cert.pem \ + -CAkey root/root_key.pem -out dumca/dumca_crlissuer_cert.pem \ + -CAcreateserial -CAserial root/root_cert.srl -days 7200 \ + -passin pass:passphrase +fi + +# generate certifiacte for Alice +if [ ! -f subca/alice/alice_cert.pem ]; then + if [ ! -d subca/alice ]; then + mkdir -p subca/alice + fi + + openssl req -newkey rsa:1024 -keyout subca/alice/alice_key.pem \ + -out subca/alice/alice_req.pem \ + -subj "/C=US/O=Example/OU=Class-1/CN=Alice" -days 7650 \ + -passin pass:passphrase -passout pass:passphrase + + openssl x509 -req -in subca/alice/alice_req.pem \ + -extfile openssl.cnf -extensions ee_of_subca \ + -CA subca/subca_cert.pem -CAkey subca/subca_key.pem \ + -out subca/alice/alice_cert.pem -CAcreateserial \ + -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase +fi + +# generate certifiacte for Bob +if [ ! -f subca/bob/bob_cert.pem ]; then + if [ ! -d subca/bob ]; then + mkdir -p subca/bob + fi + + openssl req -newkey rsa:1024 -keyout subca/bob/bob_key.pem \ + -out subca/bob/bob_req.pem \ + -subj "/C=US/O=Example/OU=Class-1/CN=Bob" -days 7650 \ + -passin pass:passphrase -passout pass:passphrase + + openssl x509 -req -in subca/bob/bob_req.pem \ + -extfile openssl.cnf -extensions ee_of_subca \ + -CA subca/subca_cert.pem -CAkey subca/subca_key.pem \ + -out subca/bob/bob_cert.pem -CAcreateserial \ + -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase +fi + +# generate certifiacte for Susan +if [ ! -f subca/susan/susan_cert.pem ]; then + if [ ! -d subca/susan ]; then + mkdir -p subca/susan + fi + + openssl req -newkey rsa:1024 -keyout subca/susan/susan_key.pem \ + -out subca/susan/susan_req.pem \ + -subj "/C=US/O=Example/OU=Class-1/CN=Susan" -days 7650 \ + -passin pass:passphrase -passout pass:passphrase + + openssl x509 -req -in subca/susan/susan_req.pem -extfile openssl.cnf \ + -extensions ee_of_subca -CA subca/subca_cert.pem \ + -CAkey subca/subca_key.pem -out subca/susan/susan_cert.pem \ + -CAcreateserial -CAserial subca/subca_cert.srl -days 7200 \ + -passin pass:passphrase +fi + + +# generate the top CRL +if [ ! -f root/top_crl.pem ]; then + if [ ! -d root ]; then + mkdir root + fi + + if [ ! -f root/index.txt ]; then + touch root/index.txt + echo 00 > root/crlnumber + fi + + openssl ca -gencrl -config openssl.cnf -name ca_top -crldays 7000 \ + -crl_reason superseded -keyfile root/top_crlissuer_key.pem \ + -cert root/top_crlissuer_cert.pem -out root/top_crl.pem \ + -passin pass:passphrase +fi + +# revoke dumca +openssl ca -revoke dumca/dumca_cert.pem -config openssl.cnf \ + -name ca_top -crl_reason superseded \ + -keyfile root/top_crlissuer_key.pem -cert root/top_crlissuer_cert.pem \ + -passin pass:passphrase + +openssl ca -gencrl -config openssl.cnf -name ca_top -crldays 7000 \ + -crl_reason superseded -keyfile root/top_crlissuer_key.pem \ + -cert root/top_crlissuer_cert.pem -out root/top_crl.pem \ + -passin pass:passphrase + +# revoke for subca +if [ ! -f subca/subca_crl.pem ]; then + if [ ! -d subca ]; then + mkdir subca + fi + + if [ ! -f subca/index.txt ]; then + touch subca/index.txt + echo 00 > subca/crlnumber + fi + + openssl ca -gencrl -config openssl.cnf -name ca_subca -crldays 7000 \ + -crl_reason superseded -keyfile subca/subca_crlissuer_key.pem \ + -cert subca/subca_crlissuer_cert.pem -out subca/subca_crl.pem \ + -passin pass:passphrase +fi + +# revoke susan +openssl ca -revoke subca/susan/susan_cert.pem -config openssl.cnf \ + -name ca_subca -crl_reason superseded \ + -keyfile subca/subca_crlissuer_key.pem \ + -cert subca/subca_crlissuer_cert.pem -passin pass:passphrase + +openssl ca -gencrl -config openssl.cnf -name ca_subca -crldays 7000 \ + -crl_reason superseded -keyfile subca/subca_crlissuer_key.pem \ + -cert subca/subca_crlissuer_cert.pem -out subca/subca_crl.pem \ + -passin pass:passphrase diff --git a/jdk/test/java/security/cert/CertPathBuilder/selfIssued/openssl.cnf b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/openssl.cnf new file mode 100644 index 00000000000..f9fca998b72 --- /dev/null +++ b/jdk/test/java/security/cert/CertPathBuilder/selfIssued/openssl.cnf @@ -0,0 +1,205 @@ +# +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# OpenSSL configuration file. +# + +HOME = . +RANDFILE = $ENV::HOME/.rnd + +[ ca ] +default_ca = CA_default + +[ CA_default ] +dir = ./top +certs = $dir/certs +crl_dir = $dir/crl +database = $dir/index.txt +unique_subject = no +new_certs_dir = $dir/newcerts +certificate = $dir/cacert.pem +serial = $dir/serial +crlnumber = $dir/crlnumber +crl = $dir/crl.pem +private_key = $dir/private/cakey.pem +RANDFILE = $dir/private/.rand +x509_extensions = v3_ca + +name_opt = ca_default +cert_opt = ca_default + +default_days = 7650 +default_crl_days = 30 +default_md = sha1 +preserve = no + +policy = policy_anything + +[ ca_top ] +dir = ./root +certs = $dir/certs +crl_dir = $dir/crl +database = $dir/index.txt +unique_subject = no +new_certs_dir = $dir/newcerts +certificate = $dir/cacert.pem +serial = $dir/serial +crlnumber = $dir/crlnumber +crl = $dir/crl.pem +private_key = $dir/private/cakey.pem +RANDFILE = $dir/private/.rand + +x509_extensions = v3_ca + +name_opt = ca_default +cert_opt = ca_default + +default_days = 7650 +default_crl_days = 30 +default_md = sha1 +preserve = no + +policy = policy_anything + +[ ca_subca ] +dir = ./subca +certs = $dir/certs +crl_dir = $dir/crl +database = $dir/index.txt +unique_subject = no +new_certs_dir = $dir/newcerts + +certificate = $dir/cacert.pem +serial = $dir/serial +crlnumber = $dir/crlnumber +crl = $dir/crl.pem +private_key = $dir/private/cakey.pem +RANDFILE = $dir/private/.rand + +x509_extensions = usr_cert + +name_opt = ca_default +cert_opt = ca_default + +default_days = 7650 +default_crl_days = 30 +default_md = sha1 +preserve = no + +policy = policy_anything + +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca + +string_mask = nombstr + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = NO +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = A-State + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Internet Widgits Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 +unstructuredName = An optional company name + +[ usr_cert ] +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer + +[ v3_req ] +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectAltName = email:example@openjdk.net, RID:1.2.3.4:true + +[ v3_ca ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +basicConstraints = critical,CA:true +keyUsage = keyCertSign, cRLSign + +[ cert_issuer ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +basicConstraints = critical,CA:true +keyUsage = keyCertSign, cRLSign + +[ crl_issuer ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +basicConstraints = critical,CA:true +keyUsage = keyCertSign, cRLSign + + +[ crl_ext ] +authorityKeyIdentifier = keyid:always,issuer:always + +[ ee_of_subca ] +keyUsage = nonRepudiation, digitalSignature, keyEncipherment, keyAgreement + +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer From 6480dd7357cb2354ff9bd6d39a8dd9d83844b008 Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Fri, 10 Jul 2009 19:10:02 -0700 Subject: [PATCH 40/61] 6859411: Bump the HS16 build number to 06 Update the HS16 build number to 06 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 6635ba6afd7..cdac48030fa 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009 HS_MAJOR_VER=16 HS_MINOR_VER=0 -HS_BUILD_NUMBER=05 +HS_BUILD_NUMBER=06 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 From 1b9d35f50c366a761ef753f55662bb3d43502d1b Mon Sep 17 00:00:00 2001 From: Matthew Flaschen Date: Sat, 11 Jul 2009 16:43:08 +0100 Subject: [PATCH 41/61] 6562614: Compiler warnings for gettimeofday in Inet4/Inet6AddressImpl.c Add missing header to remove compiler warnings. Reviewed-by: martin --- jdk/src/solaris/native/java/net/Inet4AddressImpl.c | 1 + jdk/src/solaris/native/java/net/Inet6AddressImpl.c | 1 + 2 files changed, 2 insertions(+) diff --git a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c index 9e3cca486db..4e43c9d5a3a 100644 --- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c +++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c @@ -24,6 +24,7 @@ */ #include +#include #include #include #include diff --git a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c index 5ecedbc6c4f..246585abcc3 100644 --- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c +++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c @@ -24,6 +24,7 @@ */ #include +#include #include #include #include From cbb1a71a104f7b0166c211bf2eb10cd305b8771a Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Mon, 13 Jul 2009 23:01:03 +0800 Subject: [PATCH 42/61] 6453837: PartialCompositeContext.allEmpty is buggy Reviewed-by: weijun --- .../com/sun/jndi/toolkit/ctx/PartialCompositeContext.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/PartialCompositeContext.java b/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/PartialCompositeContext.java index 5e7e0e3adce..c7bfcfaae4c 100644 --- a/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/PartialCompositeContext.java +++ b/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/PartialCompositeContext.java @@ -493,9 +493,9 @@ public abstract class PartialCompositeContext implements Context, Resolver { * Tests whether a name contains a nonempty component. */ protected static boolean allEmpty(Name name) { - Enumeration enum_ = name.getAll(); + Enumeration enum_ = name.getAll(); while (enum_.hasMoreElements()) { - if (!enum_.equals("")) { + if (!enum_.nextElement().isEmpty()) { return false; } } From 1783cb93300f9b2eddb7d4eb52a6db745017b85d Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Mon, 13 Jul 2009 14:47:31 -0700 Subject: [PATCH 43/61] Added tag jdk7-b64 for changeset 752e62a9e600 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index fab0cb001ae..6b4351ee95a 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -38,3 +38,4 @@ ffd09e767dfa6d21466183a400f72cf62d53297f jdk7-b57 472c21584cfd7e9c0229ad6a100366a5c03d2976 jdk7-b61 c7ed15ab92ce36a09d264a5e34025884b2d7607f jdk7-b62 57f7e028c7ad1806500ae89eb3f4cd9a51b10e18 jdk7-b63 +269c1ec4435dfb7b452ae6e3bdde005d55c5c830 jdk7-b64 From 9c68af3ff5d74f01a96f872f715b35d3792e81b2 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Mon, 13 Jul 2009 14:47:33 -0700 Subject: [PATCH 44/61] Added tag jdk7-b64 for changeset 444fd06c5063 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 79ae00977ca..0bb9b5fe667 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -38,3 +38,4 @@ f1e1cccbd13aa96d2d8bd872782ff764010bc22c jdk7-b60 e906b16a12a9a63b615898afa5d9673cbd1c5ab8 jdk7-b61 65b66117dbd70a493e9644aeb4033cf95a4e3c99 jdk7-b62 d20e45cd539f20405ff843652069cfd7550c5ab3 jdk7-b63 +047dd27fddb607f8135296b3754131f6e13cb8c7 jdk7-b64 From 068ac9fe23275f6470aa3a7d48c37b017dd713d7 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Mon, 13 Jul 2009 14:47:36 -0700 Subject: [PATCH 45/61] Added tag jdk7-b64 for changeset 4905b291b676 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 60de6119b89..0e026969a54 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -38,3 +38,4 @@ a77eddcd510c3972717c025cfcef9a60bfa4ecac jdk7-b60 27b728fd1281ab62e9d7e4424f8bbb6ca438d803 jdk7-b61 a88386380bdaaa5ab4ffbedf22c57bac5dbec034 jdk7-b62 32c83fb84370a35344676991a48440378e6b6c8a jdk7-b63 +ba36394eb84b949b31212bdb32a518a8f92bab5b jdk7-b64 From 18605d75a20b130b020b0777abfd6e74554c8ae2 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Mon, 13 Jul 2009 14:47:42 -0700 Subject: [PATCH 46/61] Added tag jdk7-b64 for changeset 5b8a9427ecc5 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index e476b1d9b26..67a0b9e2e17 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -38,3 +38,4 @@ e4851e9f7be26fc52a628be06ffa8aaea0919bd7 jdk7-b57 f1ac756616eaaad795f77f7f5e7f7c7bfdc9c1de jdk7-b61 a97dd57a62604c35c79bc2fa77a612ed547f6135 jdk7-b62 ae449e9c04c1fe651bd30f0f4d4cc24ba794e0c4 jdk7-b63 +a10eec7a1edf536f39b5828d8623054dbc62c2b7 jdk7-b64 From 636adcfc264a5374ca969b49173ca0fecc140d0b Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Mon, 13 Jul 2009 14:47:43 -0700 Subject: [PATCH 47/61] Added tag jdk7-b64 for changeset 9bd8eb50ad5a --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 48104000603..3645edaf091 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -38,3 +38,4 @@ f64566bf4c2bc92e65ab2b9fab51b119f0d493d1 jdk7-b59 aeabf802f2a1ca72b87d7397c5ece58058e000a9 jdk7-b61 75c801c13ea1ddebc58b1a8c8da9318d72750e62 jdk7-b62 b8a6e883c0a6708f6d818815040525d472262495 jdk7-b63 +aaa25dfd3de68c6f1a1d3ef8c45fd99f76bca6dd jdk7-b64 From 5c5306394203e0e4ad9d6a338e193e1fdc1dca94 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Mon, 13 Jul 2009 14:47:51 -0700 Subject: [PATCH 48/61] Added tag jdk7-b64 for changeset 2bd0e908f480 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 78053b178ae..4b9e6d23082 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -38,3 +38,4 @@ d5a1223e961891564de25c39fba6f2442d0fb045 jdk7-b57 f72c0dc047b9b2e797beee68ae0b50decb1f020d jdk7-b61 12e11fab9a839a9666a996a8f9a02fd8fa03aab6 jdk7-b62 2ed6ed6b5bfc7dd724925b90dbb31223df59c25d jdk7-b63 +a50217eb3ee10b9f9547e0708e5c9625405083ef jdk7-b64 From d42a7a68182e4684f8350d85f03bd3da765b5a9c Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Mon, 13 Jul 2009 14:48:01 -0700 Subject: [PATCH 49/61] Added tag jdk7-b64 for changeset 186b38713174 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index ef64c5e5ca5..0bb6612a24f 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -38,3 +38,4 @@ dbdeb4a7581b2a8699644b91cae6793cb01953f7 jdk7-b53 522520757dd34321b27a7145ecbd24ac4fb64f34 jdk7-b61 6855e5aa3348f185fe5b443ee43a1b00ec5d390e jdk7-b62 5c2c8112055565b4980b6756e001e45eb7b88d6e jdk7-b63 +d8f23a81d46f47a4186f1044dd9e44841bbeab84 jdk7-b64 From fa45d4b2e5bfebd0d1b42e29d599cd7b6fe6abb1 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Mon, 13 Jul 2009 15:14:17 -0700 Subject: [PATCH 50/61] 6832540: IllegalArgumentException in ClassLoader.definePackage when classes are loaded in parallel Modified to handle race condition for parallel-capable classloaders by re-trying/re-verifying package Reviewed-by: alanb --- .../classes/java/net/URLClassLoader.java | 64 ++++++++++++------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java index 601601a5652..22be20b7ecd 100644 --- a/jdk/src/share/classes/java/net/URLClassLoader.java +++ b/jdk/src/share/classes/java/net/URLClassLoader.java @@ -305,6 +305,35 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { } } + /* + * Retrieve the package using the specified package name. + * If non-null, verify the package using the specified code + * source and manifest. + */ + private Package getAndVerifyPackage(String pkgname, + Manifest man, URL url) { + Package pkg = getPackage(pkgname); + if (pkg != null) { + // Package found, so check package sealing. + if (pkg.isSealed()) { + // Verify that code source URL is the same. + if (!pkg.isSealed(url)) { + throw new SecurityException( + "sealing violation: package " + pkgname + " is sealed"); + } + } else { + // Make sure we are not attempting to seal the package + // at this code source URL. + if ((man != null) && isSealed(pkgname, man)) { + throw new SecurityException( + "sealing violation: can't seal package " + pkgname + + ": already loaded"); + } + } + } + return pkg; + } + /* * Defines a Class using the class bytes obtained from the specified * Resource. The resulting Class must be resolved before it can be @@ -316,32 +345,23 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { if (i != -1) { String pkgname = name.substring(0, i); // Check if package already loaded. - Package pkg = getPackage(pkgname); Manifest man = res.getManifest(); - if (pkg != null) { - // Package found, so check package sealing. - if (pkg.isSealed()) { - // Verify that code source URL is the same. - if (!pkg.isSealed(url)) { - throw new SecurityException( - "sealing violation: package " + pkgname + " is sealed"); + if (getAndVerifyPackage(pkgname, man, url) == null) { + try { + if (man != null) { + definePackage(pkgname, man, url); + } else { + definePackage(pkgname, null, null, null, null, null, null, null); } - - } else { - // Make sure we are not attempting to seal the package - // at this code source URL. - if ((man != null) && isSealed(pkgname, man)) { - throw new SecurityException( - "sealing violation: can't seal package " + pkgname + - ": already loaded"); + } catch (IllegalArgumentException iae) { + // parallel-capable class loaders: re-verify in case of a + // race condition + if (getAndVerifyPackage(pkgname, man, url) == null) { + // Should never happen + throw new AssertionError("Cannot find package " + + pkgname); } } - } else { - if (man != null) { - definePackage(pkgname, man, url); - } else { - definePackage(pkgname, null, null, null, null, null, null, null); - } } } // Now read the class bytes and define the class From 565f4998b5bedcac70e93aa7a893c1baac8bff03 Mon Sep 17 00:00:00 2001 From: Anthony Petrov Date: Tue, 14 Jul 2009 14:08:47 +0400 Subject: [PATCH 51/61] 6837446: Introduce Window.isOpaque() method Reviewed-by: art, alexp --- .../classes/com/sun/awt/AWTUtilities.java | 2 +- jdk/src/share/classes/java/awt/Component.java | 6 ++-- .../classes/java/awt/GraphicsDevice.java | 4 +-- jdk/src/share/classes/java/awt/Window.java | 30 ++++++++++++++----- .../javax/swing/DefaultDesktopManager.java | 2 +- .../classes/javax/swing/RepaintManager.java | 6 ++-- .../share/classes/sun/awt/AWTAccessor.java | 5 ---- jdk/src/share/classes/sun/awt/SunToolkit.java | 3 +- .../classes/sun/awt/windows/WWindowPeer.java | 3 +- 9 files changed, 34 insertions(+), 27 deletions(-) diff --git a/jdk/src/share/classes/com/sun/awt/AWTUtilities.java b/jdk/src/share/classes/com/sun/awt/AWTUtilities.java index bf0628b4712..6dd292c865e 100644 --- a/jdk/src/share/classes/com/sun/awt/AWTUtilities.java +++ b/jdk/src/share/classes/com/sun/awt/AWTUtilities.java @@ -374,7 +374,7 @@ public final class AWTUtilities { "The window argument should not be null."); } - return AWTAccessor.getWindowAccessor().isOpaque(window); + return window.isOpaque(); } /** diff --git a/jdk/src/share/classes/java/awt/Component.java b/jdk/src/share/classes/java/awt/Component.java index e07fbe7c5c7..91347ad1b18 100644 --- a/jdk/src/share/classes/java/awt/Component.java +++ b/jdk/src/share/classes/java/awt/Component.java @@ -2370,12 +2370,10 @@ public abstract class Component implements ImageObserver, MenuContainer, * rectangular region. A non-opaque component paints only some of * its pixels, allowing the pixels underneath it to "show through". * A component that does not fully paint its pixels therefore - * provides a degree of transparency. Only lightweight - * components can be transparent. + * provides a degree of transparency. *

    * Subclasses that guarantee to always completely paint their - * contents should override this method and return true. All - * of the "heavyweight" AWT components are opaque. + * contents should override this method and return true. * * @return true if this component is completely opaque * @see #isLightweight diff --git a/jdk/src/share/classes/java/awt/GraphicsDevice.java b/jdk/src/share/classes/java/awt/GraphicsDevice.java index 3ad45e223aa..58061c6bc66 100644 --- a/jdk/src/share/classes/java/awt/GraphicsDevice.java +++ b/jdk/src/share/classes/java/awt/GraphicsDevice.java @@ -281,8 +281,8 @@ public abstract class GraphicsDevice { if (w.getOpacity() < 1.0f) { w.setOpacity(1.0f); } - Color bgColor = w.getBackground(); - if ((bgColor != null) && (bgColor.getAlpha() < 255)) { + if (!w.isOpaque()) { + Color bgColor = w.getBackground(); bgColor = new Color(bgColor.getRed(), bgColor.getGreen(), bgColor.getBlue(), 255); w.setBackground(bgColor); diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index 31c94ca77e5..b419c437c9e 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -3521,6 +3521,7 @@ public class Window extends Container implements Accessible { * @return this component's background color * * @see Window#setBackground + * @see Window#isOpaque * @see GraphicsDevice.WindowTranslucency */ @Override @@ -3583,6 +3584,7 @@ public class Window extends Container implements Accessible { * PERPIXEL_TRANSLUCENT} translucency is not supported * * @see Window#getBackground + * @see Window#isOpaque * @see Window#setOpacity() * @see Window#setShape() * @see GraphicsDevice.WindowTranslucency @@ -3623,6 +3625,25 @@ public class Window extends Container implements Accessible { } } + /** + * Indicates if the window is currently opaque. + *

    + * The method returns {@code false} if the background color of the window + * is not {@code null} and the alpha component of the color is less than + * 1.0f. The method returns {@code true} otherwise. + * + * @return {@code true} if the window is opaque, {@code false} otherwise + * + * @see Window#getBackground + * @see Window#setBackground + * @since 1.7 + */ + @Override + public boolean isOpaque() { + Color bg = getBackground(); + return bg != null ? bg.getAlpha() == 255 : true; + } + private void updateWindow() { synchronized (getTreeLock()) { WindowPeer peer = (WindowPeer)getPeer(); @@ -3639,12 +3660,11 @@ public class Window extends Container implements Accessible { */ @Override public void paint(Graphics g) { - Color bgColor = getBackground(); - if ((bgColor != null) && (bgColor.getAlpha() < 255)) { + if (!isOpaque()) { Graphics gg = g.create(); try { if (gg instanceof Graphics2D) { - gg.setColor(bgColor); + gg.setColor(getBackground()); ((Graphics2D)gg).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); gg.fillRect(0, 0, getWidth(), getHeight()); } @@ -3749,10 +3769,6 @@ public class Window extends Container implements Accessible { public void setShape(Window window, Shape shape) { window.setShape(shape); } - public boolean isOpaque(Window window) { - Color bg = window.getBackground(); - return (bg != null) ? bg.getAlpha() == 255 : true; - } public void setOpaque(Window window, boolean opaque) { Color bg = window.getBackground(); if (bg == null) { diff --git a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java index 4bf7da1ca23..fc7977df641 100644 --- a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java +++ b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java @@ -708,7 +708,7 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab // update window if it's non-opaque Window topLevel = SwingUtilities.getWindowAncestor(f); Toolkit tk = Toolkit.getDefaultToolkit(); - if (!AWTAccessor.getWindowAccessor().isOpaque(topLevel) && + if (!topLevel.isOpaque() && (tk instanceof SunToolkit) && ((SunToolkit)tk).needUpdateWindow()) { diff --git a/jdk/src/share/classes/javax/swing/RepaintManager.java b/jdk/src/share/classes/javax/swing/RepaintManager.java index 618288bd3a0..a988b99fbd3 100644 --- a/jdk/src/share/classes/javax/swing/RepaintManager.java +++ b/jdk/src/share/classes/javax/swing/RepaintManager.java @@ -732,7 +732,7 @@ public class RepaintManager (Window)dirty : SwingUtilities.getWindowAncestor(dirty); if (window != null && - !AWTAccessor.getWindowAccessor().isOpaque(window)) + !window.isOpaque()) { windows.add(window); } @@ -996,7 +996,7 @@ public class RepaintManager // If the window is non-opaque, it's double-buffered at peer's level Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c); - if (!AWTAccessor.getWindowAccessor().isOpaque(w)) { + if (!w.isOpaque()) { Toolkit tk = Toolkit.getDefaultToolkit(); if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) { return null; @@ -1032,7 +1032,7 @@ public class RepaintManager // If the window is non-opaque, it's double-buffered at peer's level Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c); - if (!AWTAccessor.getWindowAccessor().isOpaque(w)) { + if (!w.isOpaque()) { Toolkit tk = Toolkit.getDefaultToolkit(); if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) { return null; diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java index e427b892517..c8bbc860877 100644 --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -136,11 +136,6 @@ public final class AWTAccessor { * Set a shape to the given window. */ void setShape(Window window, Shape shape); - /* - * Identify whether the given window is opaque (true) - * or translucent (false). - */ - boolean isOpaque(Window window); /* * Set the opaque preoperty to the given window. */ diff --git a/jdk/src/share/classes/sun/awt/SunToolkit.java b/jdk/src/share/classes/sun/awt/SunToolkit.java index 7f0ac590fa0..b4dd06a445c 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -1985,8 +1985,7 @@ public abstract class SunToolkit extends Toolkit */ public static boolean isContainingTopLevelOpaque(Component c) { Window w = getContainingWindow(c); - return w != null && ((Window)w).getBackground() != null && - ((Window)w).getBackground().getAlpha() == 255; + return w != null && w.isOpaque(); } /** diff --git a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java index 165acac4e93..fbb7442ba7d 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java @@ -194,8 +194,7 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, // default value of a boolean field is 'false', so set isOpaque to // true here explicitly this.isOpaque = true; - Color bgColor = ((Window)target).getBackground(); - setOpaque((bgColor == null) || (bgColor.getAlpha() == 255)); + setOpaque(((Window)target).isOpaque()); } } From addbc1de711aff94b0e991d667fc76c0e2f7f4bf Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 16 Jul 2009 10:53:04 -0700 Subject: [PATCH 52/61] Added tag jdk7-b65 for changeset f5311292903a --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 6b4351ee95a..3b501dece9d 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -39,3 +39,4 @@ ffd09e767dfa6d21466183a400f72cf62d53297f jdk7-b57 c7ed15ab92ce36a09d264a5e34025884b2d7607f jdk7-b62 57f7e028c7ad1806500ae89eb3f4cd9a51b10e18 jdk7-b63 269c1ec4435dfb7b452ae6e3bdde005d55c5c830 jdk7-b64 +e01380cd1de4ce048b87d059d238e5ab5e341947 jdk7-b65 From a9c0cc5110763a4dcc5e80a5c2195df55d48a607 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 16 Jul 2009 10:53:05 -0700 Subject: [PATCH 53/61] Added tag jdk7-b65 for changeset 2ad3a445ce89 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 0bb9b5fe667..e9712d235d3 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -39,3 +39,4 @@ e906b16a12a9a63b615898afa5d9673cbd1c5ab8 jdk7-b61 65b66117dbd70a493e9644aeb4033cf95a4e3c99 jdk7-b62 d20e45cd539f20405ff843652069cfd7550c5ab3 jdk7-b63 047dd27fddb607f8135296b3754131f6e13cb8c7 jdk7-b64 +97fd9b42f5c2d342b90d18f0a2b57e4117e39415 jdk7-b65 From 7edbc2373cfc3e23c8c4bc07c2ff70a2ecf59120 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 16 Jul 2009 10:53:09 -0700 Subject: [PATCH 54/61] Added tag jdk7-b65 for changeset 60611616dba4 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 0e026969a54..82f00b1c160 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -39,3 +39,4 @@ a77eddcd510c3972717c025cfcef9a60bfa4ecac jdk7-b60 a88386380bdaaa5ab4ffbedf22c57bac5dbec034 jdk7-b62 32c83fb84370a35344676991a48440378e6b6c8a jdk7-b63 ba36394eb84b949b31212bdb32a518a8f92bab5b jdk7-b64 +ba313800759b678979434d6da8ed3bf49eb8bea4 jdk7-b65 From 9b9bfcc5ffaabc7882708099e820a9e471eea70c Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 16 Jul 2009 10:53:13 -0700 Subject: [PATCH 55/61] Added tag jdk7-b65 for changeset 98a2177833c8 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 67a0b9e2e17..2713e5f9d70 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -39,3 +39,4 @@ f1ac756616eaaad795f77f7f5e7f7c7bfdc9c1de jdk7-b61 a97dd57a62604c35c79bc2fa77a612ed547f6135 jdk7-b62 ae449e9c04c1fe651bd30f0f4d4cc24ba794e0c4 jdk7-b63 a10eec7a1edf536f39b5828d8623054dbc62c2b7 jdk7-b64 +008c662e0ee9a91aebb75e46b97de979083d5c1c jdk7-b65 From 9243a3226550d0fa07b0cc0f4efdc7954bddcb40 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 16 Jul 2009 10:53:15 -0700 Subject: [PATCH 56/61] Added tag jdk7-b65 for changeset 83ac5deac923 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 3645edaf091..d85a9e3d5f0 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -39,3 +39,4 @@ aeabf802f2a1ca72b87d7397c5ece58058e000a9 jdk7-b61 75c801c13ea1ddebc58b1a8c8da9318d72750e62 jdk7-b62 b8a6e883c0a6708f6d818815040525d472262495 jdk7-b63 aaa25dfd3de68c6f1a1d3ef8c45fd99f76bca6dd jdk7-b64 +aa22a1be5866a6608ba17a7a443945559409ae0f jdk7-b65 From 27e3d0608ddf5ecccbd79150108bd2835b1cc22c Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 16 Jul 2009 10:53:21 -0700 Subject: [PATCH 57/61] Added tag jdk7-b65 for changeset 6d887683b2b4 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 4b9e6d23082..b1cc226d467 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -39,3 +39,4 @@ f72c0dc047b9b2e797beee68ae0b50decb1f020d jdk7-b61 12e11fab9a839a9666a996a8f9a02fd8fa03aab6 jdk7-b62 2ed6ed6b5bfc7dd724925b90dbb31223df59c25d jdk7-b63 a50217eb3ee10b9f9547e0708e5c9625405083ef jdk7-b64 +382a27aa78d3236fa123c60577797a887fe93e09 jdk7-b65 From c524fb1e6646bf3c3ee29feedff066a9fbe2bc22 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 16 Jul 2009 10:53:31 -0700 Subject: [PATCH 58/61] Added tag jdk7-b65 for changeset dde9c43422cd --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 0bb6612a24f..4d03a266a98 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -39,3 +39,4 @@ dbdeb4a7581b2a8699644b91cae6793cb01953f7 jdk7-b53 6855e5aa3348f185fe5b443ee43a1b00ec5d390e jdk7-b62 5c2c8112055565b4980b6756e001e45eb7b88d6e jdk7-b63 d8f23a81d46f47a4186f1044dd9e44841bbeab84 jdk7-b64 +7e0056ded28c802609d2bd79bfcda551d72a3fec jdk7-b65 From 7e2e64f5e04200db27fd2aa44fd00e3274332917 Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Thu, 23 Jul 2009 11:30:49 +0400 Subject: [PATCH 59/61] 6857870: Regression tests are failing with ExceptionInInitializerError Reviewed-by: art --- .../windows/classes/sun/awt/windows/WToolkit.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java index 6e12209f94c..9fcf3d67a8b 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java +++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java @@ -886,14 +886,12 @@ public class WToolkit extends SunToolkit implements Runnable { * this should be done in lazilyLoadDesktopProperty() only. */ protected synchronized void initializeDesktopProperties() { - desktopProperties.put("DnD.Autoscroll.initialDelay", Integer.valueOf(50)); - desktopProperties.put("DnD.Autoscroll.interval", Integer.valueOf(50)); - - try { - desktopProperties.put("Shell.shellFolderManager", - Class.forName("sun.awt.shell.Win32ShellFolderManager2")); - } catch (ClassNotFoundException ex) { - } + desktopProperties.put("DnD.Autoscroll.initialDelay", + Integer.valueOf(50)); + desktopProperties.put("DnD.Autoscroll.interval", + Integer.valueOf(50)); + desktopProperties.put("Shell.shellFolderManager", + "sun.awt.shell.Win32ShellFolderManager2"); } /* From ccf664b5ccc3807d91e234e3c408feffe043df31 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 16:56:12 +0200 Subject: [PATCH 60/61] Added tag jdk7-b64 for changeset d22867c5f1b2 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 08f9af77ccf..114e5a414c1 100644 --- a/.hgtags +++ b/.hgtags @@ -38,3 +38,4 @@ c33e7d38c9210741dbc285507403a4b20bd802a0 jdk7-b59 dbb955b1ee59b876dd1f133952b557b48b1d7732 jdk7-b61 6107cbff3130c747d243c25a7874cd59db5744a8 jdk7-b62 dfd8506f74c3731bb169ce93c72612d78ee0413b jdk7-b63 +d22867c5f1b295a0a2b3b4bc8999a2676f6e20c3 jdk7-b64 From bf4de55659afa8e0831f7ceca04ade4fad85857e Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 16:56:36 +0200 Subject: [PATCH 61/61] Added tag jdk7-b65 for changeset 7d3bf00f3cc4 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 114e5a414c1..0ecff5481bc 100644 --- a/.hgtags +++ b/.hgtags @@ -39,3 +39,4 @@ dbb955b1ee59b876dd1f133952b557b48b1d7732 jdk7-b61 6107cbff3130c747d243c25a7874cd59db5744a8 jdk7-b62 dfd8506f74c3731bb169ce93c72612d78ee0413b jdk7-b63 d22867c5f1b295a0a2b3b4bc8999a2676f6e20c3 jdk7-b64 +7d3bf00f3cc4f8125de1842521e7567f37dc84b8 jdk7-b65