From c2f449057d41476dc2c73c4a36486d58b9d0338e Mon Sep 17 00:00:00 2001 From: dfuchs Date: Mon, 1 Dec 2014 21:02:21 +0100 Subject: 8065552: setAccessible(true) on fields of Class may throw a SecurityException Summary: This fix hides the new private Class.classLoader field from reflection, rather than making it not accessible. Reviewed-by: mchung, coffeys --- src/share/classes/java/lang/Class.java | 2 ++ src/share/classes/java/lang/reflect/AccessibleObject.java | 7 ------- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'src/share/classes/java/lang') diff --git a/src/share/classes/java/lang/Class.java b/src/share/classes/java/lang/Class.java index 43c8c0e8ec..4c35cbce11 100644 --- a/src/share/classes/java/lang/Class.java +++ b/src/share/classes/java/lang/Class.java @@ -689,6 +689,8 @@ public final class Class implements java.io.Serializable, ClassLoader getClassLoader0() { return classLoader; } // Initialized in JVM not by private constructor + // This field is filtered from reflection access, i.e. getDeclaredField + // will throw NoSuchFieldException private final ClassLoader classLoader; /** diff --git a/src/share/classes/java/lang/reflect/AccessibleObject.java b/src/share/classes/java/lang/reflect/AccessibleObject.java index 0bf5e0eea4..45e051c454 100644 --- a/src/share/classes/java/lang/reflect/AccessibleObject.java +++ b/src/share/classes/java/lang/reflect/AccessibleObject.java @@ -140,13 +140,6 @@ public class AccessibleObject implements AnnotatedElement { throw new SecurityException("Cannot make a java.lang.Class" + " constructor accessible"); } - } else if (obj instanceof Field && flag == true) { - Field f = (Field)obj; - if (f.getDeclaringClass() == Class.class && - f.getName().equals("classLoader")) { - throw new SecurityException("Cannot make java.lang.Class.classLoader" + - " accessible"); - } } obj.override = flag; } -- cgit v1.2.3 From 7de033a6bb9700635d96d21c447f90a8df95cb18 Mon Sep 17 00:00:00 2001 From: mchung Date: Thu, 4 Dec 2014 19:03:29 -0800 Subject: 8065702: Deprecate the Extension Mechanism Reviewed-by: alanb, iris --- src/share/classes/java/lang/System.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/share/classes/java/lang') diff --git a/src/share/classes/java/lang/System.java b/src/share/classes/java/lang/System.java index 69d1d0fe1e..b2747fa7a4 100644 --- a/src/share/classes/java/lang/System.java +++ b/src/share/classes/java/lang/System.java @@ -584,7 +584,10 @@ public final class System { * java.compiler * Name of JIT compiler to use * java.ext.dirs - * Path of extension directory or directories + * Path of extension directory or directories + * Deprecated. This property, and the mechanism + * which implements it, may be removed in a future + * release. * os.name * Operating system name * os.arch -- cgit v1.2.3 From e7a2ea5c80d41ffb1e135e0c1ec442f750de3590 Mon Sep 17 00:00:00 2001 From: vlivanov Date: Thu, 4 Dec 2014 07:15:37 -0800 Subject: 8057020: LambdaForm caches should support eviction Reviewed-by: psandoz, jrose, shade --- src/share/classes/java/lang/invoke/LambdaForm.java | 2 +- .../classes/java/lang/invoke/LambdaFormBuffer.java | 15 +++---- .../classes/java/lang/invoke/LambdaFormEditor.java | 52 +++++++++++++++++----- .../classes/java/lang/invoke/MethodTypeForm.java | 43 +++++++++++------- 4 files changed, 76 insertions(+), 36 deletions(-) (limited to 'src/share/classes/java/lang') diff --git a/src/share/classes/java/lang/invoke/LambdaForm.java b/src/share/classes/java/lang/invoke/LambdaForm.java index e1791719c0..2129f8618b 100644 --- a/src/share/classes/java/lang/invoke/LambdaForm.java +++ b/src/share/classes/java/lang/invoke/LambdaForm.java @@ -125,7 +125,7 @@ class LambdaForm { MemberName vmentry; // low-level behavior, or null if not yet prepared private boolean isCompiled; - Object transformCache; // managed by LambdaFormEditor + volatile Object transformCache; // managed by LambdaFormEditor public static final int VOID_RESULT = -1, LAST_RESULT = -2; diff --git a/src/share/classes/java/lang/invoke/LambdaFormBuffer.java b/src/share/classes/java/lang/invoke/LambdaFormBuffer.java index 872a2a5992..cdc88be325 100644 --- a/src/share/classes/java/lang/invoke/LambdaFormBuffer.java +++ b/src/share/classes/java/lang/invoke/LambdaFormBuffer.java @@ -46,19 +46,16 @@ final class LambdaFormBuffer { private static final int F_TRANS = 0x10, F_OWNED = 0x03; LambdaFormBuffer(LambdaForm lf) { - this(lf.arity, lf.names, lf.result); + this.arity = lf.arity; + setNames(lf.names); + int result = lf.result; + if (result == LAST_RESULT) result = length - 1; + if (result >= 0 && lf.names[result].type != V_TYPE) + resultName = lf.names[result]; debugName = lf.debugName; assert(lf.nameRefsAreLegal()); } - private LambdaFormBuffer(int arity, Name[] names, int result) { - this.arity = arity; - setNames(names); - if (result == LAST_RESULT) result = length - 1; - if (result >= 0 && names[result].type != V_TYPE) - resultName = names[result]; - } - private LambdaForm lambdaForm() { assert(!inTrans()); // need endEdit call to tidy things up return new LambdaForm(debugName, arity, nameArray(), resultIndex()); diff --git a/src/share/classes/java/lang/invoke/LambdaFormEditor.java b/src/share/classes/java/lang/invoke/LambdaFormEditor.java index 1c29d73b4c..1c23e94995 100644 --- a/src/share/classes/java/lang/invoke/LambdaFormEditor.java +++ b/src/share/classes/java/lang/invoke/LambdaFormEditor.java @@ -25,6 +25,7 @@ package java.lang.invoke; +import java.lang.ref.SoftReference; import java.util.Arrays; import static java.lang.invoke.LambdaForm.*; import static java.lang.invoke.LambdaForm.BasicType.*; @@ -58,10 +59,9 @@ class LambdaFormEditor { * The sequence is unterminated, ending with an indefinite number of zero bytes. * Sequences that are simple (short enough and with small enough values) pack into a 64-bit long. */ - private static final class Transform { + private static final class Transform extends SoftReference { final long packedBytes; final byte[] fullBytes; - final LambdaForm result; // result of transform, or null, if there is none available private enum Kind { NO_KIND, // necessary because ordinal must be greater than zero @@ -140,9 +140,9 @@ class LambdaFormEditor { Kind kind() { return Kind.values()[byteAt(0)]; } private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) { + super(result); this.packedBytes = packedBytes; this.fullBytes = fullBytes; - this.result = result; } private Transform(long packedBytes) { this(packedBytes, null, null); @@ -243,6 +243,7 @@ class LambdaFormEditor { buf.append("unpacked"); buf.append(Arrays.toString(fullBytes)); } + LambdaForm result = get(); if (result != null) { buf.append(" result="); buf.append(result); @@ -253,7 +254,7 @@ class LambdaFormEditor { /** Find a previously cached transform equivalent to the given one, and return its result. */ private LambdaForm getInCache(Transform key) { - assert(key.result == null); + assert(key.get() == null); // The transformCache is one of null, Transform, Transform[], or ConcurrentHashMap. Object c = lambdaForm.transformCache; Transform k = null; @@ -276,7 +277,7 @@ class LambdaFormEditor { } } assert(k == null || key.equals(k)); - return k == null ? null : k.result; + return (k != null) ? k.get() : null; } /** Arbitrary but reasonable limits on Transform[] size for cache. */ @@ -293,7 +294,17 @@ class LambdaFormEditor { @SuppressWarnings("unchecked") ConcurrentHashMap m = (ConcurrentHashMap) c; Transform k = m.putIfAbsent(key, key); - return k != null ? k.result : form; + if (k == null) return form; + LambdaForm result = k.get(); + if (result != null) { + return result; + } else { + if (m.replace(key, k, key)) { + return form; + } else { + continue; + } + } } assert(pass == 0); synchronized (lambdaForm) { @@ -308,17 +319,27 @@ class LambdaFormEditor { if (c instanceof Transform) { Transform k = (Transform)c; if (k.equals(key)) { - return k.result; + LambdaForm result = k.get(); + if (result == null) { + lambdaForm.transformCache = key; + return form; + } else { + return result; + } + } else if (k.get() == null) { // overwrite stale entry + lambdaForm.transformCache = key; + return form; } // expand one-element cache to small array ta = new Transform[MIN_CACHE_ARRAY_SIZE]; ta[0] = k; - lambdaForm.transformCache = c = ta; + lambdaForm.transformCache = ta; } else { // it is already expanded ta = (Transform[])c; } int len = ta.length; + int stale = -1; int i; for (i = 0; i < len; i++) { Transform k = ta[i]; @@ -326,10 +347,18 @@ class LambdaFormEditor { break; } if (k.equals(key)) { - return k.result; + LambdaForm result = k.get(); + if (result == null) { + ta[i] = key; + return form; + } else { + return result; + } + } else if (stale < 0 && k.get() == null) { + stale = i; // remember 1st stale entry index } } - if (i < len) { + if (i < len || stale >= 0) { // just fall through to cache update } else if (len < MAX_CACHE_ARRAY_SIZE) { len = Math.min(len * 2, MAX_CACHE_ARRAY_SIZE); @@ -344,7 +373,8 @@ class LambdaFormEditor { // The second iteration will update for this query, concurrently. continue; } - ta[i] = key; + int idx = (stale >= 0) ? stale : i; + ta[idx] = key; return form; } } diff --git a/src/share/classes/java/lang/invoke/MethodTypeForm.java b/src/share/classes/java/lang/invoke/MethodTypeForm.java index 6733e29ef9..bcf16dba9d 100644 --- a/src/share/classes/java/lang/invoke/MethodTypeForm.java +++ b/src/share/classes/java/lang/invoke/MethodTypeForm.java @@ -26,9 +26,8 @@ package java.lang.invoke; import sun.invoke.util.Wrapper; +import java.lang.ref.SoftReference; import static java.lang.invoke.MethodHandleStatics.*; -import static java.lang.invoke.MethodHandleNatives.Constants.*; - import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; /** * Shared information for a group of method types, which differ @@ -51,7 +50,7 @@ final class MethodTypeForm { final MethodType basicType; // the canonical erasure, with primitives simplified // Cached adapter information: - @Stable final MethodHandle[] methodHandles; + @Stable final SoftReference[] methodHandles; // Indexes into methodHandles: static final int MH_BASIC_INV = 0, // cached instance of MH.invokeBasic @@ -60,7 +59,7 @@ final class MethodTypeForm { MH_LIMIT = 3; // Cached lambda form information, for basic types only: - final @Stable LambdaForm[] lambdaForms; + final @Stable SoftReference[] lambdaForms; // Indexes into lambdaForms: static final int LF_INVVIRTUAL = 0, // DMH invokeVirtual @@ -108,26 +107,40 @@ final class MethodTypeForm { public MethodHandle cachedMethodHandle(int which) { assert(assertIsBasicType()); - return methodHandles[which]; + SoftReference entry = methodHandles[which]; + return (entry != null) ? entry.get() : null; } synchronized public MethodHandle setCachedMethodHandle(int which, MethodHandle mh) { // Simulate a CAS, to avoid racy duplication of results. - MethodHandle prev = methodHandles[which]; - if (prev != null) return prev; - return methodHandles[which] = mh; + SoftReference entry = methodHandles[which]; + if (entry != null) { + MethodHandle prev = entry.get(); + if (prev != null) { + return prev; + } + } + methodHandles[which] = new SoftReference<>(mh); + return mh; } public LambdaForm cachedLambdaForm(int which) { assert(assertIsBasicType()); - return lambdaForms[which]; + SoftReference entry = lambdaForms[which]; + return (entry != null) ? entry.get() : null; } synchronized public LambdaForm setCachedLambdaForm(int which, LambdaForm form) { // Simulate a CAS, to avoid racy duplication of results. - LambdaForm prev = lambdaForms[which]; - if (prev != null) return prev; - return lambdaForms[which] = form; + SoftReference entry = lambdaForms[which]; + if (entry != null) { + LambdaForm prev = entry.get(); + if (prev != null) { + return prev; + } + } + lambdaForms[which] = new SoftReference<>(form); + return form; } /** @@ -135,6 +148,7 @@ final class MethodTypeForm { * This MTF will stand for that type and all un-erased variations. * Eagerly compute some basic properties of the type, common to all variations. */ + @SuppressWarnings({"rawtypes", "unchecked"}) protected MethodTypeForm(MethodType erasedType) { this.erasedType = erasedType; @@ -234,8 +248,8 @@ final class MethodTypeForm { // Initialize caches, but only for basic types assert(basicType == erasedType); - this.lambdaForms = new LambdaForm[LF_LIMIT]; - this.methodHandles = new MethodHandle[MH_LIMIT]; + this.lambdaForms = new SoftReference[LF_LIMIT]; + this.methodHandles = new SoftReference[MH_LIMIT]; } private static long pack(int a, int b, int c, int d) { @@ -409,5 +423,4 @@ final class MethodTypeForm { public String toString() { return "Form"+erasedType; } - } -- cgit v1.2.3 From dbebd7497ff54fbba26fa03eaa8cda0418f24ea3 Mon Sep 17 00:00:00 2001 From: vlivanov Date: Tue, 9 Dec 2014 09:22:07 -0800 Subject: 8066746: MHs.explicitCastArguments does incorrect type checks for VarargsCollector Reviewed-by: jrose, psandoz --- src/share/classes/java/lang/invoke/MethodHandles.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/share/classes/java/lang') diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java index 3c60a8c3c9..8511890481 100644 --- a/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/share/classes/java/lang/invoke/MethodHandles.java @@ -2029,7 +2029,7 @@ return invoker; MethodType oldType = target.type(); if (oldType == newType) return target; if (oldType.explicitCastEquivalentToAsType(newType)) { - return target.asType(newType); + return target.asFixedArity().asType(newType); } return MethodHandleImpl.makePairwiseConvert(target, newType, false); } -- cgit v1.2.3