Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
ef182632
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看板
提交
ef182632
编写于
9月 19, 2013
作者:
P
plevart
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8011940: java.lang.Class.getAnnotations() always enters synchronized method
Reviewed-by: jfranck, chegar, psandoz, shade
上级
a2ba4be5
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
289 addition
and
40 deletion
+289
-40
src/share/classes/java/lang/Class.java
src/share/classes/java/lang/Class.java
+79
-40
test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java
...notation/AnnotationsInheritanceOrderRedefinitionTest.java
+210
-0
未找到文件。
src/share/classes/java/lang/Class.java
浏览文件 @
ef182632
...
...
@@ -48,6 +48,7 @@ import java.util.ArrayList;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Map
;
...
...
@@ -2370,11 +2371,14 @@ public final class Class<T> implements java.io.Serializable,
private
static
final
long
reflectionDataOffset
;
// offset of Class.annotationType instance field
private
static
final
long
annotationTypeOffset
;
// offset of Class.annotationData instance field
private
static
final
long
annotationDataOffset
;
static
{
Field
[]
fields
=
Class
.
class
.
getDeclaredFields0
(
false
);
// bypass caches
reflectionDataOffset
=
objectFieldOffset
(
fields
,
"reflectionData"
);
annotationTypeOffset
=
objectFieldOffset
(
fields
,
"annotationType"
);
annotationDataOffset
=
objectFieldOffset
(
fields
,
"annotationData"
);
}
private
static
long
objectFieldOffset
(
Field
[]
fields
,
String
fieldName
)
{
...
...
@@ -2396,6 +2400,12 @@ public final class Class<T> implements java.io.Serializable,
AnnotationType
newType
)
{
return
unsafe
.
compareAndSwapObject
(
clazz
,
annotationTypeOffset
,
oldType
,
newType
);
}
static
<
T
>
boolean
casAnnotationData
(
Class
<?>
clazz
,
AnnotationData
oldData
,
AnnotationData
newData
)
{
return
unsafe
.
compareAndSwapObject
(
clazz
,
annotationDataOffset
,
oldData
,
newData
);
}
}
/**
...
...
@@ -2406,7 +2416,7 @@ public final class Class<T> implements java.io.Serializable,
private
static
boolean
useCaches
=
true
;
// reflection data that might get invalidated when JVM TI RedefineClasses() is called
static
class
ReflectionData
<
T
>
{
private
static
class
ReflectionData
<
T
>
{
volatile
Field
[]
declaredFields
;
volatile
Field
[]
publicFields
;
volatile
Method
[]
declaredMethods
;
...
...
@@ -3253,8 +3263,7 @@ public final class Class<T> implements java.io.Serializable,
public
<
A
extends
Annotation
>
A
getAnnotation
(
Class
<
A
>
annotationClass
)
{
Objects
.
requireNonNull
(
annotationClass
);
initAnnotationsIfNecessary
();
return
(
A
)
annotations
.
get
(
annotationClass
);
return
(
A
)
annotationData
().
annotations
.
get
(
annotationClass
);
}
/**
...
...
@@ -3275,16 +3284,14 @@ public final class Class<T> implements java.io.Serializable,
public
<
A
extends
Annotation
>
A
[]
getAnnotationsByType
(
Class
<
A
>
annotationClass
)
{
Objects
.
requireNonNull
(
annotationClass
);
initAnnotationsIfNecessary
();
return
AnnotationSupport
.
getMultipleAnnotations
(
annotations
,
annotationClass
);
return
AnnotationSupport
.
getMultipleAnnotations
(
annotationData
().
annotations
,
annotationClass
);
}
/**
* @since 1.5
*/
public
Annotation
[]
getAnnotations
()
{
initAnnotationsIfNecessary
();
return
AnnotationParser
.
toArray
(
annotations
);
return
AnnotationParser
.
toArray
(
annotationData
().
annotations
);
}
/**
...
...
@@ -3296,8 +3303,7 @@ public final class Class<T> implements java.io.Serializable,
public
<
A
extends
Annotation
>
A
getDeclaredAnnotation
(
Class
<
A
>
annotationClass
)
{
Objects
.
requireNonNull
(
annotationClass
);
initAnnotationsIfNecessary
();
return
(
A
)
declaredAnnotations
.
get
(
annotationClass
);
return
(
A
)
annotationData
().
declaredAnnotations
.
get
(
annotationClass
);
}
/**
...
...
@@ -3308,52 +3314,85 @@ public final class Class<T> implements java.io.Serializable,
public
<
A
extends
Annotation
>
A
[]
getDeclaredAnnotationsByType
(
Class
<
A
>
annotationClass
)
{
Objects
.
requireNonNull
(
annotationClass
);
initAnnotationsIfNecessary
();
return
AnnotationSupport
.
getMultipleAnnotations
(
declaredAnnotations
,
annotationClass
);
return
AnnotationSupport
.
getMultipleAnnotations
(
annotationData
().
declaredAnnotations
,
annotationClass
);
}
/**
* @since 1.5
*/
public
Annotation
[]
getDeclaredAnnotations
()
{
initAnnotationsIfNecessary
();
return
AnnotationParser
.
toArray
(
declaredAnnotations
);
return
AnnotationParser
.
toArray
(
annotationData
().
declaredAnnotations
);
}
// annotation data that might get invalidated when JVM TI RedefineClasses() is called
private
static
class
AnnotationData
{
final
Map
<
Class
<?
extends
Annotation
>,
Annotation
>
annotations
;
final
Map
<
Class
<?
extends
Annotation
>,
Annotation
>
declaredAnnotations
;
// Value of classRedefinedCount when we created this AnnotationData instance
final
int
redefinedCount
;
AnnotationData
(
Map
<
Class
<?
extends
Annotation
>,
Annotation
>
annotations
,
Map
<
Class
<?
extends
Annotation
>,
Annotation
>
declaredAnnotations
,
int
redefinedCount
)
{
this
.
annotations
=
annotations
;
this
.
declaredAnnotations
=
declaredAnnotations
;
this
.
redefinedCount
=
redefinedCount
;
}
}
// Annotations cache
private
transient
Map
<
Class
<?
extends
Annotation
>,
Annotation
>
annotations
;
private
transient
Map
<
Class
<?
extends
Annotation
>,
Annotation
>
declaredAnnotations
;
// Value of classRedefinedCount when we last cleared the cached annotations and declaredAnnotations fields
private
transient
int
lastAnnotationsRedefinedCount
=
0
;
// Clears cached values that might possibly have been obsoleted by
// a class redefinition.
private
void
clearAnnotationCachesOnClassRedefinition
()
{
if
(
lastAnnotationsRedefinedCount
!=
classRedefinedCount
)
{
annotations
=
declaredAnnotations
=
null
;
lastAnnotationsRedefinedCount
=
classRedefinedCount
;
}
}
private
synchronized
void
initAnnotationsIfNecessary
()
{
clearAnnotationCachesOnClassRedefinition
();
if
(
annotations
!=
null
)
return
;
declaredAnnotations
=
AnnotationParser
.
parseAnnotations
(
getRawAnnotations
(),
getConstantPool
(),
this
);
@SuppressWarnings
(
"UnusedDeclaration"
)
private
volatile
transient
AnnotationData
annotationData
;
private
AnnotationData
annotationData
()
{
while
(
true
)
{
// retry loop
AnnotationData
annotationData
=
this
.
annotationData
;
int
classRedefinedCount
=
this
.
classRedefinedCount
;
if
(
annotationData
!=
null
&&
annotationData
.
redefinedCount
==
classRedefinedCount
)
{
return
annotationData
;
}
// null or stale annotationData -> optimistically create new instance
AnnotationData
newAnnotationData
=
createAnnotationData
(
classRedefinedCount
);
// try to install it
if
(
Atomic
.
casAnnotationData
(
this
,
annotationData
,
newAnnotationData
))
{
// successfully installed new AnnotationData
return
newAnnotationData
;
}
}
}
private
AnnotationData
createAnnotationData
(
int
classRedefinedCount
)
{
Map
<
Class
<?
extends
Annotation
>,
Annotation
>
declaredAnnotations
=
AnnotationParser
.
parseAnnotations
(
getRawAnnotations
(),
getConstantPool
(),
this
);
Class
<?>
superClass
=
getSuperclass
();
if
(
superClass
==
null
)
{
annotations
=
declaredAnnotations
;
}
else
{
annotations
=
new
HashMap
<>();
superClass
.
initAnnotationsIfNecessary
();
for
(
Map
.
Entry
<
Class
<?
extends
Annotation
>,
Annotation
>
e
:
superClass
.
annotations
.
entrySet
())
{
Map
<
Class
<?
extends
Annotation
>,
Annotation
>
annotations
=
null
;
if
(
superClass
!=
null
)
{
Map
<
Class
<?
extends
Annotation
>,
Annotation
>
superAnnotations
=
superClass
.
annotationData
().
annotations
;
for
(
Map
.
Entry
<
Class
<?
extends
Annotation
>,
Annotation
>
e
:
superAnnotations
.
entrySet
())
{
Class
<?
extends
Annotation
>
annotationClass
=
e
.
getKey
();
if
(
AnnotationType
.
getInstance
(
annotationClass
).
isInherited
())
if
(
AnnotationType
.
getInstance
(
annotationClass
).
isInherited
())
{
if
(
annotations
==
null
)
{
// lazy construction
annotations
=
new
LinkedHashMap
<>((
Math
.
max
(
declaredAnnotations
.
size
(),
Math
.
min
(
12
,
declaredAnnotations
.
size
()
+
superAnnotations
.
size
())
)
*
4
+
2
)
/
3
);
}
annotations
.
put
(
annotationClass
,
e
.
getValue
());
}
}
}
if
(
annotations
==
null
)
{
// no inherited annotations -> share the Map with declaredAnnotations
annotations
=
declaredAnnotations
;
}
else
{
// at least one inherited annotation -> declared may override inherited
annotations
.
putAll
(
declaredAnnotations
);
}
return
new
AnnotationData
(
annotations
,
declaredAnnotations
,
classRedefinedCount
);
}
// Annotation types cache their internal (AnnotationType) form
...
...
test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java
0 → 100644
浏览文件 @
ef182632
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8011940
* @summary Test inheritance, order and class redefinition behaviour of RUNTIME
* class annotations
* @author plevart
*/
import
sun.reflect.annotation.AnnotationParser
;
import
java.lang.annotation.Annotation
;
import
java.lang.annotation.Inherited
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.InvocationTargetException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.StringJoiner
;
public
class
AnnotationsInheritanceOrderRedefinitionTest
{
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Inherited
@interface
Ann1
{
String
value
();
}
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Inherited
@interface
Ann2
{
String
value
();
}
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Inherited
@interface
Ann3
{
String
value
();
}
@Ann1
(
"A"
)
@Ann2
(
"A"
)
static
class
A
{}
@Ann3
(
"B"
)
static
class
B
extends
A
{}
@Ann1
(
"C"
)
@Ann3
(
"C"
)
static
class
C
extends
B
{}
public
static
void
main
(
String
[]
args
)
{
StringBuilder
msgs
=
new
StringBuilder
();
boolean
ok
=
true
;
ok
&=
annotationsEqual
(
msgs
,
A
.
class
,
true
,
ann
(
Ann1
.
class
,
"A"
),
ann
(
Ann2
.
class
,
"A"
));
ok
&=
annotationsEqual
(
msgs
,
A
.
class
,
false
,
ann
(
Ann1
.
class
,
"A"
),
ann
(
Ann2
.
class
,
"A"
));
ok
&=
annotationsEqual
(
msgs
,
B
.
class
,
true
,
ann
(
Ann3
.
class
,
"B"
));
ok
&=
annotationsEqual
(
msgs
,
B
.
class
,
false
,
ann
(
Ann1
.
class
,
"A"
),
ann
(
Ann2
.
class
,
"A"
),
ann
(
Ann3
.
class
,
"B"
));
ok
&=
annotationsEqual
(
msgs
,
C
.
class
,
true
,
ann
(
Ann1
.
class
,
"C"
),
ann
(
Ann3
.
class
,
"C"
));
ok
&=
annotationsEqual
(
msgs
,
C
.
class
,
false
,
ann
(
Ann1
.
class
,
"C"
),
ann
(
Ann2
.
class
,
"A"
),
ann
(
Ann3
.
class
,
"C"
));
Annotation
[]
declaredAnnotatiosA
=
A
.
class
.
getDeclaredAnnotations
();
Annotation
[]
annotationsA
=
A
.
class
.
getAnnotations
();
Annotation
[]
declaredAnnotatiosB
=
B
.
class
.
getDeclaredAnnotations
();
Annotation
[]
annotationsB
=
B
.
class
.
getAnnotations
();
Annotation
[]
declaredAnnotatiosC
=
C
.
class
.
getDeclaredAnnotations
();
Annotation
[]
annotationsC
=
C
.
class
.
getAnnotations
();
incrementClassRedefinedCount
(
A
.
class
);
incrementClassRedefinedCount
(
B
.
class
);
incrementClassRedefinedCount
(
C
.
class
);
ok
&=
annotationsEqualButNotSame
(
msgs
,
A
.
class
,
true
,
declaredAnnotatiosA
);
ok
&=
annotationsEqualButNotSame
(
msgs
,
A
.
class
,
false
,
annotationsA
);
ok
&=
annotationsEqualButNotSame
(
msgs
,
B
.
class
,
true
,
declaredAnnotatiosB
);
ok
&=
annotationsEqualButNotSame
(
msgs
,
B
.
class
,
false
,
annotationsB
);
ok
&=
annotationsEqualButNotSame
(
msgs
,
C
.
class
,
true
,
declaredAnnotatiosC
);
ok
&=
annotationsEqualButNotSame
(
msgs
,
C
.
class
,
false
,
annotationsC
);
if
(!
ok
)
{
throw
new
RuntimeException
(
"test failure\n"
+
msgs
);
}
}
// utility methods
private
static
boolean
annotationsEqualButNotSame
(
StringBuilder
msgs
,
Class
<?>
declaringClass
,
boolean
declaredOnly
,
Annotation
[]
oldAnns
)
{
if
(!
annotationsEqual
(
msgs
,
declaringClass
,
declaredOnly
,
oldAnns
))
{
return
false
;
}
Annotation
[]
anns
=
declaredOnly
?
declaringClass
.
getDeclaredAnnotations
()
:
declaringClass
.
getAnnotations
();
List
<
Annotation
>
sameAnns
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
anns
.
length
;
i
++)
{
if
(
anns
[
i
]
==
oldAnns
[
i
])
{
sameAnns
.
add
(
anns
[
i
]);
}
}
if
(!
sameAnns
.
isEmpty
())
{
msgs
.
append
(
declaredOnly
?
"declared "
:
""
).
append
(
"annotations for "
)
.
append
(
declaringClass
.
getSimpleName
())
.
append
(
" not re-parsed after class redefinition: "
)
.
append
(
toSimpleString
(
sameAnns
)).
append
(
"\n"
);
return
false
;
}
else
{
return
true
;
}
}
private
static
boolean
annotationsEqual
(
StringBuilder
msgs
,
Class
<?>
declaringClass
,
boolean
declaredOnly
,
Annotation
...
expectedAnns
)
{
Annotation
[]
anns
=
declaredOnly
?
declaringClass
.
getDeclaredAnnotations
()
:
declaringClass
.
getAnnotations
();
if
(!
Arrays
.
equals
(
anns
,
expectedAnns
))
{
msgs
.
append
(
declaredOnly
?
"declared "
:
""
).
append
(
"annotations for "
)
.
append
(
declaringClass
.
getSimpleName
()).
append
(
" are: "
)
.
append
(
toSimpleString
(
anns
)).
append
(
", expected: "
)
.
append
(
toSimpleString
(
expectedAnns
)).
append
(
"\n"
);
return
false
;
}
else
{
return
true
;
}
}
private
static
Annotation
ann
(
Class
<?
extends
Annotation
>
annotationType
,
Object
value
)
{
return
AnnotationParser
.
annotationForMap
(
annotationType
,
Collections
.
singletonMap
(
"value"
,
value
));
}
private
static
String
toSimpleString
(
List
<
Annotation
>
anns
)
{
return
toSimpleString
(
anns
.
toArray
(
new
Annotation
[
anns
.
size
()]));
}
private
static
String
toSimpleString
(
Annotation
[]
anns
)
{
StringJoiner
joiner
=
new
StringJoiner
(
", "
);
for
(
Annotation
ann
:
anns
)
{
joiner
.
add
(
toSimpleString
(
ann
));
}
return
joiner
.
toString
();
}
private
static
String
toSimpleString
(
Annotation
ann
)
{
Class
<?
extends
Annotation
>
annotationType
=
ann
.
annotationType
();
Object
value
;
try
{
value
=
annotationType
.
getDeclaredMethod
(
"value"
).
invoke
(
ann
);
}
catch
(
IllegalAccessException
|
InvocationTargetException
|
NoSuchMethodException
e
)
{
throw
new
RuntimeException
(
e
);
}
return
"@"
+
annotationType
.
getSimpleName
()
+
"("
+
value
+
")"
;
}
private
static
final
Field
classRedefinedCountField
;
static
{
try
{
classRedefinedCountField
=
Class
.
class
.
getDeclaredField
(
"classRedefinedCount"
);
classRedefinedCountField
.
setAccessible
(
true
);
}
catch
(
NoSuchFieldException
e
)
{
throw
new
Error
(
e
);
}
}
private
static
void
incrementClassRedefinedCount
(
Class
<?>
clazz
)
{
try
{
classRedefinedCountField
.
set
(
clazz
,
((
Integer
)
classRedefinedCountField
.
get
(
clazz
))
+
1
);
}
catch
(
IllegalAccessException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录