Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
35367e22
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
35367e22
编写于
11月 26, 2013
作者:
M
malenkov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8028054: com.sun.beans.finder.MethodFinder has unsynchronized access to a static Map
Reviewed-by: alexsch, serb
上级
21d2c743
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
965 addition
and
18 deletion
+965
-18
src/share/classes/com/sun/beans/finder/ConstructorFinder.java
...share/classes/com/sun/beans/finder/ConstructorFinder.java
+19
-8
src/share/classes/com/sun/beans/finder/MethodFinder.java
src/share/classes/com/sun/beans/finder/MethodFinder.java
+19
-10
src/share/classes/com/sun/beans/finder/Signature.java
src/share/classes/com/sun/beans/finder/Signature.java
+12
-0
src/share/classes/com/sun/beans/finder/SignatureException.java
...hare/classes/com/sun/beans/finder/SignatureException.java
+41
-0
src/share/classes/com/sun/beans/util/Cache.java
src/share/classes/com/sun/beans/util/Cache.java
+613
-0
test/java/beans/XMLDecoder/8028054/Task.java
test/java/beans/XMLDecoder/8028054/Task.java
+99
-0
test/java/beans/XMLDecoder/8028054/TestConstructorFinder.java
.../java/beans/XMLDecoder/8028054/TestConstructorFinder.java
+81
-0
test/java/beans/XMLDecoder/8028054/TestMethodFinder.java
test/java/beans/XMLDecoder/8028054/TestMethodFinder.java
+81
-0
未找到文件。
src/share/classes/com/sun/beans/finder/ConstructorFinder.java
浏览文件 @
35367e22
...
@@ -24,11 +24,12 @@
...
@@ -24,11 +24,12 @@
*/
*/
package
com.sun.beans.finder
;
package
com.sun.beans.finder
;
import
com.sun.beans.
Weak
Cache
;
import
com.sun.beans.
util.
Cache
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Modifier
;
import
java.lang.reflect.Modifier
;
import
static
com
.
sun
.
beans
.
util
.
Cache
.
Kind
.
SOFT
;
import
static
sun
.
reflect
.
misc
.
ReflectUtil
.
isPackageAccessible
;
import
static
sun
.
reflect
.
misc
.
ReflectUtil
.
isPackageAccessible
;
/**
/**
...
@@ -41,7 +42,18 @@ import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
...
@@ -41,7 +42,18 @@ import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
* @author Sergey A. Malenkov
* @author Sergey A. Malenkov
*/
*/
public
final
class
ConstructorFinder
extends
AbstractFinder
<
Constructor
<?>>
{
public
final
class
ConstructorFinder
extends
AbstractFinder
<
Constructor
<?>>
{
private
static
final
WeakCache
<
Signature
,
Constructor
<?>>
CACHE
=
new
WeakCache
<
Signature
,
Constructor
<?>>();
private
static
final
Cache
<
Signature
,
Constructor
<?>>
CACHE
=
new
Cache
<
Signature
,
Constructor
<?>>(
SOFT
,
SOFT
)
{
@Override
public
Constructor
create
(
Signature
signature
)
{
try
{
ConstructorFinder
finder
=
new
ConstructorFinder
(
signature
.
getArgs
());
return
finder
.
find
(
signature
.
getType
().
getConstructors
());
}
catch
(
Exception
exception
)
{
throw
new
SignatureException
(
exception
);
}
}
};
/**
/**
* Finds public constructor
* Finds public constructor
...
@@ -69,13 +81,12 @@ public final class ConstructorFinder extends AbstractFinder<Constructor<?>> {
...
@@ -69,13 +81,12 @@ public final class ConstructorFinder extends AbstractFinder<Constructor<?>> {
PrimitiveWrapperMap
.
replacePrimitivesWithWrappers
(
args
);
PrimitiveWrapperMap
.
replacePrimitivesWithWrappers
(
args
);
Signature
signature
=
new
Signature
(
type
,
args
);
Signature
signature
=
new
Signature
(
type
,
args
);
Constructor
<?>
constructor
=
CACHE
.
get
(
signature
);
try
{
if
(
constructor
!=
null
)
{
return
CACHE
.
get
(
signature
);
return
constructor
;
}
catch
(
SignatureException
exception
)
{
throw
exception
.
toNoSuchMethodException
(
"Constructor is not found"
);
}
}
constructor
=
new
ConstructorFinder
(
args
).
find
(
type
.
getConstructors
());
CACHE
.
put
(
signature
,
constructor
);
return
constructor
;
}
}
/**
/**
...
...
src/share/classes/com/sun/beans/finder/MethodFinder.java
浏览文件 @
35367e22
...
@@ -25,7 +25,7 @@
...
@@ -25,7 +25,7 @@
package
com.sun.beans.finder
;
package
com.sun.beans.finder
;
import
com.sun.beans.TypeResolver
;
import
com.sun.beans.TypeResolver
;
import
com.sun.beans.
Weak
Cache
;
import
com.sun.beans.
util.
Cache
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.lang.reflect.Modifier
;
...
@@ -33,6 +33,7 @@ import java.lang.reflect.ParameterizedType;
...
@@ -33,6 +33,7 @@ import java.lang.reflect.ParameterizedType;
import
java.lang.reflect.Type
;
import
java.lang.reflect.Type
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
static
com
.
sun
.
beans
.
util
.
Cache
.
Kind
.
SOFT
;
import
static
sun
.
reflect
.
misc
.
ReflectUtil
.
isPackageAccessible
;
import
static
sun
.
reflect
.
misc
.
ReflectUtil
.
isPackageAccessible
;
/**
/**
...
@@ -45,7 +46,18 @@ import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
...
@@ -45,7 +46,18 @@ import static sun.reflect.misc.ReflectUtil.isPackageAccessible;
* @author Sergey A. Malenkov
* @author Sergey A. Malenkov
*/
*/
public
final
class
MethodFinder
extends
AbstractFinder
<
Method
>
{
public
final
class
MethodFinder
extends
AbstractFinder
<
Method
>
{
private
static
final
WeakCache
<
Signature
,
Method
>
CACHE
=
new
WeakCache
<
Signature
,
Method
>();
private
static
final
Cache
<
Signature
,
Method
>
CACHE
=
new
Cache
<
Signature
,
Method
>(
SOFT
,
SOFT
)
{
@Override
public
Method
create
(
Signature
signature
)
{
try
{
MethodFinder
finder
=
new
MethodFinder
(
signature
.
getName
(),
signature
.
getArgs
());
return
findAccessibleMethod
(
finder
.
find
(
signature
.
getType
().
getMethods
()));
}
catch
(
Exception
exception
)
{
throw
new
SignatureException
(
exception
);
}
}
};
/**
/**
* Finds public method (static or non-static)
* Finds public method (static or non-static)
...
@@ -65,16 +77,13 @@ public final class MethodFinder extends AbstractFinder<Method> {
...
@@ -65,16 +77,13 @@ public final class MethodFinder extends AbstractFinder<Method> {
PrimitiveWrapperMap
.
replacePrimitivesWithWrappers
(
args
);
PrimitiveWrapperMap
.
replacePrimitivesWithWrappers
(
args
);
Signature
signature
=
new
Signature
(
type
,
name
,
args
);
Signature
signature
=
new
Signature
(
type
,
name
,
args
);
Method
method
=
CACHE
.
get
(
signature
);
try
{
boolean
cached
=
method
!=
null
;
Method
method
=
CACHE
.
get
(
signature
);
if
(
cached
&&
isPackageAccessible
(
method
.
getDeclaringClass
()))
{
return
(
method
==
null
)
||
isPackageAccessible
(
method
.
getDeclaringClass
())
?
method
:
CACHE
.
create
(
signature
);
return
method
;
}
}
method
=
findAccessibleMethod
(
new
MethodFinder
(
name
,
args
).
find
(
type
.
getMethods
()));
catch
(
SignatureException
exception
)
{
if
(!
cached
)
{
throw
exception
.
toNoSuchMethodException
(
"Method '"
+
name
+
"' is not found"
);
CACHE
.
put
(
signature
,
method
);
}
}
return
method
;
}
}
/**
/**
...
...
src/share/classes/com/sun/beans/finder/Signature.java
浏览文件 @
35367e22
...
@@ -62,6 +62,18 @@ final class Signature {
...
@@ -62,6 +62,18 @@ final class Signature {
this
.
args
=
args
;
this
.
args
=
args
;
}
}
Class
<?>
getType
()
{
return
this
.
type
;
}
String
getName
()
{
return
this
.
name
;
}
Class
<?>[]
getArgs
()
{
return
this
.
args
;
}
/**
/**
* Indicates whether some other object is "equal to" this one.
* Indicates whether some other object is "equal to" this one.
*
*
...
...
src/share/classes/com/sun/beans/finder/SignatureException.java
0 → 100644
浏览文件 @
35367e22
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
com.sun.beans.finder
;
final
class
SignatureException
extends
RuntimeException
{
SignatureException
(
Throwable
cause
)
{
super
(
cause
);
}
NoSuchMethodException
toNoSuchMethodException
(
String
message
)
{
Throwable
throwable
=
getCause
();
if
(
throwable
instanceof
NoSuchMethodException
)
{
return
(
NoSuchMethodException
)
throwable
;
}
NoSuchMethodException
exception
=
new
NoSuchMethodException
(
message
);
exception
.
initCause
(
throwable
);
return
exception
;
}
}
src/share/classes/com/sun/beans/util/Cache.java
0 → 100644
浏览文件 @
35367e22
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
com.sun.beans.util
;
import
java.lang.ref.ReferenceQueue
;
import
java.lang.ref.SoftReference
;
import
java.lang.ref.WeakReference
;
import
java.util.Objects
;
/**
* Hash table based implementation of the cache,
* which allows to use weak or soft references for keys and values.
* An entry in a {@code Cache} will automatically be removed
* when its key or value is no longer in ordinary use.
*
* @author Sergey Malenkov
* @since 1.8
*/
public
abstract
class
Cache
<
K
,
V
>
{
private
static
final
int
MAXIMUM_CAPACITY
=
1
<<
30
;
// maximum capacity MUST be a power of two <= 1<<30
private
final
boolean
identity
;
// defines whether the identity comparison is used
private
final
Kind
keyKind
;
// a reference kind for the cache keys
private
final
Kind
valueKind
;
// a reference kind for the cache values
private
final
ReferenceQueue
<
Object
>
queue
=
new
ReferenceQueue
<>();
// queue for references to remove
private
volatile
CacheEntry
<
K
,
V
>[]
table
=
newTable
(
1
<<
3
);
// table's length MUST be a power of two
private
int
threshold
=
6
;
// the next size value at which to resize
private
int
size
;
// the number of key-value mappings contained in this map
/**
* Creates a corresponding value for the specified key.
*
* @param key a key that can be used to create a value
* @return a corresponding value for the specified key
*/
public
abstract
V
create
(
K
key
);
/**
* Constructs an empty {@code Cache}.
* The default initial capacity is 8.
* The default load factor is 0.75.
*
* @param keyKind a reference kind for keys
* @param valueKind a reference kind for values
*
* @throws NullPointerException if {@code keyKind} or {@code valueKind} are {@code null}
*/
public
Cache
(
Kind
keyKind
,
Kind
valueKind
)
{
this
(
keyKind
,
valueKind
,
false
);
}
/**
* Constructs an empty {@code Cache}
* with the specified comparison method.
* The default initial capacity is 8.
* The default load factor is 0.75.
*
* @param keyKind a reference kind for keys
* @param valueKind a reference kind for values
* @param identity defines whether reference-equality
* is used in place of object-equality
*
* @throws NullPointerException if {@code keyKind} or {@code valueKind} are {@code null}
*/
public
Cache
(
Kind
keyKind
,
Kind
valueKind
,
boolean
identity
)
{
Objects
.
requireNonNull
(
keyKind
,
"keyKind"
);
Objects
.
requireNonNull
(
valueKind
,
"valueKind"
);
this
.
keyKind
=
keyKind
;
this
.
valueKind
=
valueKind
;
this
.
identity
=
identity
;
}
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if there is no mapping for the key.
*
* @param key the key whose cached value is to be returned
* @return a value to which the specified key is mapped,
* or {@code null} if there is no mapping for {@code key}
*
* @throws NullPointerException if {@code key} is {@code null}
* or corresponding value is {@code null}
*/
public
final
V
get
(
K
key
)
{
Objects
.
requireNonNull
(
key
,
"key"
);
removeStaleEntries
();
int
hash
=
hash
(
key
);
// unsynchronized search improves performance
// the null value does not mean that there are no needed entry
CacheEntry
<
K
,
V
>[]
table
=
this
.
table
;
// unsynchronized access
V
current
=
getEntryValue
(
key
,
hash
,
table
[
index
(
hash
,
table
)]);
if
(
current
!=
null
)
{
return
current
;
}
synchronized
(
this
.
queue
)
{
// synchronized search improves stability
// we must create and add new value if there are no needed entry
int
index
=
index
(
hash
,
this
.
table
);
current
=
getEntryValue
(
key
,
hash
,
this
.
table
[
index
]);
if
(
current
!=
null
)
{
return
current
;
}
V
value
=
create
(
key
);
Objects
.
requireNonNull
(
value
,
"value"
);
this
.
table
[
index
]
=
new
CacheEntry
<>(
hash
,
key
,
value
,
this
.
table
[
index
]);
if
(++
this
.
size
>=
this
.
threshold
)
{
if
(
this
.
table
.
length
==
MAXIMUM_CAPACITY
)
{
this
.
threshold
=
Integer
.
MAX_VALUE
;
}
else
{
removeStaleEntries
();
table
=
newTable
(
this
.
table
.
length
<<
1
);
transfer
(
this
.
table
,
table
);
// If ignoring null elements and processing ref queue caused massive
// shrinkage, then restore old table. This should be rare, but avoids
// unbounded expansion of garbage-filled tables.
if
(
this
.
size
>=
this
.
threshold
/
2
)
{
this
.
table
=
table
;
this
.
threshold
<<=
1
;
}
else
{
transfer
(
table
,
this
.
table
);
}
removeStaleEntries
();
}
}
return
value
;
}
}
/**
* Removes the cached value that corresponds to the specified key.
*
* @param key the key whose mapping is to be removed from this cache
*/
public
final
void
remove
(
K
key
)
{
if
(
key
!=
null
)
{
synchronized
(
this
.
queue
)
{
removeStaleEntries
();
int
hash
=
hash
(
key
);
int
index
=
index
(
hash
,
this
.
table
);
CacheEntry
<
K
,
V
>
prev
=
this
.
table
[
index
];
CacheEntry
<
K
,
V
>
entry
=
prev
;
while
(
entry
!=
null
)
{
CacheEntry
<
K
,
V
>
next
=
entry
.
next
;
if
(
entry
.
matches
(
hash
,
key
))
{
if
(
entry
==
prev
)
{
this
.
table
[
index
]
=
next
;
}
else
{
prev
.
next
=
next
;
}
entry
.
unlink
();
break
;
}
prev
=
entry
;
entry
=
next
;
}
}
}
}
/**
* Removes all of the mappings from this cache.
* It will be empty after this call returns.
*/
public
final
void
clear
()
{
synchronized
(
this
.
queue
)
{
int
index
=
this
.
table
.
length
;
while
(
0
<
index
--)
{
CacheEntry
<
K
,
V
>
entry
=
this
.
table
[
index
];
while
(
entry
!=
null
)
{
CacheEntry
<
K
,
V
>
next
=
entry
.
next
;
entry
.
unlink
();
entry
=
next
;
}
this
.
table
[
index
]
=
null
;
}
while
(
null
!=
this
.
queue
.
poll
())
{
// Clear out the reference queue.
}
}
}
/**
* Retrieves object hash code and applies a supplemental hash function
* to the result hash, which defends against poor quality hash functions.
* This is critical because {@code Cache} uses power-of-two length hash tables,
* that otherwise encounter collisions for hashCodes that do not differ
* in lower bits.
*
* @param key the object which hash code is to be calculated
* @return a hash code value for the specified object
*/
private
int
hash
(
Object
key
)
{
if
(
this
.
identity
)
{
int
hash
=
System
.
identityHashCode
(
key
);
return
(
hash
<<
1
)
-
(
hash
<<
8
);
}
int
hash
=
key
.
hashCode
();
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
hash
^=
(
hash
>>>
20
)
^
(
hash
>>>
12
);
return
hash
^
(
hash
>>>
7
)
^
(
hash
>>>
4
);
}
/**
* Returns index of the specified hash code in the given table.
* Note that the table size must be a power of two.
*
* @param hash the hash code
* @param table the table
* @return an index of the specified hash code in the given table
*/
private
static
int
index
(
int
hash
,
Object
[]
table
)
{
return
hash
&
(
table
.
length
-
1
);
}
/**
* Creates a new array for the cache entries.
*
* @param size requested capacity MUST be a power of two
* @return a new array for the cache entries
*/
@SuppressWarnings
(
"unchecked"
)
private
CacheEntry
<
K
,
V
>[]
newTable
(
int
size
)
{
return
(
CacheEntry
<
K
,
V
>[])
new
CacheEntry
[
size
];
}
private
V
getEntryValue
(
K
key
,
int
hash
,
CacheEntry
<
K
,
V
>
entry
)
{
while
(
entry
!=
null
)
{
if
(
entry
.
matches
(
hash
,
key
))
{
return
entry
.
value
.
getReferent
();
}
entry
=
entry
.
next
;
}
return
null
;
}
private
void
removeStaleEntries
()
{
Object
reference
=
this
.
queue
.
poll
();
if
(
reference
!=
null
)
{
synchronized
(
this
.
queue
)
{
do
{
if
(
reference
instanceof
Ref
)
{
Ref
ref
=
(
Ref
)
reference
;
@SuppressWarnings
(
"unchecked"
)
CacheEntry
<
K
,
V
>
owner
=
(
CacheEntry
<
K
,
V
>)
ref
.
getOwner
();
if
(
owner
!=
null
)
{
int
index
=
index
(
owner
.
hash
,
this
.
table
);
CacheEntry
<
K
,
V
>
prev
=
this
.
table
[
index
];
CacheEntry
<
K
,
V
>
entry
=
prev
;
while
(
entry
!=
null
)
{
CacheEntry
<
K
,
V
>
next
=
entry
.
next
;
if
(
entry
==
owner
)
{
if
(
entry
==
prev
)
{
this
.
table
[
index
]
=
next
;
}
else
{
prev
.
next
=
next
;
}
entry
.
unlink
();
break
;
}
prev
=
entry
;
entry
=
next
;
}
}
}
reference
=
this
.
queue
.
poll
();
}
while
(
reference
!=
null
);
}
}
}
private
void
transfer
(
CacheEntry
<
K
,
V
>[]
oldTable
,
CacheEntry
<
K
,
V
>[]
newTable
)
{
int
oldIndex
=
oldTable
.
length
;
while
(
0
<
oldIndex
--)
{
CacheEntry
<
K
,
V
>
entry
=
oldTable
[
oldIndex
];
oldTable
[
oldIndex
]
=
null
;
while
(
entry
!=
null
)
{
CacheEntry
<
K
,
V
>
next
=
entry
.
next
;
if
(
entry
.
key
.
isStale
()
||
entry
.
value
.
isStale
())
{
entry
.
unlink
();
}
else
{
int
newIndex
=
index
(
entry
.
hash
,
newTable
);
entry
.
next
=
newTable
[
newIndex
];
newTable
[
newIndex
]
=
entry
;
}
entry
=
next
;
}
}
}
/**
* Represents a cache entry (key-value pair).
*/
private
final
class
CacheEntry
<
K
,
V
>
{
private
final
int
hash
;
private
final
Ref
<
K
>
key
;
private
final
Ref
<
V
>
value
;
private
volatile
CacheEntry
<
K
,
V
>
next
;
/**
* Constructs an entry for the cache.
*
* @param hash the hash code calculated for the entry key
* @param key the entry key
* @param value the initial value of the entry
* @param next the next entry in a chain
*/
private
CacheEntry
(
int
hash
,
K
key
,
V
value
,
CacheEntry
<
K
,
V
>
next
)
{
this
.
hash
=
hash
;
this
.
key
=
Cache
.
this
.
keyKind
.
create
(
this
,
key
,
Cache
.
this
.
queue
);
this
.
value
=
Cache
.
this
.
valueKind
.
create
(
this
,
value
,
Cache
.
this
.
queue
);
this
.
next
=
next
;
}
/**
* Determines whether the entry has the given key with the given hash code.
*
* @param hash an expected hash code
* @param object an object to be compared with the entry key
* @return {@code true} if the entry has the given key with the given hash code;
* {@code false} otherwise
*/
private
boolean
matches
(
int
hash
,
Object
object
)
{
if
(
this
.
hash
!=
hash
)
{
return
false
;
}
Object
key
=
this
.
key
.
getReferent
();
return
(
key
==
object
)
||
!
Cache
.
this
.
identity
&&
(
key
!=
null
)
&&
key
.
equals
(
object
);
}
/**
* Marks the entry as actually removed from the cache.
*/
private
void
unlink
()
{
this
.
next
=
null
;
this
.
key
.
removeOwner
();
this
.
value
.
removeOwner
();
Cache
.
this
.
size
--;
}
}
/**
* Basic interface for references.
* It defines the operations common for the all kind of references.
*
* @param <T> the type of object to refer
*/
private
static
interface
Ref
<
T
>
{
/**
* Returns the object that possesses information about the reference.
*
* @return the owner of the reference or {@code null} if the owner is unknown
*/
Object
getOwner
();
/**
* Returns the object to refer.
*
* @return the referred object or {@code null} if it was collected
*/
T
getReferent
();
/**
* Determines whether the referred object was taken by the garbage collector or not.
*
* @return {@code true} if the referred object was collected
*/
boolean
isStale
();
/**
* Marks this reference as removed from the cache.
*/
void
removeOwner
();
}
/**
* Represents a reference kind.
*/
public
static
enum
Kind
{
STRONG
{
<
T
>
Ref
<
T
>
create
(
Object
owner
,
T
value
,
ReferenceQueue
<?
super
T
>
queue
)
{
return
new
Strong
<>(
owner
,
value
);
}
},
SOFT
{
<
T
>
Ref
<
T
>
create
(
Object
owner
,
T
referent
,
ReferenceQueue
<?
super
T
>
queue
)
{
return
(
referent
==
null
)
?
new
Strong
<>(
owner
,
referent
)
:
new
Soft
<>(
owner
,
referent
,
queue
);
}
},
WEAK
{
<
T
>
Ref
<
T
>
create
(
Object
owner
,
T
referent
,
ReferenceQueue
<?
super
T
>
queue
)
{
return
(
referent
==
null
)
?
new
Strong
<>(
owner
,
referent
)
:
new
Weak
<>(
owner
,
referent
,
queue
);
}
};
/**
* Creates a reference to the specified object.
*
* @param <T> the type of object to refer
* @param owner the owner of the reference, if needed
* @param referent the object to refer
* @param queue the queue to register the reference with,
* or {@code null} if registration is not required
* @return the reference to the specified object
*/
abstract
<
T
>
Ref
<
T
>
create
(
Object
owner
,
T
referent
,
ReferenceQueue
<?
super
T
>
queue
);
/**
* This is an implementation of the {@link Cache.Ref} interface
* that uses the strong references that prevent their referents
* from being made finalizable, finalized, and then reclaimed.
*
* @param <T> the type of object to refer
*/
private
static
final
class
Strong
<
T
>
implements
Ref
<
T
>
{
private
Object
owner
;
private
final
T
referent
;
/**
* Creates a strong reference to the specified object.
*
* @param owner the owner of the reference, if needed
* @param referent the non-null object to refer
*/
private
Strong
(
Object
owner
,
T
referent
)
{
this
.
owner
=
owner
;
this
.
referent
=
referent
;
}
/**
* Returns the object that possesses information about the reference.
*
* @return the owner of the reference or {@code null} if the owner is unknown
*/
public
Object
getOwner
()
{
return
this
.
owner
;
}
/**
* Returns the object to refer.
*
* @return the referred object
*/
public
T
getReferent
()
{
return
this
.
referent
;
}
/**
* Determines whether the referred object was taken by the garbage collector or not.
*
* @return {@code true} if the referred object was collected
*/
public
boolean
isStale
()
{
return
false
;
}
/**
* Marks this reference as removed from the cache.
*/
public
void
removeOwner
()
{
this
.
owner
=
null
;
}
}
/**
* This is an implementation of the {@link Cache.Ref} interface
* that uses the soft references that are cleared at the discretion
* of the garbage collector in response to a memory request.
*
* @param <T> the type of object to refer
* @see java.lang.ref.SoftReference
*/
private
static
final
class
Soft
<
T
>
extends
SoftReference
<
T
>
implements
Ref
<
T
>
{
private
Object
owner
;
/**
* Creates a soft reference to the specified object.
*
* @param owner the owner of the reference, if needed
* @param referent the non-null object to refer
* @param queue the queue to register the reference with,
* or {@code null} if registration is not required
*/
private
Soft
(
Object
owner
,
T
referent
,
ReferenceQueue
<?
super
T
>
queue
)
{
super
(
referent
,
queue
);
this
.
owner
=
owner
;
}
/**
* Returns the object that possesses information about the reference.
*
* @return the owner of the reference or {@code null} if the owner is unknown
*/
public
Object
getOwner
()
{
return
this
.
owner
;
}
/**
* Returns the object to refer.
*
* @return the referred object or {@code null} if it was collected
*/
public
T
getReferent
()
{
return
get
();
}
/**
* Determines whether the referred object was taken by the garbage collector or not.
*
* @return {@code true} if the referred object was collected
*/
public
boolean
isStale
()
{
return
null
==
get
();
}
/**
* Marks this reference as removed from the cache.
*/
public
void
removeOwner
()
{
this
.
owner
=
null
;
}
}
/**
* This is an implementation of the {@link Cache.Ref} interface
* that uses the weak references that do not prevent their referents
* from being made finalizable, finalized, and then reclaimed.
*
* @param <T> the type of object to refer
* @see java.lang.ref.WeakReference
*/
private
static
final
class
Weak
<
T
>
extends
WeakReference
<
T
>
implements
Ref
<
T
>
{
private
Object
owner
;
/**
* Creates a weak reference to the specified object.
*
* @param owner the owner of the reference, if needed
* @param referent the non-null object to refer
* @param queue the queue to register the reference with,
* or {@code null} if registration is not required
*/
private
Weak
(
Object
owner
,
T
referent
,
ReferenceQueue
<?
super
T
>
queue
)
{
super
(
referent
,
queue
);
this
.
owner
=
owner
;
}
/**
* Returns the object that possesses information about the reference.
*
* @return the owner of the reference or {@code null} if the owner is unknown
*/
public
Object
getOwner
()
{
return
this
.
owner
;
}
/**
* Returns the object to refer.
*
* @return the referred object or {@code null} if it was collected
*/
public
T
getReferent
()
{
return
get
();
}
/**
* Determines whether the referred object was taken by the garbage collector or not.
*
* @return {@code true} if the referred object was collected
*/
public
boolean
isStale
()
{
return
null
==
get
();
}
/**
* Marks this reference as removed from the cache.
*/
public
void
removeOwner
()
{
this
.
owner
=
null
;
}
}
}
}
test/java/beans/XMLDecoder/8028054/Task.java
0 → 100644
浏览文件 @
35367e22
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import
java.util.ArrayList
;
import
java.util.Enumeration
;
import
java.util.List
;
import
java.util.jar.JarEntry
;
import
java.util.jar.JarFile
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
abstract
class
Task
<
T
>
implements
Runnable
{
private
transient
boolean
working
=
true
;
private
final
List
<
T
>
methods
;
private
final
Thread
thread
;
Task
(
List
<
T
>
methods
)
{
this
.
methods
=
methods
;
this
.
thread
=
new
Thread
(
this
);
this
.
thread
.
start
();
}
boolean
isAlive
()
{
return
this
.
thread
.
isAlive
();
}
boolean
isWorking
()
{
boolean
working
=
this
.
working
&&
this
.
thread
.
isAlive
();
this
.
working
=
false
;
return
working
;
}
@Override
public
void
run
()
{
long
time
=
-
System
.
currentTimeMillis
();
for
(
T
method
:
this
.
methods
)
{
this
.
working
=
true
;
try
{
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
process
(
method
);
}
}
catch
(
NoSuchMethodException
ignore
)
{
}
}
time
+=
System
.
currentTimeMillis
();
print
(
"thread done in "
+
time
/
1000
+
" seconds"
);
}
protected
abstract
void
process
(
T
method
)
throws
NoSuchMethodException
;
static
synchronized
void
print
(
Object
message
)
{
System
.
out
.
println
(
message
);
System
.
out
.
flush
();
}
static
List
<
Class
<?>>
getClasses
(
int
count
)
throws
Exception
{
String
resource
=
ClassLoader
.
getSystemClassLoader
().
getResource
(
"java/lang/Object.class"
).
toString
();
Pattern
pattern
=
Pattern
.
compile
(
"jar:file:(.*)!.*"
);
Matcher
matcher
=
pattern
.
matcher
(
resource
);
matcher
.
matches
();
resource
=
matcher
.
group
(
1
);
List
<
Class
<?>>
classes
=
new
ArrayList
<>();
try
(
JarFile
jarFile
=
new
JarFile
(
resource
))
{
Enumeration
<
JarEntry
>
entries
=
jarFile
.
entries
();
while
(
entries
.
hasMoreElements
())
{
String
name
=
entries
.
nextElement
().
getName
();
if
(
name
.
startsWith
(
"java"
)
&&
name
.
endsWith
(
".class"
))
{
classes
.
add
(
Class
.
forName
(
name
.
substring
(
0
,
name
.
indexOf
(
"."
)).
replace
(
'/'
,
'.'
)));
if
(
count
==
classes
.
size
())
{
break
;
}
}
}
}
return
classes
;
}
}
test/java/beans/XMLDecoder/8028054/TestConstructorFinder.java
0 → 100644
浏览文件 @
35367e22
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import
com.sun.beans.finder.ConstructorFinder
;
import
java.lang.reflect.Constructor
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
/*
* @test
* @bug 8028054
* @summary Tests that cached constructors have synchronized access
* @author Sergey Malenkov
* @compile -XDignore.symbol.file TestConstructorFinder.java
* @run main TestConstructorFinder
*/
public
class
TestConstructorFinder
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
List
<
Class
<?>>
classes
=
Task
.
getClasses
(
Integer
.
MAX_VALUE
);
List
<
Constructor
>
constructors
=
new
ArrayList
<>();
for
(
Class
<?>
type
:
classes
)
{
Collections
.
addAll
(
constructors
,
type
.
getConstructors
());
}
Task
.
print
(
"found "
+
constructors
.
size
()
+
" constructors in "
+
classes
.
size
()
+
" classes"
);
List
<
Task
>
tasks
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
50
;
i
++)
{
tasks
.
add
(
new
Task
<
Constructor
>(
constructors
)
{
@Override
protected
void
process
(
Constructor
constructor
)
throws
NoSuchMethodException
{
ConstructorFinder
.
findConstructor
(
constructor
.
getDeclaringClass
(),
constructor
.
getParameterTypes
());
}
});
}
int
alarm
=
0
;
while
(
true
)
{
int
alive
=
0
;
int
working
=
0
;
for
(
Task
task
:
tasks
)
{
if
(
task
.
isWorking
())
{
working
++;
alive
++;
}
else
if
(
task
.
isAlive
())
{
alive
++;
}
}
if
(
alive
==
0
)
{
break
;
}
Task
.
print
(
working
+
" out of "
+
alive
+
" threads are working"
);
if
((
working
==
0
)
&&
(++
alarm
==
10
))
{
Task
.
print
(
"DEADLOCK DETECTED"
);
System
.
exit
(
100
);
}
Thread
.
sleep
(
1000
);
}
}
}
test/java/beans/XMLDecoder/8028054/TestMethodFinder.java
0 → 100644
浏览文件 @
35367e22
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import
com.sun.beans.finder.MethodFinder
;
import
java.lang.reflect.Method
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
/*
* @test
* @bug 8028054
* @summary Tests that cached methods have synchronized access
* @author Sergey Malenkov
* @compile -XDignore.symbol.file TestMethodFinder.java
* @run main TestMethodFinder
*/
public
class
TestMethodFinder
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
List
<
Class
<?>>
classes
=
Task
.
getClasses
(
4000
);
List
<
Method
>
methods
=
new
ArrayList
<>();
for
(
Class
<?>
type
:
classes
)
{
Collections
.
addAll
(
methods
,
type
.
getMethods
());
}
Task
.
print
(
"found "
+
methods
.
size
()
+
" methods in "
+
classes
.
size
()
+
" classes"
);
List
<
Task
>
tasks
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
50
;
i
++)
{
tasks
.
add
(
new
Task
<
Method
>(
methods
)
{
@Override
protected
void
process
(
Method
method
)
throws
NoSuchMethodException
{
MethodFinder
.
findMethod
(
method
.
getDeclaringClass
(),
method
.
getName
(),
method
.
getParameterTypes
());
}
});
}
int
alarm
=
0
;
while
(
true
)
{
int
alive
=
0
;
int
working
=
0
;
for
(
Task
task
:
tasks
)
{
if
(
task
.
isWorking
())
{
working
++;
alive
++;
}
else
if
(
task
.
isAlive
())
{
alive
++;
}
}
if
(
alive
==
0
)
{
break
;
}
Task
.
print
(
working
+
" out of "
+
alive
+
" threads are working"
);
if
((
working
==
0
)
&&
(++
alarm
==
10
))
{
Task
.
print
(
"DEADLOCK DETECTED"
);
System
.
exit
(
100
);
}
Thread
.
sleep
(
1000
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录