Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
2cf3ff27
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
2cf3ff27
编写于
6月 06, 2014
作者:
A
amurillo
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
65c01a25
248315c0
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
645 addition
and
135 deletion
+645
-135
make/aix/makefiles/mapfile-vers-debug
make/aix/makefiles/mapfile-vers-debug
+2
-1
make/aix/makefiles/mapfile-vers-product
make/aix/makefiles/mapfile-vers-product
+1
-0
make/bsd/makefiles/mapfile-vers-debug
make/bsd/makefiles/mapfile-vers-debug
+1
-0
make/bsd/makefiles/mapfile-vers-product
make/bsd/makefiles/mapfile-vers-product
+1
-0
make/bsd/makefiles/universal.gmk
make/bsd/makefiles/universal.gmk
+5
-3
make/hotspot_version
make/hotspot_version
+1
-1
make/linux/makefiles/mapfile-vers-debug
make/linux/makefiles/mapfile-vers-debug
+2
-1
make/linux/makefiles/mapfile-vers-product
make/linux/makefiles/mapfile-vers-product
+1
-0
make/solaris/makefiles/mapfile-vers
make/solaris/makefiles/mapfile-vers
+1
-0
src/cpu/sparc/vm/copy_sparc.hpp
src/cpu/sparc/vm/copy_sparc.hpp
+1
-1
src/share/vm/ci/bcEscapeAnalyzer.cpp
src/share/vm/ci/bcEscapeAnalyzer.cpp
+3
-0
src/share/vm/opto/bytecodeInfo.cpp
src/share/vm/opto/bytecodeInfo.cpp
+7
-4
src/share/vm/opto/library_call.cpp
src/share/vm/opto/library_call.cpp
+25
-25
src/share/vm/prims/jvm.cpp
src/share/vm/prims/jvm.cpp
+17
-0
src/share/vm/prims/jvm.h
src/share/vm/prims/jvm.h
+3
-0
src/share/vm/runtime/objectMonitor.cpp
src/share/vm/runtime/objectMonitor.cpp
+9
-0
src/share/vm/runtime/vframe.cpp
src/share/vm/runtime/vframe.cpp
+6
-1
test/TEST.groups
test/TEST.groups
+2
-1
test/compiler/EscapeAnalysis/TestAllocatedEscapesPtrComparison.java
...ler/EscapeAnalysis/TestAllocatedEscapesPtrComparison.java
+107
-0
test/compiler/intrinsics/hashcode/TestHashCode.java
test/compiler/intrinsics/hashcode/TestHashCode.java
+45
-8
test/gc/g1/TestStringDeduplicationTools.java
test/gc/g1/TestStringDeduplicationTools.java
+0
-89
test/runtime/Thread/TestThreadDumpMonitorContention.java
test/runtime/Thread/TestThreadDumpMonitorContention.java
+405
-0
未找到文件。
make/aix/makefiles/mapfile-vers-debug
浏览文件 @
2cf3ff27
...
@@ -122,7 +122,7 @@ SUNWprivate_1.1 {
...
@@ -122,7 +122,7 @@ SUNWprivate_1.1 {
JVM_GetClassModifiers;
JVM_GetClassModifiers;
JVM_GetClassName;
JVM_GetClassName;
JVM_GetClassNameUTF;
JVM_GetClassNameUTF;
JVM_GetClassSignature;
JVM_GetClassSignature;
JVM_GetClassSigners;
JVM_GetClassSigners;
JVM_GetClassTypeAnnotations;
JVM_GetClassTypeAnnotations;
JVM_GetComponentType;
JVM_GetComponentType;
...
@@ -163,6 +163,7 @@ SUNWprivate_1.1 {
...
@@ -163,6 +163,7 @@ SUNWprivate_1.1 {
JVM_GetStackTraceElement;
JVM_GetStackTraceElement;
JVM_GetSystemPackage;
JVM_GetSystemPackage;
JVM_GetSystemPackages;
JVM_GetSystemPackages;
JVM_GetTemporaryDirectory;
JVM_GetThreadStateNames;
JVM_GetThreadStateNames;
JVM_GetThreadStateValues;
JVM_GetThreadStateValues;
JVM_GetVersionInfo;
JVM_GetVersionInfo;
...
...
make/aix/makefiles/mapfile-vers-product
浏览文件 @
2cf3ff27
...
@@ -161,6 +161,7 @@ SUNWprivate_1.1 {
...
@@ -161,6 +161,7 @@ SUNWprivate_1.1 {
JVM_GetStackTraceElement;
JVM_GetStackTraceElement;
JVM_GetSystemPackage;
JVM_GetSystemPackage;
JVM_GetSystemPackages;
JVM_GetSystemPackages;
JVM_GetTemporaryDirectory;
JVM_GetThreadStateNames;
JVM_GetThreadStateNames;
JVM_GetThreadStateValues;
JVM_GetThreadStateValues;
JVM_GetVersionInfo;
JVM_GetVersionInfo;
...
...
make/bsd/makefiles/mapfile-vers-debug
浏览文件 @
2cf3ff27
...
@@ -161,6 +161,7 @@
...
@@ -161,6 +161,7 @@
_JVM_GetStackTraceElement
_JVM_GetStackTraceElement
_JVM_GetSystemPackage
_JVM_GetSystemPackage
_JVM_GetSystemPackages
_JVM_GetSystemPackages
_JVM_GetTemporaryDirectory
_JVM_GetThreadStateNames
_JVM_GetThreadStateNames
_JVM_GetThreadStateValues
_JVM_GetThreadStateValues
_JVM_GetVersionInfo
_JVM_GetVersionInfo
...
...
make/bsd/makefiles/mapfile-vers-product
浏览文件 @
2cf3ff27
...
@@ -161,6 +161,7 @@
...
@@ -161,6 +161,7 @@
_JVM_GetStackTraceElement
_JVM_GetStackTraceElement
_JVM_GetSystemPackage
_JVM_GetSystemPackage
_JVM_GetSystemPackages
_JVM_GetSystemPackages
_JVM_GetTemporaryDirectory
_JVM_GetThreadStateNames
_JVM_GetThreadStateNames
_JVM_GetThreadStateValues
_JVM_GetThreadStateValues
_JVM_GetVersionInfo
_JVM_GetVersionInfo
...
...
make/bsd/makefiles/universal.gmk
浏览文件 @
2cf3ff27
#
#
# Copyright (c) 2006, 201
3
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2006, 201
4
, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
#
# This code is free software; you can redistribute it and/or modify it
# This code is free software; you can redistribute it and/or modify it
...
@@ -74,19 +74,21 @@ $(UNIVERSAL_COPY_LIST):
...
@@ -74,19 +74,21 @@ $(UNIVERSAL_COPY_LIST):
# Replace arch specific binaries with universal binaries
# Replace arch specific binaries with universal binaries
# Do not touch jre/lib/{client,server}/libjsig.$(LIBRARY_SUFFIX)
# That symbolic link belongs to the 'jdk' build.
export_universal:
export_universal:
$(RM) -r $(EXPORT_PATH)/jre/lib/{i386,amd64}
$(RM) -r $(EXPORT_PATH)/jre/lib/{i386,amd64}
$(RM) -r $(JDK_IMAGE_DIR)/jre/lib/{i386,amd64}
$(RM) -r $(JDK_IMAGE_DIR)/jre/lib/{i386,amd64}
$(RM) $(JDK_IMAGE_DIR)/jre/lib/{client,server}/libjsig.$(LIBRARY_SUFFIX)
($(CD) $(EXPORT_PATH) && \
($(CD) $(EXPORT_PATH) && \
$(TAR) -cf - *) | \
$(TAR) -cf - *) | \
($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xpf -)
($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xpf -)
# Overlay universal binaries
# Overlay universal binaries
# Do not touch jre/lib/{client,server}/libjsig.$(LIBRARY_SUFFIX)
# That symbolic link belongs to the 'jdk' build.
copy_universal:
copy_universal:
$(RM) -r $(JDK_IMAGE_DIR)$(COPY_SUBDIR)/jre/lib/{i386,amd64}
$(RM) -r $(JDK_IMAGE_DIR)$(COPY_SUBDIR)/jre/lib/{i386,amd64}
$(RM) $(JDK_IMAGE_DIR)$(COPY_SUBDIR)/jre/lib/{client,server}/libjsig.$(LIBRARY_SUFFIX)
($(CD) $(EXPORT_PATH)$(COPY_SUBDIR) && \
($(CD) $(EXPORT_PATH)$(COPY_SUBDIR) && \
$(TAR) -cf - *) | \
$(TAR) -cf - *) | \
($(CD) $(JDK_IMAGE_DIR)$(COPY_SUBDIR) && $(TAR) -xpf -)
($(CD) $(JDK_IMAGE_DIR)$(COPY_SUBDIR) && $(TAR) -xpf -)
...
...
make/hotspot_version
浏览文件 @
2cf3ff27
...
@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014
...
@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014
HS_MAJOR_VER=25
HS_MAJOR_VER=25
HS_MINOR_VER=20
HS_MINOR_VER=20
HS_BUILD_NUMBER=1
7
HS_BUILD_NUMBER=1
8
JDK_MAJOR_VER=1
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
JDK_MINOR_VER=8
...
...
make/linux/makefiles/mapfile-vers-debug
浏览文件 @
2cf3ff27
...
@@ -122,7 +122,7 @@ SUNWprivate_1.1 {
...
@@ -122,7 +122,7 @@ SUNWprivate_1.1 {
JVM_GetClassModifiers;
JVM_GetClassModifiers;
JVM_GetClassName;
JVM_GetClassName;
JVM_GetClassNameUTF;
JVM_GetClassNameUTF;
JVM_GetClassSignature;
JVM_GetClassSignature;
JVM_GetClassSigners;
JVM_GetClassSigners;
JVM_GetClassTypeAnnotations;
JVM_GetClassTypeAnnotations;
JVM_GetComponentType;
JVM_GetComponentType;
...
@@ -163,6 +163,7 @@ SUNWprivate_1.1 {
...
@@ -163,6 +163,7 @@ SUNWprivate_1.1 {
JVM_GetStackTraceElement;
JVM_GetStackTraceElement;
JVM_GetSystemPackage;
JVM_GetSystemPackage;
JVM_GetSystemPackages;
JVM_GetSystemPackages;
JVM_GetTemporaryDirectory;
JVM_GetThreadStateNames;
JVM_GetThreadStateNames;
JVM_GetThreadStateValues;
JVM_GetThreadStateValues;
JVM_GetVersionInfo;
JVM_GetVersionInfo;
...
...
make/linux/makefiles/mapfile-vers-product
浏览文件 @
2cf3ff27
...
@@ -163,6 +163,7 @@ SUNWprivate_1.1 {
...
@@ -163,6 +163,7 @@ SUNWprivate_1.1 {
JVM_GetStackTraceElement;
JVM_GetStackTraceElement;
JVM_GetSystemPackage;
JVM_GetSystemPackage;
JVM_GetSystemPackages;
JVM_GetSystemPackages;
JVM_GetTemporaryDirectory;
JVM_GetThreadStateNames;
JVM_GetThreadStateNames;
JVM_GetThreadStateValues;
JVM_GetThreadStateValues;
JVM_GetVersionInfo;
JVM_GetVersionInfo;
...
...
make/solaris/makefiles/mapfile-vers
浏览文件 @
2cf3ff27
...
@@ -163,6 +163,7 @@ SUNWprivate_1.1 {
...
@@ -163,6 +163,7 @@ SUNWprivate_1.1 {
JVM_GetStackTraceElement;
JVM_GetStackTraceElement;
JVM_GetSystemPackage;
JVM_GetSystemPackage;
JVM_GetSystemPackages;
JVM_GetSystemPackages;
JVM_GetTemporaryDirectory;
JVM_GetThreadStateNames;
JVM_GetThreadStateNames;
JVM_GetThreadStateValues;
JVM_GetThreadStateValues;
JVM_GetVersionInfo;
JVM_GetVersionInfo;
...
...
src/cpu/sparc/vm/copy_sparc.hpp
浏览文件 @
2cf3ff27
...
@@ -184,7 +184,7 @@ static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value)
...
@@ -184,7 +184,7 @@ static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value)
assert
(
MinObjAlignmentInBytes
>=
BytesPerLong
,
"need alternate implementation"
);
assert
(
MinObjAlignmentInBytes
>=
BytesPerLong
,
"need alternate implementation"
);
if
(
value
==
0
&&
UseBlockZeroing
&&
if
(
value
==
0
&&
UseBlockZeroing
&&
(
count
>
(
BlockZeroingLowLimit
>>
LogHeapWordSize
)))
{
(
count
>
(
size_t
)(
BlockZeroingLowLimit
>>
LogHeapWordSize
)))
{
// Call it only when block zeroing is used
// Call it only when block zeroing is used
((
_zero_Fn
)
StubRoutines
::
zero_aligned_words
())(
tohw
,
count
);
((
_zero_Fn
)
StubRoutines
::
zero_aligned_words
())(
tohw
,
count
);
}
else
{
}
else
{
...
...
src/share/vm/ci/bcEscapeAnalyzer.cpp
浏览文件 @
2cf3ff27
...
@@ -158,6 +158,9 @@ void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
...
@@ -158,6 +158,9 @@ void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
void
BCEscapeAnalyzer
::
set_method_escape
(
ArgumentMap
vars
)
{
void
BCEscapeAnalyzer
::
set_method_escape
(
ArgumentMap
vars
)
{
clear_bits
(
vars
,
_arg_local
);
clear_bits
(
vars
,
_arg_local
);
if
(
vars
.
contains_allocated
())
{
_allocated_escapes
=
true
;
}
}
}
void
BCEscapeAnalyzer
::
set_global_escape
(
ArgumentMap
vars
,
bool
merge
)
{
void
BCEscapeAnalyzer
::
set_global_escape
(
ArgumentMap
vars
,
bool
merge
)
{
...
...
src/share/vm/opto/bytecodeInfo.cpp
浏览文件 @
2cf3ff27
...
@@ -361,11 +361,14 @@ bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method,
...
@@ -361,11 +361,14 @@ bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method,
set_msg
(
"not an accessor"
);
set_msg
(
"not an accessor"
);
return
false
;
return
false
;
}
}
// Limit inlining depth in case inlining is forced or
// _max_inline_level was increased to compensate for lambda forms.
if
(
inline_level
()
>
MaxForceInlineLevel
)
{
set_msg
(
"MaxForceInlineLevel"
);
return
false
;
}
if
(
inline_level
()
>
_max_inline_level
)
{
if
(
inline_level
()
>
_max_inline_level
)
{
if
(
callee_method
->
force_inline
()
&&
inline_level
()
>
MaxForceInlineLevel
)
{
set_msg
(
"MaxForceInlineLevel"
);
return
false
;
}
if
(
!
callee_method
->
force_inline
()
||
!
IncrementalInline
)
{
if
(
!
callee_method
->
force_inline
()
||
!
IncrementalInline
)
{
set_msg
(
"inlining too deep"
);
set_msg
(
"inlining too deep"
);
return
false
;
return
false
;
...
...
src/share/vm/opto/library_call.cpp
浏览文件 @
2cf3ff27
...
@@ -3978,8 +3978,11 @@ LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual
...
@@ -3978,8 +3978,11 @@ LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual
}
}
//------------------------------inline_native_hashcode--------------------
/**
// Build special case code for calls to hashCode on an object.
* Build special case code for calls to hashCode on an object. This call may
* be virtual (invokevirtual) or bound (invokespecial). For each case we generate
* slightly different code.
*/
bool
LibraryCallKit
::
inline_native_hashcode
(
bool
is_virtual
,
bool
is_static
)
{
bool
LibraryCallKit
::
inline_native_hashcode
(
bool
is_virtual
,
bool
is_static
)
{
assert
(
is_static
==
callee
()
->
is_static
(),
"correct intrinsic selection"
);
assert
(
is_static
==
callee
()
->
is_static
(),
"correct intrinsic selection"
);
assert
(
!
(
is_virtual
&&
is_static
),
"either virtual, special, or static"
);
assert
(
!
(
is_virtual
&&
is_static
),
"either virtual, special, or static"
);
...
@@ -3987,11 +3990,9 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
...
@@ -3987,11 +3990,9 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
enum
{
_slow_path
=
1
,
_fast_path
,
_null_path
,
PATH_LIMIT
};
enum
{
_slow_path
=
1
,
_fast_path
,
_null_path
,
PATH_LIMIT
};
RegionNode
*
result_reg
=
new
(
C
)
RegionNode
(
PATH_LIMIT
);
RegionNode
*
result_reg
=
new
(
C
)
RegionNode
(
PATH_LIMIT
);
PhiNode
*
result_val
=
new
(
C
)
PhiNode
(
result_reg
,
PhiNode
*
result_val
=
new
(
C
)
PhiNode
(
result_reg
,
TypeInt
::
INT
);
TypeInt
::
INT
);
PhiNode
*
result_io
=
new
(
C
)
PhiNode
(
result_reg
,
Type
::
ABIO
);
PhiNode
*
result_io
=
new
(
C
)
PhiNode
(
result_reg
,
Type
::
ABIO
);
PhiNode
*
result_mem
=
new
(
C
)
PhiNode
(
result_reg
,
Type
::
MEMORY
,
PhiNode
*
result_mem
=
new
(
C
)
PhiNode
(
result_reg
,
Type
::
MEMORY
,
TypePtr
::
BOTTOM
);
TypePtr
::
BOTTOM
);
Node
*
obj
=
NULL
;
Node
*
obj
=
NULL
;
if
(
!
is_static
)
{
if
(
!
is_static
)
{
// Check for hashing null object
// Check for hashing null object
...
@@ -4017,12 +4018,6 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
...
@@ -4017,12 +4018,6 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
return
true
;
return
true
;
}
}
// After null check, get the object's klass.
Node
*
obj_klass
=
load_object_klass
(
obj
);
// This call may be virtual (invokevirtual) or bound (invokespecial).
// For each case we generate slightly different code.
// We only go to the fast case code if we pass a number of guards. The
// We only go to the fast case code if we pass a number of guards. The
// paths which do not pass are accumulated in the slow_region.
// paths which do not pass are accumulated in the slow_region.
RegionNode
*
slow_region
=
new
(
C
)
RegionNode
(
1
);
RegionNode
*
slow_region
=
new
(
C
)
RegionNode
(
1
);
...
@@ -4035,19 +4030,24 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
...
@@ -4035,19 +4030,24 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
// guard for non-virtual calls -- the caller is known to be the native
// guard for non-virtual calls -- the caller is known to be the native
// Object hashCode().
// Object hashCode().
if
(
is_virtual
)
{
if
(
is_virtual
)
{
// After null check, get the object's klass.
Node
*
obj_klass
=
load_object_klass
(
obj
);
generate_virtual_guard
(
obj_klass
,
slow_region
);
generate_virtual_guard
(
obj_klass
,
slow_region
);
}
}
// Get the header out of the object, use LoadMarkNode when available
// Get the header out of the object, use LoadMarkNode when available
Node
*
header_addr
=
basic_plus_adr
(
obj
,
oopDesc
::
mark_offset_in_bytes
());
Node
*
header_addr
=
basic_plus_adr
(
obj
,
oopDesc
::
mark_offset_in_bytes
());
Node
*
header
=
make_load
(
control
(),
header_addr
,
TypeX_X
,
TypeX_X
->
basic_type
(),
MemNode
::
unordered
);
// The control of the load must be NULL. Otherwise, the load can move before
// the null check after castPP removal.
Node
*
no_ctrl
=
NULL
;
Node
*
header
=
make_load
(
no_ctrl
,
header_addr
,
TypeX_X
,
TypeX_X
->
basic_type
(),
MemNode
::
unordered
);
// Test the header to see if it is unlocked.
// Test the header to see if it is unlocked.
Node
*
lock_mask
=
_gvn
.
MakeConX
(
markOopDesc
::
biased_lock_mask_in_place
);
Node
*
lock_mask
=
_gvn
.
MakeConX
(
markOopDesc
::
biased_lock_mask_in_place
);
Node
*
lmasked_header
=
_gvn
.
transform
(
new
(
C
)
AndXNode
(
header
,
lock_mask
));
Node
*
lmasked_header
=
_gvn
.
transform
(
new
(
C
)
AndXNode
(
header
,
lock_mask
));
Node
*
unlocked_val
=
_gvn
.
MakeConX
(
markOopDesc
::
unlocked_value
);
Node
*
unlocked_val
=
_gvn
.
MakeConX
(
markOopDesc
::
unlocked_value
);
Node
*
chk_unlocked
=
_gvn
.
transform
(
new
(
C
)
CmpXNode
(
lmasked_header
,
unlocked_val
));
Node
*
chk_unlocked
=
_gvn
.
transform
(
new
(
C
)
CmpXNode
(
lmasked_header
,
unlocked_val
));
Node
*
test_unlocked
=
_gvn
.
transform
(
new
(
C
)
BoolNode
(
chk_unlocked
,
BoolTest
::
ne
));
Node
*
test_unlocked
=
_gvn
.
transform
(
new
(
C
)
BoolNode
(
chk_unlocked
,
BoolTest
::
ne
));
generate_slow_guard
(
test_unlocked
,
slow_region
);
generate_slow_guard
(
test_unlocked
,
slow_region
);
...
@@ -4055,19 +4055,19 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
...
@@ -4055,19 +4055,19 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
// We depend on hash_mask being at most 32 bits and avoid the use of
// We depend on hash_mask being at most 32 bits and avoid the use of
// hash_mask_in_place because it could be larger than 32 bits in a 64-bit
// hash_mask_in_place because it could be larger than 32 bits in a 64-bit
// vm: see markOop.hpp.
// vm: see markOop.hpp.
Node
*
hash_mask
=
_gvn
.
intcon
(
markOopDesc
::
hash_mask
);
Node
*
hash_mask
=
_gvn
.
intcon
(
markOopDesc
::
hash_mask
);
Node
*
hash_shift
=
_gvn
.
intcon
(
markOopDesc
::
hash_shift
);
Node
*
hash_shift
=
_gvn
.
intcon
(
markOopDesc
::
hash_shift
);
Node
*
hshifted_header
=
_gvn
.
transform
(
new
(
C
)
URShiftXNode
(
header
,
hash_shift
));
Node
*
hshifted_header
=
_gvn
.
transform
(
new
(
C
)
URShiftXNode
(
header
,
hash_shift
));
// This hack lets the hash bits live anywhere in the mark object now, as long
// This hack lets the hash bits live anywhere in the mark object now, as long
// as the shift drops the relevant bits into the low 32 bits. Note that
// as the shift drops the relevant bits into the low 32 bits. Note that
// Java spec says that HashCode is an int so there's no point in capturing
// Java spec says that HashCode is an int so there's no point in capturing
// an 'X'-sized hashcode (32 in 32-bit build or 64 in 64-bit build).
// an 'X'-sized hashcode (32 in 32-bit build or 64 in 64-bit build).
hshifted_header
=
ConvX2I
(
hshifted_header
);
hshifted_header
=
ConvX2I
(
hshifted_header
);
Node
*
hash_val
=
_gvn
.
transform
(
new
(
C
)
AndINode
(
hshifted_header
,
hash_mask
));
Node
*
hash_val
=
_gvn
.
transform
(
new
(
C
)
AndINode
(
hshifted_header
,
hash_mask
));
Node
*
no_hash_val
=
_gvn
.
intcon
(
markOopDesc
::
no_hash
);
Node
*
no_hash_val
=
_gvn
.
intcon
(
markOopDesc
::
no_hash
);
Node
*
chk_assigned
=
_gvn
.
transform
(
new
(
C
)
CmpINode
(
hash_val
,
no_hash_val
));
Node
*
chk_assigned
=
_gvn
.
transform
(
new
(
C
)
CmpINode
(
hash_val
,
no_hash_val
));
Node
*
test_assigned
=
_gvn
.
transform
(
new
(
C
)
BoolNode
(
chk_assigned
,
BoolTest
::
eq
));
Node
*
test_assigned
=
_gvn
.
transform
(
new
(
C
)
BoolNode
(
chk_assigned
,
BoolTest
::
eq
));
generate_slow_guard
(
test_assigned
,
slow_region
);
generate_slow_guard
(
test_assigned
,
slow_region
);
...
...
src/share/vm/prims/jvm.cpp
浏览文件 @
2cf3ff27
...
@@ -392,6 +392,23 @@ JVM_ENTRY(jobject, JVM_InitProperties(JNIEnv *env, jobject properties))
...
@@ -392,6 +392,23 @@ JVM_ENTRY(jobject, JVM_InitProperties(JNIEnv *env, jobject properties))
JVM_END
JVM_END
/*
* Return the temporary directory that the VM uses for the attach
* and perf data files.
*
* It is important that this directory is well-known and the
* same for all VM instances. It cannot be affected by configuration
* variables such as java.io.tmpdir.
*/
JVM_ENTRY
(
jstring
,
JVM_GetTemporaryDirectory
(
JNIEnv
*
env
))
JVMWrapper
(
"JVM_GetTemporaryDirectory"
);
HandleMark
hm
(
THREAD
);
const
char
*
temp_dir
=
os
::
get_temp_directory
();
Handle
h
=
java_lang_String
::
create_from_platform_dependent_str
(
temp_dir
,
CHECK_NULL
);
return
(
jstring
)
JNIHandles
::
make_local
(
env
,
h
());
JVM_END
// java.lang.Runtime /////////////////////////////////////////////////////////////////////////
// java.lang.Runtime /////////////////////////////////////////////////////////////////////////
extern
volatile
jint
vm_created
;
extern
volatile
jint
vm_created
;
...
...
src/share/vm/prims/jvm.h
浏览文件 @
2cf3ff27
...
@@ -1485,6 +1485,9 @@ JVM_GetManagement(jint version);
...
@@ -1485,6 +1485,9 @@ JVM_GetManagement(jint version);
JNIEXPORT
jobject
JNICALL
JNIEXPORT
jobject
JNICALL
JVM_InitAgentProperties
(
JNIEnv
*
env
,
jobject
agent_props
);
JVM_InitAgentProperties
(
JNIEnv
*
env
,
jobject
agent_props
);
JNIEXPORT
jstring
JNICALL
JVM_GetTemporaryDirectory
(
JNIEnv
*
env
);
/* Generics reflection support.
/* Generics reflection support.
*
*
* Returns information about the given class's EnclosingMethod
* Returns information about the given class's EnclosingMethod
...
...
src/share/vm/runtime/objectMonitor.cpp
浏览文件 @
2cf3ff27
...
@@ -418,6 +418,15 @@ void ATTR ObjectMonitor::enter(TRAPS) {
...
@@ -418,6 +418,15 @@ void ATTR ObjectMonitor::enter(TRAPS) {
jt
->
java_suspend_self
();
jt
->
java_suspend_self
();
}
}
Self
->
set_current_pending_monitor
(
NULL
);
Self
->
set_current_pending_monitor
(
NULL
);
// We cleared the pending monitor info since we've just gotten past
// the enter-check-for-suspend dance and we now own the monitor free
// and clear, i.e., it is no longer pending. The ThreadBlockInVM
// destructor can go to a safepoint at the end of this block. If we
// do a thread dump during that safepoint, then this thread will show
// as having "-locked" the monitor, but the OS and java.lang.Thread
// states will still report that the thread is blocked trying to
// acquire it.
}
}
Atomic
::
dec_ptr
(
&
_count
);
Atomic
::
dec_ptr
(
&
_count
);
...
...
src/share/vm/runtime/vframe.cpp
浏览文件 @
2cf3ff27
...
@@ -199,6 +199,7 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
...
@@ -199,6 +199,7 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
continue
;
continue
;
}
}
if
(
monitor
->
owner
()
!=
NULL
)
{
if
(
monitor
->
owner
()
!=
NULL
)
{
// the monitor is associated with an object, i.e., it is locked
// First, assume we have the monitor locked. If we haven't found an
// First, assume we have the monitor locked. If we haven't found an
// owned monitor before and this is the first frame, then we need to
// owned monitor before and this is the first frame, then we need to
...
@@ -209,7 +210,11 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
...
@@ -209,7 +210,11 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
if
(
!
found_first_monitor
&&
frame_count
==
0
)
{
if
(
!
found_first_monitor
&&
frame_count
==
0
)
{
markOop
mark
=
monitor
->
owner
()
->
mark
();
markOop
mark
=
monitor
->
owner
()
->
mark
();
if
(
mark
->
has_monitor
()
&&
if
(
mark
->
has_monitor
()
&&
mark
->
monitor
()
==
thread
()
->
current_pending_monitor
())
{
(
// we have marked ourself as pending on this monitor
mark
->
monitor
()
==
thread
()
->
current_pending_monitor
()
||
// we are not the owner of this monitor
!
mark
->
monitor
()
->
is_entered
(
thread
())
))
{
lock_state
=
"waiting to lock"
;
lock_state
=
"waiting to lock"
;
}
}
}
}
...
...
test/TEST.groups
浏览文件 @
2cf3ff27
#
#
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2013,
2014,
Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
#
# This code is free software; you can redistribute it and/or modify it
# This code is free software; you can redistribute it and/or modify it
...
@@ -84,6 +84,7 @@ needs_jdk = \
...
@@ -84,6 +84,7 @@ needs_jdk = \
runtime/NMT/ThreadedVirtualAllocTestType.java \
runtime/NMT/ThreadedVirtualAllocTestType.java \
runtime/NMT/VirtualAllocTestType.java \
runtime/NMT/VirtualAllocTestType.java \
runtime/RedefineObject/TestRedefineObject.java \
runtime/RedefineObject/TestRedefineObject.java \
runtime/Thread/TestThreadDumpMonitorContention.java \
runtime/XCheckJniJsig/XCheckJSig.java \
runtime/XCheckJniJsig/XCheckJSig.java \
serviceability/attach/AttachWithStalePidFile.java \
serviceability/attach/AttachWithStalePidFile.java \
serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
...
...
test/compiler/EscapeAnalysis/TestAllocatedEscapesPtrComparison.java
0 → 100644
浏览文件 @
2cf3ff27
/*
* Copyright 2014 Google, 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 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 8043354
* @summary bcEscapeAnalyzer allocated_escapes not conservative enough
* @run main/othervm -XX:CompileOnly=.visitAndPop TestAllocatedEscapesPtrComparison
* @author Chuck Rasbold rasbold@google.com
*/
/*
* Test always passes with -XX:-OptmimizePtrCompare
*/
import
java.util.ArrayList
;
import
java.util.List
;
public
class
TestAllocatedEscapesPtrComparison
{
static
TestAllocatedEscapesPtrComparison
dummy
;
class
Marker
{
}
List
<
Marker
>
markerList
=
new
ArrayList
<>();
// Suppress compilation of this method, it must be processed
// by the bytecode escape analyzer.
// Make a new marker and put it on the List
Marker
getMarker
()
{
// result escapes through markerList
final
Marker
result
=
new
Marker
();
markerList
.
add
(
result
);
return
result
;
}
void
visit
(
int
depth
)
{
// Make a new marker
getMarker
();
// Call visitAndPop every once in a while
// Cap the depth of our recursive visits
if
(
depth
%
10
==
2
)
{
visitAndPop
(
depth
+
1
);
}
else
if
(
depth
<
15
)
{
visit
(
depth
+
1
);
}
}
void
visitAndPop
(
int
depth
)
{
// Random dummy allocation to force EscapeAnalysis to process this method
dummy
=
new
TestAllocatedEscapesPtrComparison
();
// Make a new marker
Marker
marker
=
getMarker
();
visit
(
depth
+
1
);
// Walk and pop the marker list up to the current marker
boolean
found
=
false
;
for
(
int
i
=
markerList
.
size
()
-
1
;
i
>=
0
;
i
--)
{
Marker
removed
=
markerList
.
remove
(
i
);
// In the failure, EA mistakenly converts this comparison to false
if
(
removed
==
marker
)
{
found
=
true
;
break
;
}
}
if
(!
found
)
{
throw
new
RuntimeException
(
"test fails"
);
}
}
public
static
void
main
(
String
args
[])
{
TestAllocatedEscapesPtrComparison
tc
=
new
TestAllocatedEscapesPtrComparison
();
// Warmup and run enough times
for
(
int
i
=
0
;
i
<
20000
;
i
++)
{
tc
.
visit
(
0
);
}
}
}
test/
gc/g1/TestStringDeduplicationMemoryUsag
e.java
→
test/
compiler/intrinsics/hashcode/TestHashCod
e.java
浏览文件 @
2cf3ff27
...
@@ -22,15 +22,52 @@
...
@@ -22,15 +22,52 @@
*/
*/
/*
/*
* @test
TestStringDeduplicationMemoryUsage
* @test
* @
summary Test string deduplication memory usage
* @
bug 8011646
* @
bug 8029075
* @
summary SEGV in compiled code with loop predication
* @
key gc
* @
run main/othervm -XX:-TieredCompilation -XX:CompileOnly=TestHashCode.m1,Object.hashCode TestHashCode
*
@library /testlibrary
*
*/
*/
public
class
TestStringDeduplicationMemoryUsage
{
public
class
TestHashCode
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
static
class
A
{
TestStringDeduplicationTools
.
testMemoryUsage
();
int
i
;
}
static
class
B
extends
A
{
}
static
boolean
crash
=
false
;
static
A
m2
()
{
if
(
crash
)
{
return
null
;
}
return
new
A
();
}
static
int
m1
(
A
aa
)
{
int
res
=
0
;
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
A
a
=
m2
();
int
j
=
a
.
i
;
if
(
aa
instanceof
B
)
{
}
res
+=
a
.
hashCode
();
}
return
res
;
}
public
static
void
main
(
String
[]
args
)
{
A
a
=
new
A
();
for
(
int
i
=
0
;
i
<
20000
;
i
++)
{
m1
(
a
);
}
crash
=
true
;
try
{
m1
(
a
);
}
catch
(
NullPointerException
e
)
{
System
.
out
.
println
(
"Test passed"
);
}
}
}
}
}
test/gc/g1/TestStringDeduplicationTools.java
浏览文件 @
2cf3ff27
...
@@ -294,55 +294,6 @@ class TestStringDeduplicationTools {
...
@@ -294,55 +294,6 @@ class TestStringDeduplicationTools {
}
}
}
}
private
static
class
MemoryUsageTest
{
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
"Begin: MemoryUsageTest"
);
final
boolean
useStringDeduplication
=
Boolean
.
parseBoolean
(
args
[
0
]);
final
int
numberOfStrings
=
LargeNumberOfStrings
;
final
int
numberOfUniqueStrings
=
1
;
ArrayList
<
String
>
list
=
createStrings
(
numberOfStrings
,
numberOfUniqueStrings
);
forceDeduplication
(
DefaultAgeThreshold
,
FullGC
);
if
(
useStringDeduplication
)
{
verifyStrings
(
list
,
numberOfUniqueStrings
);
}
System
.
gc
();
System
.
out
.
println
(
"Heap Memory Usage: "
+
ManagementFactory
.
getMemoryMXBean
().
getHeapMemoryUsage
().
getUsed
());
System
.
out
.
println
(
"Array Header Size: "
+
unsafe
.
ARRAY_CHAR_BASE_OFFSET
);
System
.
out
.
println
(
"End: MemoryUsageTest"
);
}
public
static
OutputAnalyzer
run
(
boolean
useStringDeduplication
)
throws
Exception
{
String
[]
extraArgs
=
new
String
[
0
];
if
(
useStringDeduplication
)
{
extraArgs
=
new
String
[]
{
"-XX:+UseStringDeduplication"
,
"-XX:+PrintStringDeduplicationStatistics"
,
"-XX:StringDeduplicationAgeThreshold="
+
DefaultAgeThreshold
};
}
String
[]
defaultArgs
=
new
String
[]
{
"-XX:+PrintGC"
,
"-XX:+PrintGCDetails"
,
MemoryUsageTest
.
class
.
getName
(),
""
+
useStringDeduplication
};
ArrayList
<
String
>
args
=
new
ArrayList
<
String
>();
args
.
addAll
(
Arrays
.
asList
(
extraArgs
));
args
.
addAll
(
Arrays
.
asList
(
defaultArgs
));
return
runTest
(
args
.
toArray
(
new
String
[
args
.
size
()]));
}
}
/*
/*
* Tests
* Tests
*/
*/
...
@@ -480,44 +431,4 @@ class TestStringDeduplicationTools {
...
@@ -480,44 +431,4 @@ class TestStringDeduplicationTools {
OutputAnalyzer
output
=
InternedTest
.
run
();
OutputAnalyzer
output
=
InternedTest
.
run
();
output
.
shouldHaveExitValue
(
0
);
output
.
shouldHaveExitValue
(
0
);
}
}
public
static
void
testMemoryUsage
()
throws
Exception
{
// Test that memory usage is reduced after deduplication
OutputAnalyzer
output
;
final
String
heapMemoryUsagePattern
=
"Heap Memory Usage: (\\d+)"
;
final
String
arrayHeaderSizePattern
=
"Array Header Size: (\\d+)"
;
// Run without deduplication
output
=
MemoryUsageTest
.
run
(
false
);
output
.
shouldHaveExitValue
(
0
);
final
long
heapMemoryUsageWithoutDedup
=
Long
.
parseLong
(
output
.
firstMatch
(
heapMemoryUsagePattern
,
1
));
final
long
arrayHeaderSizeWithoutDedup
=
Long
.
parseLong
(
output
.
firstMatch
(
arrayHeaderSizePattern
,
1
));
// Run with deduplication
output
=
MemoryUsageTest
.
run
(
true
);
output
.
shouldHaveExitValue
(
0
);
final
long
heapMemoryUsageWithDedup
=
Long
.
parseLong
(
output
.
firstMatch
(
heapMemoryUsagePattern
,
1
));
final
long
arrayHeaderSizeWithDedup
=
Long
.
parseLong
(
output
.
firstMatch
(
arrayHeaderSizePattern
,
1
));
// Sanity check to make sure one instance isn't using compressed class pointers and the other not
if
(
arrayHeaderSizeWithoutDedup
!=
arrayHeaderSizeWithDedup
)
{
throw
new
Exception
(
"Unexpected difference between array header sizes"
);
}
// Calculate expected memory usage with deduplication enabled. This calculation does
// not take alignment and padding into account, so it's a conservative estimate.
final
long
sizeOfChar
=
unsafe
.
ARRAY_CHAR_INDEX_SCALE
;
final
long
sizeOfCharArray
=
StringLength
*
sizeOfChar
+
arrayHeaderSizeWithoutDedup
;
final
long
bytesSaved
=
(
LargeNumberOfStrings
-
1
)
*
sizeOfCharArray
;
final
long
heapMemoryUsageWithDedupExpected
=
heapMemoryUsageWithoutDedup
-
bytesSaved
;
System
.
out
.
println
(
"Memory usage summary:"
);
System
.
out
.
println
(
" heapMemoryUsageWithoutDedup: "
+
heapMemoryUsageWithoutDedup
);
System
.
out
.
println
(
" heapMemoryUsageWithDedup: "
+
heapMemoryUsageWithDedup
);
System
.
out
.
println
(
" heapMemoryUsageWithDedupExpected: "
+
heapMemoryUsageWithDedupExpected
);
if
(
heapMemoryUsageWithDedup
>
heapMemoryUsageWithDedupExpected
)
{
throw
new
Exception
(
"Unexpected memory usage, heapMemoryUsageWithDedup should be less or equal to heapMemoryUsageWithDedupExpected"
);
}
}
}
}
test/runtime/Thread/TestThreadDumpMonitorContention.java
0 → 100644
浏览文件 @
2cf3ff27
/*
* Copyright (c) 2014, 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 8036823
* @summary Creates two threads contending for the same lock and checks
* whether jstack reports "locked" by more than one thread.
*
* @library /testlibrary
* @run main/othervm TestThreadDumpMonitorContention
*/
import
java.io.BufferedReader
;
import
java.io.InputStreamReader
;
import
java.lang.management.ManagementFactory
;
import
java.lang.management.RuntimeMXBean
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
com.oracle.java.testlibrary.*
;
public
class
TestThreadDumpMonitorContention
{
// jstack tends to be closely bound to the VM that we are running
// so use getTestJDKTool() instead of getCompileJDKTool() or even
// getJDKTool() which can fall back to "compile.jdk".
final
static
String
JSTACK
=
JDKToolFinder
.
getTestJDKTool
(
"jstack"
);
final
static
String
PID
=
getPid
();
// looking for header lines with these patterns:
// "ContendingThread-1" #19 prio=5 os_prio=64 tid=0x000000000079c000 nid=0x23 runnable [0xffff80ffb8b87000]
// "ContendingThread-2" #21 prio=5 os_prio=64 tid=0x0000000000780000 nid=0x2f waiting for monitor entry [0xfffffd7fc1111000]
final
static
Pattern
HEADER_PREFIX_PATTERN
=
Pattern
.
compile
(
"^\"ContendingThread-.*"
);
final
static
Pattern
HEADER_WAITING_PATTERN
=
Pattern
.
compile
(
"^\"ContendingThread-.* waiting for monitor entry .*"
);
final
static
Pattern
HEADER_RUNNABLE_PATTERN
=
Pattern
.
compile
(
"^\"ContendingThread-.* runnable .*"
);
// looking for thread state lines with these patterns:
// java.lang.Thread.State: RUNNABLE
// java.lang.Thread.State: BLOCKED (on object monitor)
final
static
Pattern
THREAD_STATE_PREFIX_PATTERN
=
Pattern
.
compile
(
" *java\\.lang\\.Thread\\.State: .*"
);
final
static
Pattern
THREAD_STATE_BLOCKED_PATTERN
=
Pattern
.
compile
(
" *java\\.lang\\.Thread\\.State: BLOCKED \\(on object monitor\\)"
);
final
static
Pattern
THREAD_STATE_RUNNABLE_PATTERN
=
Pattern
.
compile
(
" *java\\.lang\\.Thread\\.State: RUNNABLE"
);
// looking for duplicates of this pattern:
// - locked <0x000000076ac59e20> (a TestThreadDumpMonitorContention$1)
final
static
Pattern
LOCK_PATTERN
=
Pattern
.
compile
(
".* locked \\<.*\\(a TestThreadDumpMonitorContention.*"
);
// sanity checking header and thread state lines associated
// with this pattern:
// - waiting to lock <0x000000076ac59e20> (a TestThreadDumpMonitorContention$1)
final
static
Pattern
WAITING_PATTERN
=
Pattern
.
compile
(
".* waiting to lock \\<.*\\(a TestThreadDumpMonitorContention.*"
);
volatile
static
boolean
done
=
false
;
static
int
error_cnt
=
0
;
static
String
header_line
=
null
;
static
boolean
have_header_line
=
false
;
static
boolean
have_thread_state_line
=
false
;
static
int
match_cnt
=
0
;
static
String
[]
match_list
=
new
String
[
2
];
static
int
n_samples
=
15
;
static
String
thread_state_line
=
null
;
static
boolean
verbose
=
false
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
if
(
args
.
length
!=
0
)
{
int
arg_i
=
0
;
if
(
args
[
arg_i
].
equals
(
"-v"
))
{
verbose
=
true
;
arg_i
++;
}
try
{
n_samples
=
Integer
.
parseInt
(
args
[
arg_i
]);
}
catch
(
NumberFormatException
nfe
)
{
System
.
err
.
println
(
nfe
);
usage
();
}
}
Runnable
runnable
=
new
Runnable
()
{
public
void
run
()
{
while
(!
done
)
{
synchronized
(
this
)
{
}
}
}
};
Thread
[]
thread_list
=
new
Thread
[
2
];
thread_list
[
0
]
=
new
Thread
(
runnable
,
"ContendingThread-1"
);
thread_list
[
1
]
=
new
Thread
(
runnable
,
"ContendingThread-2"
);
thread_list
[
0
].
start
();
thread_list
[
1
].
start
();
doSamples
();
done
=
true
;
thread_list
[
0
].
join
();
thread_list
[
1
].
join
();
if
(
error_cnt
==
0
)
{
System
.
out
.
println
(
"Test PASSED."
);
}
else
{
System
.
out
.
println
(
"Test FAILED."
);
throw
new
AssertionError
(
"error_cnt="
+
error_cnt
);
}
}
// Reached a blank line which is the end of the
// stack trace without matching either LOCK_PATTERN
// or WAITING_PATTERN. Rare, but it's not an error.
//
// Example:
// "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f runnable [0xfffffd7fc1111000]
// java.lang.Thread.State: RUNNABLE
// at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:67)
// at java.lang.Thread.run(Thread.java:745)
//
static
boolean
checkBlankLine
(
String
line
)
{
if
(
line
.
length
()
==
0
)
{
have_header_line
=
false
;
have_thread_state_line
=
false
;
return
true
;
}
return
false
;
}
// Process the locked line here if we found one.
//
// Example 1:
// "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f runnable [0xfffffd7fc1111000]
// java.lang.Thread.State: RUNNABLE
// at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:67)
// - locked <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1)
// at java.lang.Thread.run(Thread.java:745)
//
// Example 2:
// "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f waiting for monitor entry [0xfffffd7fc1111000]
// java.lang.Thread.State: BLOCKED (on object monitor)
// at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:67)
// - locked <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1)
// at java.lang.Thread.run(Thread.java:745)
//
static
boolean
checkLockedLine
(
String
line
)
{
Matcher
matcher
=
LOCK_PATTERN
.
matcher
(
line
);
if
(
matcher
.
matches
())
{
if
(
verbose
)
{
System
.
out
.
println
(
"locked_line='"
+
line
+
"'"
);
}
match_list
[
match_cnt
]
=
new
String
(
line
);
match_cnt
++;
matcher
=
HEADER_RUNNABLE_PATTERN
.
matcher
(
header_line
);
if
(!
matcher
.
matches
())
{
// It's strange, but a locked line can also
// match the HEADER_WAITING_PATTERN.
matcher
=
HEADER_WAITING_PATTERN
.
matcher
(
header_line
);
if
(!
matcher
.
matches
())
{
System
.
err
.
println
();
System
.
err
.
println
(
"ERROR: header line does "
+
"not match runnable or waiting patterns."
);
System
.
err
.
println
(
"ERROR: header_line='"
+
header_line
+
"'"
);
System
.
err
.
println
(
"ERROR: locked_line='"
+
line
+
"'"
);
error_cnt
++;
}
}
matcher
=
THREAD_STATE_RUNNABLE_PATTERN
.
matcher
(
thread_state_line
);
if
(!
matcher
.
matches
())
{
// It's strange, but a locked line can also
// match the THREAD_STATE_BLOCKED_PATTERN.
matcher
=
THREAD_STATE_BLOCKED_PATTERN
.
matcher
(
thread_state_line
);
if
(!
matcher
.
matches
())
{
System
.
err
.
println
();
System
.
err
.
println
(
"ERROR: thread state line does not "
+
"match runnable or waiting patterns."
);
System
.
err
.
println
(
"ERROR: "
+
"thread_state_line='"
+
thread_state_line
+
"'"
);
System
.
err
.
println
(
"ERROR: locked_line='"
+
line
+
"'"
);
error_cnt
++;
}
}
// Have everything we need from this thread stack
// that matches the LOCK_PATTERN.
have_header_line
=
false
;
have_thread_state_line
=
false
;
return
true
;
}
return
false
;
}
// Process the waiting line here if we found one.
//
// Example:
// "ContendingThread-2" #22 prio=5 os_prio=64 tid=0x00000000007b9800 nid=0x30 waiting for monitor entry [0xfffffd7fc1010000]
// java.lang.Thread.State: BLOCKED (on object monitor)
// at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:67)
// - waiting to lock <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1)
// at java.lang.Thread.run(Thread.java:745)
//
static
boolean
checkWaitingLine
(
String
line
)
{
Matcher
matcher
=
WAITING_PATTERN
.
matcher
(
line
);
if
(
matcher
.
matches
())
{
if
(
verbose
)
{
System
.
out
.
println
(
"waiting_line='"
+
line
+
"'"
);
}
matcher
=
HEADER_WAITING_PATTERN
.
matcher
(
header_line
);
if
(!
matcher
.
matches
())
{
System
.
err
.
println
();
System
.
err
.
println
(
"ERROR: header line does "
+
"not match a waiting pattern."
);
System
.
err
.
println
(
"ERROR: header_line='"
+
header_line
+
"'"
);
System
.
err
.
println
(
"ERROR: waiting_line='"
+
line
+
"'"
);
error_cnt
++;
}
matcher
=
THREAD_STATE_BLOCKED_PATTERN
.
matcher
(
thread_state_line
);
if
(!
matcher
.
matches
())
{
System
.
err
.
println
();
System
.
err
.
println
(
"ERROR: thread state line "
+
"does not match a waiting pattern."
);
System
.
err
.
println
(
"ERROR: thread_state_line='"
+
thread_state_line
+
"'"
);
System
.
err
.
println
(
"ERROR: waiting_line='"
+
line
+
"'"
);
error_cnt
++;
}
// Have everything we need from this thread stack
// that matches the WAITING_PATTERN.
have_header_line
=
false
;
have_thread_state_line
=
false
;
return
true
;
}
return
false
;
}
static
void
doSamples
()
throws
Exception
{
for
(
int
count
=
0
;
count
<
n_samples
;
count
++)
{
match_cnt
=
0
;
// verbose mode or an error has a lot of output so add more space
if
(
verbose
||
error_cnt
>
0
)
System
.
out
.
println
();
System
.
out
.
println
(
"Sample #"
+
count
);
// We don't use the ProcessTools, OutputBuffer or
// OutputAnalyzer classes from the testlibrary because
// we have a complicated multi-line parse to perform
// on a narrow subset of the JSTACK output.
//
// - we only care about stack traces that match
// HEADER_PREFIX_PATTERN; only two should match
// - we care about at most three lines from each stack trace
// - if both stack traces match LOCKED_PATTERN, then that's
// a failure and we report it
// - for a stack trace that matches LOCKED_PATTERN, we verify:
// - the header line matches HEADER_RUNNABLE_PATTERN
// or HEADER_WAITING_PATTERN
// - the thread state line matches THREAD_STATE_BLOCKED_PATTERN
// or THREAD_STATE_RUNNABLE_PATTERN
// - we report any mismatches as failures
// - for a stack trace that matches WAITING_PATTERN, we verify:
// - the header line matches HEADER_WAITING_PATTERN
// - the thread state line matches THREAD_STATE_BLOCKED_PATTERN
// - we report any mismatches as failures
// - the stack traces that match HEADER_PREFIX_PATTERN may
// not match either LOCKED_PATTERN or WAITING_PATTERN
// because we might observe the thread outside of
// monitor operations; this is not considered a failure
//
// When we do observe LOCKED_PATTERN or WAITING_PATTERN,
// then we are checking the header and thread state patterns
// that occurred earlier in the current stack trace that
// matched HEADER_PREFIX_PATTERN. We don't use data from
// stack traces that don't match HEADER_PREFIX_PATTERN and
// we don't mix data between the two stack traces that do
// match HEADER_PREFIX_PATTERN.
//
Process
process
=
new
ProcessBuilder
(
JSTACK
,
PID
)
.
redirectErrorStream
(
true
).
start
();
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
process
.
getInputStream
()));
String
line
;
while
((
line
=
reader
.
readLine
())
!=
null
)
{
Matcher
matcher
=
null
;
// process the header line here
if
(!
have_header_line
)
{
matcher
=
HEADER_PREFIX_PATTERN
.
matcher
(
line
);
if
(
matcher
.
matches
())
{
if
(
verbose
)
{
System
.
out
.
println
();
System
.
out
.
println
(
"header='"
+
line
+
"'"
);
}
header_line
=
new
String
(
line
);
have_header_line
=
true
;
continue
;
}
continue
;
// skip until have a header line
}
// process the thread state line here
if
(!
have_thread_state_line
)
{
matcher
=
THREAD_STATE_PREFIX_PATTERN
.
matcher
(
line
);
if
(
matcher
.
matches
())
{
if
(
verbose
)
{
System
.
out
.
println
(
"thread_state='"
+
line
+
"'"
);
}
thread_state_line
=
new
String
(
line
);
have_thread_state_line
=
true
;
continue
;
}
continue
;
// skip until we have a thread state line
}
// process the locked line here if we find one
if
(
checkLockedLine
(
line
))
{
continue
;
}
// process the waiting line here if we find one
if
(
checkWaitingLine
(
line
))
{
continue
;
}
// process the blank line here if we find one
if
(
checkBlankLine
(
line
))
{
continue
;
}
}
process
.
waitFor
();
if
(
match_cnt
==
2
)
{
if
(
match_list
[
0
].
equals
(
match_list
[
1
]))
{
System
.
err
.
println
();
System
.
err
.
println
(
"ERROR: matching lock lines:"
);
System
.
err
.
println
(
"ERROR: line[0]'"
+
match_list
[
0
]
+
"'"
);
System
.
err
.
println
(
"ERROR: line[1]'"
+
match_list
[
1
]
+
"'"
);
error_cnt
++;
}
}
// slight delay between jstack launches
Thread
.
sleep
(
500
);
}
}
// This helper relies on RuntimeMXBean.getName() returning a string
// that looks like this: 5436@mt-haku
//
// The testlibrary has tryFindJvmPid(), but that uses a separate
// process which is much more expensive for finding out your own PID.
//
static
String
getPid
()
{
RuntimeMXBean
runtimebean
=
ManagementFactory
.
getRuntimeMXBean
();
String
vmname
=
runtimebean
.
getName
();
int
i
=
vmname
.
indexOf
(
'@'
);
if
(
i
!=
-
1
)
{
vmname
=
vmname
.
substring
(
0
,
i
);
}
return
vmname
;
}
static
void
usage
()
{
System
.
err
.
println
(
"Usage: "
+
"java TestThreadDumpMonitorContention [-v] [n_samples]"
);
System
.
exit
(
1
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录