Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
cf041cfa
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看板
提交
cf041cfa
编写于
9月 20, 2013
作者:
D
dcubed
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
2f4a2dd8
f61dd06e
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
409 addition
and
340 deletion
+409
-340
src/share/vm/classfile/javaClasses.cpp
src/share/vm/classfile/javaClasses.cpp
+23
-0
src/share/vm/classfile/javaClasses.hpp
src/share/vm/classfile/javaClasses.hpp
+1
-0
src/share/vm/classfile/symbolTable.cpp
src/share/vm/classfile/symbolTable.cpp
+158
-0
src/share/vm/classfile/symbolTable.hpp
src/share/vm/classfile/symbolTable.hpp
+20
-0
src/share/vm/memory/metaspaceShared.cpp
src/share/vm/memory/metaspaceShared.cpp
+3
-2
src/share/vm/oops/instanceKlass.cpp
src/share/vm/oops/instanceKlass.cpp
+45
-112
src/share/vm/oops/instanceKlass.hpp
src/share/vm/oops/instanceKlass.hpp
+14
-57
src/share/vm/prims/jvm.cpp
src/share/vm/prims/jvm.cpp
+54
-63
src/share/vm/prims/jvmtiEnvBase.hpp
src/share/vm/prims/jvmtiEnvBase.hpp
+5
-1
src/share/vm/prims/jvmtiImpl.cpp
src/share/vm/prims/jvmtiImpl.cpp
+36
-46
src/share/vm/prims/jvmtiRedefineClasses.cpp
src/share/vm/prims/jvmtiRedefineClasses.cpp
+15
-24
src/share/vm/runtime/arguments.cpp
src/share/vm/runtime/arguments.cpp
+13
-24
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+3
-0
src/share/vm/runtime/handles.hpp
src/share/vm/runtime/handles.hpp
+2
-2
src/share/vm/runtime/handles.inline.hpp
src/share/vm/runtime/handles.inline.hpp
+2
-0
src/share/vm/runtime/java.cpp
src/share/vm/runtime/java.cpp
+13
-0
test/runtime/CDSCompressedKPtrs/XShareAuto.java
test/runtime/CDSCompressedKPtrs/XShareAuto.java
+2
-9
未找到文件。
src/share/vm/classfile/javaClasses.cpp
浏览文件 @
cf041cfa
...
...
@@ -438,6 +438,29 @@ bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
return
true
;
}
bool
java_lang_String
::
equals
(
oop
str1
,
oop
str2
)
{
assert
(
str1
->
klass
()
==
SystemDictionary
::
String_klass
(),
"must be java String"
);
assert
(
str2
->
klass
()
==
SystemDictionary
::
String_klass
(),
"must be java String"
);
typeArrayOop
value1
=
java_lang_String
::
value
(
str1
);
int
offset1
=
java_lang_String
::
offset
(
str1
);
int
length1
=
java_lang_String
::
length
(
str1
);
typeArrayOop
value2
=
java_lang_String
::
value
(
str2
);
int
offset2
=
java_lang_String
::
offset
(
str2
);
int
length2
=
java_lang_String
::
length
(
str2
);
if
(
length1
!=
length2
)
{
return
false
;
}
for
(
int
i
=
0
;
i
<
length1
;
i
++
)
{
if
(
value1
->
char_at
(
i
+
offset1
)
!=
value2
->
char_at
(
i
+
offset2
))
{
return
false
;
}
}
return
true
;
}
void
java_lang_String
::
print
(
Handle
java_string
,
outputStream
*
st
)
{
oop
obj
=
java_string
();
assert
(
obj
->
klass
()
==
SystemDictionary
::
String_klass
(),
"must be java_string"
);
...
...
src/share/vm/classfile/javaClasses.hpp
浏览文件 @
cf041cfa
...
...
@@ -182,6 +182,7 @@ class java_lang_String : AllStatic {
static
unsigned
int
hash_string
(
oop
java_string
);
static
bool
equals
(
oop
java_string
,
jchar
*
chars
,
int
len
);
static
bool
equals
(
oop
str1
,
oop
str2
);
// Conversion between '.' and '/' formats
static
Handle
externalize_classname
(
Handle
java_string
,
TRAPS
)
{
return
char_converter
(
java_string
,
'/'
,
'.'
,
THREAD
);
}
...
...
src/share/vm/classfile/symbolTable.cpp
浏览文件 @
cf041cfa
...
...
@@ -807,6 +807,8 @@ void StringTable::possibly_parallel_oops_do(OopClosure* f) {
}
}
// This verification is part of Universe::verify() and needs to be quick.
// See StringTable::verify_and_compare() below for exhaustive verification.
void
StringTable
::
verify
()
{
for
(
int
i
=
0
;
i
<
the_table
()
->
table_size
();
++
i
)
{
HashtableEntry
<
oop
,
mtSymbol
>*
p
=
the_table
()
->
bucket
(
i
);
...
...
@@ -825,6 +827,162 @@ void StringTable::dump(outputStream* st) {
the_table
()
->
dump_table
(
st
,
"StringTable"
);
}
StringTable
::
VerifyRetTypes
StringTable
::
compare_entries
(
int
bkt1
,
int
e_cnt1
,
HashtableEntry
<
oop
,
mtSymbol
>*
e_ptr1
,
int
bkt2
,
int
e_cnt2
,
HashtableEntry
<
oop
,
mtSymbol
>*
e_ptr2
)
{
// These entries are sanity checked by verify_and_compare_entries()
// before this function is called.
oop
str1
=
e_ptr1
->
literal
();
oop
str2
=
e_ptr2
->
literal
();
if
(
str1
==
str2
)
{
tty
->
print_cr
(
"ERROR: identical oop values (0x"
PTR_FORMAT
") "
"in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]"
,
str1
,
bkt1
,
e_cnt1
,
bkt2
,
e_cnt2
);
return
_verify_fail_continue
;
}
if
(
java_lang_String
::
equals
(
str1
,
str2
))
{
tty
->
print_cr
(
"ERROR: identical String values in entry @ "
"bucket[%d][%d] and entry @ bucket[%d][%d]"
,
bkt1
,
e_cnt1
,
bkt2
,
e_cnt2
);
return
_verify_fail_continue
;
}
return
_verify_pass
;
}
StringTable
::
VerifyRetTypes
StringTable
::
verify_entry
(
int
bkt
,
int
e_cnt
,
HashtableEntry
<
oop
,
mtSymbol
>*
e_ptr
,
StringTable
::
VerifyMesgModes
mesg_mode
)
{
VerifyRetTypes
ret
=
_verify_pass
;
// be optimistic
oop
str
=
e_ptr
->
literal
();
if
(
str
==
NULL
)
{
if
(
mesg_mode
==
_verify_with_mesgs
)
{
tty
->
print_cr
(
"ERROR: NULL oop value in entry @ bucket[%d][%d]"
,
bkt
,
e_cnt
);
}
// NULL oop means no more verifications are possible
return
_verify_fail_done
;
}
if
(
str
->
klass
()
!=
SystemDictionary
::
String_klass
())
{
if
(
mesg_mode
==
_verify_with_mesgs
)
{
tty
->
print_cr
(
"ERROR: oop is not a String in entry @ bucket[%d][%d]"
,
bkt
,
e_cnt
);
}
// not a String means no more verifications are possible
return
_verify_fail_done
;
}
unsigned
int
h
=
java_lang_String
::
hash_string
(
str
);
if
(
e_ptr
->
hash
()
!=
h
)
{
if
(
mesg_mode
==
_verify_with_mesgs
)
{
tty
->
print_cr
(
"ERROR: broken hash value in entry @ bucket[%d][%d], "
"bkt_hash=%d, str_hash=%d"
,
bkt
,
e_cnt
,
e_ptr
->
hash
(),
h
);
}
ret
=
_verify_fail_continue
;
}
if
(
the_table
()
->
hash_to_index
(
h
)
!=
bkt
)
{
if
(
mesg_mode
==
_verify_with_mesgs
)
{
tty
->
print_cr
(
"ERROR: wrong index value for entry @ bucket[%d][%d], "
"str_hash=%d, hash_to_index=%d"
,
bkt
,
e_cnt
,
h
,
the_table
()
->
hash_to_index
(
h
));
}
ret
=
_verify_fail_continue
;
}
return
ret
;
}
// See StringTable::verify() above for the quick verification that is
// part of Universe::verify(). This verification is exhaustive and
// reports on every issue that is found. StringTable::verify() only
// reports on the first issue that is found.
//
// StringTable::verify_entry() checks:
// - oop value != NULL (same as verify())
// - oop value is a String
// - hash(String) == hash in entry (same as verify())
// - index for hash == index of entry (same as verify())
//
// StringTable::compare_entries() checks:
// - oops are unique across all entries
// - String values are unique across all entries
//
int
StringTable
::
verify_and_compare_entries
()
{
assert
(
StringTable_lock
->
is_locked
(),
"sanity check"
);
int
fail_cnt
=
0
;
// first, verify all the entries individually:
for
(
int
bkt
=
0
;
bkt
<
the_table
()
->
table_size
();
bkt
++
)
{
HashtableEntry
<
oop
,
mtSymbol
>*
e_ptr
=
the_table
()
->
bucket
(
bkt
);
for
(
int
e_cnt
=
0
;
e_ptr
!=
NULL
;
e_ptr
=
e_ptr
->
next
(),
e_cnt
++
)
{
VerifyRetTypes
ret
=
verify_entry
(
bkt
,
e_cnt
,
e_ptr
,
_verify_with_mesgs
);
if
(
ret
!=
_verify_pass
)
{
fail_cnt
++
;
}
}
}
// Optimization: if the above check did not find any failures, then
// the comparison loop below does not need to call verify_entry()
// before calling compare_entries(). If there were failures, then we
// have to call verify_entry() to see if the entry can be passed to
// compare_entries() safely. When we call verify_entry() in the loop
// below, we do so quietly to void duplicate messages and we don't
// increment fail_cnt because the failures have already been counted.
bool
need_entry_verify
=
(
fail_cnt
!=
0
);
// second, verify all entries relative to each other:
for
(
int
bkt1
=
0
;
bkt1
<
the_table
()
->
table_size
();
bkt1
++
)
{
HashtableEntry
<
oop
,
mtSymbol
>*
e_ptr1
=
the_table
()
->
bucket
(
bkt1
);
for
(
int
e_cnt1
=
0
;
e_ptr1
!=
NULL
;
e_ptr1
=
e_ptr1
->
next
(),
e_cnt1
++
)
{
if
(
need_entry_verify
)
{
VerifyRetTypes
ret
=
verify_entry
(
bkt1
,
e_cnt1
,
e_ptr1
,
_verify_quietly
);
if
(
ret
==
_verify_fail_done
)
{
// cannot use the current entry to compare against other entries
continue
;
}
}
for
(
int
bkt2
=
bkt1
;
bkt2
<
the_table
()
->
table_size
();
bkt2
++
)
{
HashtableEntry
<
oop
,
mtSymbol
>*
e_ptr2
=
the_table
()
->
bucket
(
bkt2
);
int
e_cnt2
;
for
(
e_cnt2
=
0
;
e_ptr2
!=
NULL
;
e_ptr2
=
e_ptr2
->
next
(),
e_cnt2
++
)
{
if
(
bkt1
==
bkt2
&&
e_cnt2
<=
e_cnt1
)
{
// skip the entries up to and including the one that
// we're comparing against
continue
;
}
if
(
need_entry_verify
)
{
VerifyRetTypes
ret
=
verify_entry
(
bkt2
,
e_cnt2
,
e_ptr2
,
_verify_quietly
);
if
(
ret
==
_verify_fail_done
)
{
// cannot compare against this entry
continue
;
}
}
// compare two entries, report and count any failures:
if
(
compare_entries
(
bkt1
,
e_cnt1
,
e_ptr1
,
bkt2
,
e_cnt2
,
e_ptr2
)
!=
_verify_pass
)
{
fail_cnt
++
;
}
}
}
}
}
return
fail_cnt
;
}
// Create a new table and using alternate hash code, populate the new table
// with the existing strings. Set flag to use the alternate hash code afterwards.
...
...
src/share/vm/classfile/symbolTable.hpp
浏览文件 @
cf041cfa
...
...
@@ -311,6 +311,26 @@ public:
static
void
verify
();
static
void
dump
(
outputStream
*
st
);
enum
VerifyMesgModes
{
_verify_quietly
=
0
,
_verify_with_mesgs
=
1
};
enum
VerifyRetTypes
{
_verify_pass
=
0
,
_verify_fail_continue
=
1
,
_verify_fail_done
=
2
};
static
VerifyRetTypes
compare_entries
(
int
bkt1
,
int
e_cnt1
,
HashtableEntry
<
oop
,
mtSymbol
>*
e_ptr1
,
int
bkt2
,
int
e_cnt2
,
HashtableEntry
<
oop
,
mtSymbol
>*
e_ptr2
);
static
VerifyRetTypes
verify_entry
(
int
bkt
,
int
e_cnt
,
HashtableEntry
<
oop
,
mtSymbol
>*
e_ptr
,
VerifyMesgModes
mesg_mode
);
static
int
verify_and_compare_entries
();
// Sharing
static
void
copy_buckets
(
char
**
top
,
char
*
end
)
{
the_table
()
->
Hashtable
<
oop
,
mtSymbol
>::
copy_buckets
(
top
,
end
);
...
...
src/share/vm/memory/metaspaceShared.cpp
浏览文件 @
cf041cfa
...
...
@@ -103,9 +103,10 @@ static void calculate_fingerprints() {
if
(
k
->
oop_is_instance
())
{
InstanceKlass
*
ik
=
InstanceKlass
::
cast
(
k
);
for
(
int
i
=
0
;
i
<
ik
->
methods
()
->
length
();
i
++
)
{
ResourceMark
rm
;
Method
*
m
=
ik
->
methods
()
->
at
(
i
);
(
new
Fingerprinter
(
m
))
->
fingerprint
();
Fingerprinter
fp
(
m
);
// The side effect of this call sets method's fingerprint field.
fp
.
fingerprint
();
}
}
}
...
...
src/share/vm/oops/instanceKlass.cpp
浏览文件 @
cf041cfa
...
...
@@ -2769,24 +2769,17 @@ void InstanceKlass::print_on(outputStream* st) const {
st
->
print
(
BULLET
"field annotations: "
);
fields_annotations
()
->
print_value_on
(
st
);
st
->
cr
();
st
->
print
(
BULLET
"field type annotations: "
);
fields_type_annotations
()
->
print_value_on
(
st
);
st
->
cr
();
{
ResourceMark
rm
;
// PreviousVersionInfo objects returned via PreviousVersionWalker
// contain a GrowableArray of handles. We have to clean up the
// GrowableArray _after_ the PreviousVersionWalker destructor
// has destroyed the handles.
{
bool
have_pv
=
false
;
PreviousVersionWalker
pvw
((
InstanceKlass
*
)
this
);
for
(
PreviousVersionInfo
*
pv_info
=
pvw
.
next_previous_version
();
pv_info
!=
NULL
;
pv_info
=
pvw
.
next_previous_version
())
{
if
(
!
have_pv
)
st
->
print
(
BULLET
"previous version: "
);
have_pv
=
true
;
pv_info
->
prev_constant_pool_handle
()()
->
print_value_on
(
st
);
}
if
(
have_pv
)
st
->
cr
();
}
// pvw is cleaned up
}
// rm is cleaned up
bool
have_pv
=
false
;
PreviousVersionWalker
pvw
(
Thread
::
current
(),
(
InstanceKlass
*
)
this
);
for
(
PreviousVersionNode
*
pv_node
=
pvw
.
next_previous_version
();
pv_node
!=
NULL
;
pv_node
=
pvw
.
next_previous_version
())
{
if
(
!
have_pv
)
st
->
print
(
BULLET
"previous version: "
);
have_pv
=
true
;
pv_node
->
prev_constant_pool
()
->
print_value_on
(
st
);
}
if
(
have_pv
)
st
->
cr
();
}
// pvw is cleaned up
if
(
generic_signature
()
!=
NULL
)
{
st
->
print
(
BULLET
"generic signature: "
);
...
...
@@ -3317,34 +3310,34 @@ void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
Array
<
Method
*>*
old_methods
=
ikh
->
methods
();
if
(
cp_ref
->
on_stack
())
{
PreviousVersionNode
*
pv_node
=
NULL
;
if
(
emcp_method_count
==
0
)
{
PreviousVersionNode
*
pv_node
=
NULL
;
if
(
emcp_method_count
==
0
)
{
// non-shared ConstantPool gets a reference
pv_node
=
new
PreviousVersionNode
(
cp_ref
,
!
cp_ref
->
is_shared
(),
NULL
);
RC_TRACE
(
0x00000400
,
(
"add: all methods are obsolete; flushing any EMCP refs"
));
}
else
{
int
local_count
=
0
;
pv_node
=
new
PreviousVersionNode
(
cp_ref
,
NULL
);
RC_TRACE
(
0x00000400
,
(
"add: all methods are obsolete; flushing any EMCP refs"
));
}
else
{
int
local_count
=
0
;
GrowableArray
<
Method
*>*
method_refs
=
new
(
ResourceObj
::
C_HEAP
,
mtClass
)
GrowableArray
<
Method
*>
(
emcp_method_count
,
true
);
for
(
int
i
=
0
;
i
<
old_methods
->
length
();
i
++
)
{
if
(
emcp_methods
->
at
(
i
))
{
// this old method is EMCP. Save it only if it's on the stack
Method
*
old_method
=
old_methods
->
at
(
i
);
if
(
old_method
->
on_stack
())
{
method_refs
->
append
(
old_method
);
GrowableArray
<
Method
*>
(
emcp_method_count
,
true
);
for
(
int
i
=
0
;
i
<
old_methods
->
length
();
i
++
)
{
if
(
emcp_methods
->
at
(
i
))
{
// this old method is EMCP. Save it only if it's on the stack
Method
*
old_method
=
old_methods
->
at
(
i
);
if
(
old_method
->
on_stack
())
{
method_refs
->
append
(
old_method
);
}
if
(
++
local_count
>=
emcp_method_count
)
{
// no more EMCP methods so bail out now
break
;
}
if
(
++
local_count
>=
emcp_method_count
)
{
// no more EMCP methods so bail out now
break
;
}
}
}
// non-shared ConstantPool gets a reference
pv_node
=
new
PreviousVersionNode
(
cp_ref
,
!
cp_ref
->
is_shared
(),
method_refs
);
pv_node
=
new
PreviousVersionNode
(
cp_ref
,
method_refs
);
}
// append new previous version.
_previous_versions
->
append
(
pv_node
);
_previous_versions
->
append
(
pv_node
);
}
// Since the caller is the VMThread and we are at a safepoint, this
...
...
@@ -3445,6 +3438,8 @@ Method* InstanceKlass::method_with_idnum(int idnum) {
return
m
;
}
}
// None found, return null for the caller to handle.
return
NULL
;
}
return
m
;
}
...
...
@@ -3461,10 +3456,9 @@ unsigned char * InstanceKlass::get_cached_class_file_bytes() {
// Construct a PreviousVersionNode entry for the array hung off
// the InstanceKlass.
PreviousVersionNode
::
PreviousVersionNode
(
ConstantPool
*
prev_constant_pool
,
bool
prev_cp_is_weak
,
GrowableArray
<
Method
*>*
prev_EMCP_methods
)
{
GrowableArray
<
Method
*>*
prev_EMCP_methods
)
{
_prev_constant_pool
=
prev_constant_pool
;
_prev_cp_is_weak
=
prev_cp_is_weak
;
_prev_EMCP_methods
=
prev_EMCP_methods
;
}
...
...
@@ -3480,99 +3474,38 @@ PreviousVersionNode::~PreviousVersionNode() {
}
}
// Construct a PreviousVersionInfo entry
PreviousVersionInfo
::
PreviousVersionInfo
(
PreviousVersionNode
*
pv_node
)
{
_prev_constant_pool_handle
=
constantPoolHandle
();
// NULL handle
_prev_EMCP_method_handles
=
NULL
;
ConstantPool
*
cp
=
pv_node
->
prev_constant_pool
();
assert
(
cp
!=
NULL
,
"constant pool ref was unexpectedly cleared"
);
if
(
cp
==
NULL
)
{
return
;
// robustness
}
// make the ConstantPool* safe to return
_prev_constant_pool_handle
=
constantPoolHandle
(
cp
);
GrowableArray
<
Method
*>*
method_refs
=
pv_node
->
prev_EMCP_methods
();
if
(
method_refs
==
NULL
)
{
// the InstanceKlass did not have any EMCP methods
return
;
}
_prev_EMCP_method_handles
=
new
GrowableArray
<
methodHandle
>
(
10
);
int
n_methods
=
method_refs
->
length
();
for
(
int
i
=
0
;
i
<
n_methods
;
i
++
)
{
Method
*
method
=
method_refs
->
at
(
i
);
assert
(
method
!=
NULL
,
"method has been cleared"
);
if
(
method
==
NULL
)
{
continue
;
// robustness
}
// make the Method* safe to return
_prev_EMCP_method_handles
->
append
(
methodHandle
(
method
));
}
}
// Destroy a PreviousVersionInfo
PreviousVersionInfo
::~
PreviousVersionInfo
()
{
// Since _prev_EMCP_method_handles is not C-heap allocated, we
// don't have to delete it.
}
// Construct a helper for walking the previous versions array
PreviousVersionWalker
::
PreviousVersionWalker
(
InstanceKlass
*
ik
)
{
PreviousVersionWalker
::
PreviousVersionWalker
(
Thread
*
thread
,
InstanceKlass
*
ik
)
{
_thread
=
thread
;
_previous_versions
=
ik
->
previous_versions
();
_current_index
=
0
;
// _hm needs no initialization
_current_p
=
NULL
;
}
// Destroy a PreviousVersionWalker
PreviousVersionWalker
::~
PreviousVersionWalker
()
{
// Delete the current info just in case the caller didn't walk to
// the end of the previous versions list. No harm if _current_p is
// already NULL.
delete
_current_p
;
// When _hm is destroyed, all the Handles returned in
// PreviousVersionInfo objects will be destroyed.
// Also, after this destructor is finished it will be
// safe to delete the GrowableArray allocated in the
// PreviousVersionInfo objects.
_current_constant_pool_handle
=
constantPoolHandle
(
thread
,
ik
->
constants
());
}
// Return the interesting information for the next previous version
// of the klass. Returns NULL if there are no more previous versions.
PreviousVersion
Info
*
PreviousVersionWalker
::
next_previous_version
()
{
PreviousVersion
Node
*
PreviousVersionWalker
::
next_previous_version
()
{
if
(
_previous_versions
==
NULL
)
{
// no previous versions so nothing to return
return
NULL
;
}
delete
_current_p
;
// cleanup the previous info for the caller
_current_
p
=
NULL
;
// reset to NULL so we don't delete same object twice
_current_p
=
NULL
;
// reset to NULL
_current_
constant_pool_handle
=
NULL
;
int
length
=
_previous_versions
->
length
();
while
(
_current_index
<
length
)
{
PreviousVersionNode
*
pv_node
=
_previous_versions
->
at
(
_current_index
++
);
PreviousVersionInfo
*
pv_info
=
new
(
ResourceObj
::
C_HEAP
,
mtClass
)
PreviousVersionInfo
(
pv_node
);
constantPoolHandle
cp_h
=
pv_info
->
prev_constant_pool_handle
();
assert
(
!
cp_h
.
is_null
(),
"null cp found in previous version"
);
// The caller will need to delete pv_info when they are done with it.
_current_p
=
pv_info
;
return
pv_info
;
// Save a handle to the constant pool for this previous version,
// which keeps all the methods from being deallocated.
_current_constant_pool_handle
=
constantPoolHandle
(
_thread
,
pv_node
->
prev_constant_pool
());
_current_p
=
pv_node
;
return
pv_node
;
}
// all of the underlying nodes' info has been deleted
return
NULL
;
}
// end next_previous_version()
src/share/vm/oops/instanceKlass.hpp
浏览文件 @
cf041cfa
...
...
@@ -1126,21 +1126,11 @@ class BreakpointInfo;
// A collection point for interesting information about the previous
// version(s) of an InstanceKlass. This class uses weak references to
// the information so that the information may be collected as needed
// by the system. If the information is shared, then a regular
// reference must be used because a weak reference would be seen as
// collectible. A GrowableArray of PreviousVersionNodes is attached
// to the InstanceKlass as needed. See PreviousVersionWalker below.
// version(s) of an InstanceKlass. A GrowableArray of PreviousVersionNodes
// is attached to the InstanceKlass as needed. See PreviousVersionWalker below.
class
PreviousVersionNode
:
public
CHeapObj
<
mtClass
>
{
private:
// A shared ConstantPool is never collected so we'll always have
// a reference to it so we can update items in the cache. We'll
// have a weak reference to a non-shared ConstantPool until all
// of the methods (EMCP or obsolete) have been collected; the
// non-shared ConstantPool becomes collectible at that point.
ConstantPool
*
_prev_constant_pool
;
// regular or weak reference
bool
_prev_cp_is_weak
;
// true if not a shared ConstantPool
ConstantPool
*
_prev_constant_pool
;
// If the previous version of the InstanceKlass doesn't have any
// EMCP methods, then _prev_EMCP_methods will be NULL. If all the
...
...
@@ -1149,8 +1139,8 @@ class PreviousVersionNode : public CHeapObj<mtClass> {
GrowableArray
<
Method
*>*
_prev_EMCP_methods
;
public:
PreviousVersionNode
(
ConstantPool
*
prev_constant_pool
,
bool
prev_cp_is_weak
,
GrowableArray
<
Method
*>*
prev_EMCP_methods
);
PreviousVersionNode
(
ConstantPool
*
prev_constant_pool
,
GrowableArray
<
Method
*>*
prev_EMCP_methods
);
~
PreviousVersionNode
();
ConstantPool
*
prev_constant_pool
()
const
{
return
_prev_constant_pool
;
...
...
@@ -1161,59 +1151,26 @@ public:
};
// A Handle-ized version of PreviousVersionNode.
class
PreviousVersionInfo
:
public
ResourceObj
{
private:
constantPoolHandle
_prev_constant_pool_handle
;
// If the previous version of the InstanceKlass doesn't have any
// EMCP methods, then _prev_EMCP_methods will be NULL. Since the
// methods cannot be collected while we hold a handle,
// _prev_EMCP_methods should never have a length of zero.
GrowableArray
<
methodHandle
>*
_prev_EMCP_method_handles
;
public:
PreviousVersionInfo
(
PreviousVersionNode
*
pv_node
);
~
PreviousVersionInfo
();
constantPoolHandle
prev_constant_pool_handle
()
const
{
return
_prev_constant_pool_handle
;
}
GrowableArray
<
methodHandle
>*
prev_EMCP_method_handles
()
const
{
return
_prev_EMCP_method_handles
;
}
};
// Helper object for walking previous versions. This helper cleans up
// the Handles that it allocates when the helper object is destroyed.
// The PreviousVersionInfo object returned by next_previous_version()
// is only valid until a subsequent call to next_previous_version() or
// the helper object is destroyed.
// Helper object for walking previous versions.
class
PreviousVersionWalker
:
public
StackObj
{
private:
Thread
*
_thread
;
GrowableArray
<
PreviousVersionNode
*>*
_previous_versions
;
int
_current_index
;
// Fields for cleaning up when we are done walking the previous versions:
// A HandleMark for the PreviousVersionInfo handles:
HandleMark
_hm
;
// It would be nice to have a ResourceMark field in this helper also,
// but the ResourceMark code says to be careful to delete handles held
// in GrowableArrays _before_ deleting the GrowableArray. Since we
// can't guarantee the order in which the fields are destroyed, we
// have to let the creator of the PreviousVersionWalker object do
// the right thing. Also, adding a ResourceMark here causes an
// include loop.
// A pointer to the current node object so we can handle the deletes.
PreviousVersionNode
*
_current_p
;
// A pointer to the current info object so we can handle the deletes.
PreviousVersionInfo
*
_current_p
;
// The constant pool handle keeps all the methods in this class from being
// deallocated from the metaspace during class unloading.
constantPoolHandle
_current_constant_pool_handle
;
public:
PreviousVersionWalker
(
InstanceKlass
*
ik
);
~
PreviousVersionWalker
();
PreviousVersionWalker
(
Thread
*
thread
,
InstanceKlass
*
ik
);
// Return the interesting information for the next previous version
// of the klass. Returns NULL if there are no more previous versions.
PreviousVersion
Info
*
next_previous_version
();
PreviousVersion
Node
*
next_previous_version
();
};
...
...
src/share/vm/prims/jvm.cpp
浏览文件 @
cf041cfa
...
...
@@ -1835,16 +1835,27 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass,
}
JVM_END
JVM_ENTRY
(
jobjectArray
,
JVM_GetClassDeclaredMethods
(
JNIEnv
*
env
,
jclass
ofClass
,
jboolean
publicOnly
))
{
JVMWrapper
(
"JVM_GetClassDeclaredMethods"
);
static
bool
select_method
(
methodHandle
method
,
bool
want_constructor
)
{
if
(
want_constructor
)
{
return
(
method
->
is_initializer
()
&&
!
method
->
is_static
());
}
else
{
return
(
!
method
->
is_initializer
()
&&
!
method
->
is_overpass
());
}
}
static
jobjectArray
get_class_declared_methods_helper
(
JNIEnv
*
env
,
jclass
ofClass
,
jboolean
publicOnly
,
bool
want_constructor
,
Klass
*
klass
,
TRAPS
)
{
JvmtiVMObjectAllocEventCollector
oam
;
// Exclude primitive types and array types
if
(
java_lang_Class
::
is_primitive
(
JNIHandles
::
resolve_non_null
(
ofClass
))
||
java_lang_Class
::
as_Klass
(
JNIHandles
::
resolve_non_null
(
ofClass
))
->
oop_is_array
())
{
// Return empty array
oop
res
=
oopFactory
::
new_objArray
(
SystemDictionary
::
reflect_Method_klass
()
,
0
,
CHECK_NULL
);
oop
res
=
oopFactory
::
new_objArray
(
klass
,
0
,
CHECK_NULL
);
return
(
jobjectArray
)
JNIHandles
::
make_local
(
env
,
res
);
}
...
...
@@ -1855,87 +1866,67 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass,
Array
<
Method
*>*
methods
=
k
->
methods
();
int
methods_length
=
methods
->
length
();
// Save original method_idnum in case of redefinition, which can change
// the idnum of obsolete methods. The new method will have the same idnum
// but if we refresh the methods array, the counts will be wrong.
ResourceMark
rm
(
THREAD
);
GrowableArray
<
int
>*
idnums
=
new
GrowableArray
<
int
>
(
methods_length
);
int
num_methods
=
0
;
int
i
;
for
(
i
=
0
;
i
<
methods_length
;
i
++
)
{
for
(
int
i
=
0
;
i
<
methods_length
;
i
++
)
{
methodHandle
method
(
THREAD
,
methods
->
at
(
i
));
if
(
!
method
->
is_initializer
()
&&
!
method
->
is_overpass
(
))
{
if
(
select_method
(
method
,
want_constructor
))
{
if
(
!
publicOnly
||
method
->
is_public
())
{
idnums
->
push
(
method
->
method_idnum
());
++
num_methods
;
}
}
}
// Allocate result
objArrayOop
r
=
oopFactory
::
new_objArray
(
SystemDictionary
::
reflect_Method_klass
()
,
num_methods
,
CHECK_NULL
);
objArrayOop
r
=
oopFactory
::
new_objArray
(
klass
,
num_methods
,
CHECK_NULL
);
objArrayHandle
result
(
THREAD
,
r
);
int
out_idx
=
0
;
for
(
i
=
0
;
i
<
methods_length
;
i
++
)
{
methodHandle
method
(
THREAD
,
methods
->
at
(
i
));
if
(
!
method
->
is_initializer
()
&&
!
method
->
is_overpass
())
{
if
(
!
publicOnly
||
method
->
is_public
())
{
oop
m
=
Reflection
::
new_method
(
method
,
UseNewReflection
,
false
,
CHECK_NULL
);
result
->
obj_at_put
(
out_idx
,
m
);
++
out_idx
;
// Now just put the methods that we selected above, but go by their idnum
// in case of redefinition. The methods can be redefined at any safepoint,
// so above when allocating the oop array and below when creating reflect
// objects.
for
(
int
i
=
0
;
i
<
num_methods
;
i
++
)
{
methodHandle
method
(
THREAD
,
k
->
method_with_idnum
(
idnums
->
at
(
i
)));
if
(
method
.
is_null
())
{
// Method may have been deleted and seems this API can handle null
// Otherwise should probably put a method that throws NSME
result
->
obj_at_put
(
i
,
NULL
);
}
else
{
oop
m
;
if
(
want_constructor
)
{
m
=
Reflection
::
new_constructor
(
method
,
CHECK_NULL
);
}
else
{
m
=
Reflection
::
new_method
(
method
,
UseNewReflection
,
false
,
CHECK_NULL
);
}
result
->
obj_at_put
(
i
,
m
);
}
}
assert
(
out_idx
==
num_methods
,
"just checking"
);
return
(
jobjectArray
)
JNIHandles
::
make_local
(
env
,
result
());
}
JVM_ENTRY
(
jobjectArray
,
JVM_GetClassDeclaredMethods
(
JNIEnv
*
env
,
jclass
ofClass
,
jboolean
publicOnly
))
{
JVMWrapper
(
"JVM_GetClassDeclaredMethods"
);
return
get_class_declared_methods_helper
(
env
,
ofClass
,
publicOnly
,
/*want_constructor*/
false
,
SystemDictionary
::
reflect_Method_klass
(),
THREAD
);
}
JVM_END
JVM_ENTRY
(
jobjectArray
,
JVM_GetClassDeclaredConstructors
(
JNIEnv
*
env
,
jclass
ofClass
,
jboolean
publicOnly
))
{
JVMWrapper
(
"JVM_GetClassDeclaredConstructors"
);
JvmtiVMObjectAllocEventCollector
oam
;
// Exclude primitive types and array types
if
(
java_lang_Class
::
is_primitive
(
JNIHandles
::
resolve_non_null
(
ofClass
))
||
java_lang_Class
::
as_Klass
(
JNIHandles
::
resolve_non_null
(
ofClass
))
->
oop_is_array
())
{
// Return empty array
oop
res
=
oopFactory
::
new_objArray
(
SystemDictionary
::
reflect_Constructor_klass
(),
0
,
CHECK_NULL
);
return
(
jobjectArray
)
JNIHandles
::
make_local
(
env
,
res
);
}
instanceKlassHandle
k
(
THREAD
,
java_lang_Class
::
as_Klass
(
JNIHandles
::
resolve_non_null
(
ofClass
)));
// Ensure class is linked
k
->
link_class
(
CHECK_NULL
);
Array
<
Method
*>*
methods
=
k
->
methods
();
int
methods_length
=
methods
->
length
();
int
num_constructors
=
0
;
int
i
;
for
(
i
=
0
;
i
<
methods_length
;
i
++
)
{
methodHandle
method
(
THREAD
,
methods
->
at
(
i
));
if
(
method
->
is_initializer
()
&&
!
method
->
is_static
())
{
if
(
!
publicOnly
||
method
->
is_public
())
{
++
num_constructors
;
}
}
}
// Allocate result
objArrayOop
r
=
oopFactory
::
new_objArray
(
SystemDictionary
::
reflect_Constructor_klass
(),
num_constructors
,
CHECK_NULL
);
objArrayHandle
result
(
THREAD
,
r
);
int
out_idx
=
0
;
for
(
i
=
0
;
i
<
methods_length
;
i
++
)
{
methodHandle
method
(
THREAD
,
methods
->
at
(
i
));
if
(
method
->
is_initializer
()
&&
!
method
->
is_static
())
{
if
(
!
publicOnly
||
method
->
is_public
())
{
oop
m
=
Reflection
::
new_constructor
(
method
,
CHECK_NULL
);
result
->
obj_at_put
(
out_idx
,
m
);
++
out_idx
;
}
}
}
assert
(
out_idx
==
num_constructors
,
"just checking"
);
return
(
jobjectArray
)
JNIHandles
::
make_local
(
env
,
result
());
return
get_class_declared_methods_helper
(
env
,
ofClass
,
publicOnly
,
/*want_constructor*/
true
,
SystemDictionary
::
reflect_Constructor_klass
(),
THREAD
);
}
JVM_END
...
...
src/share/vm/prims/jvmtiEnvBase.hpp
浏览文件 @
cf041cfa
...
...
@@ -406,7 +406,11 @@ public:
VMOp_Type
type
()
const
{
return
VMOp_GetCurrentContendedMonitor
;
}
jvmtiError
result
()
{
return
_result
;
}
void
doit
()
{
_result
=
((
JvmtiEnvBase
*
)
_env
)
->
get_current_contended_monitor
(
_calling_thread
,
_java_thread
,
_owned_monitor_ptr
);
_result
=
JVMTI_ERROR_THREAD_NOT_ALIVE
;
if
(
Threads
::
includes
(
_java_thread
)
&&
!
_java_thread
->
is_exiting
()
&&
_java_thread
->
threadObj
()
!=
NULL
)
{
_result
=
((
JvmtiEnvBase
*
)
_env
)
->
get_current_contended_monitor
(
_calling_thread
,
_java_thread
,
_owned_monitor_ptr
);
}
}
};
...
...
src/share/vm/prims/jvmtiImpl.cpp
浏览文件 @
cf041cfa
...
...
@@ -273,59 +273,49 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
// add/remove breakpoint to/from versions of the method that
// are EMCP. Directly or transitively obsolete methods are
// not saved in the PreviousVersion
Info
.
// not saved in the PreviousVersion
Nodes
.
Thread
*
thread
=
Thread
::
current
();
instanceKlassHandle
ikh
=
instanceKlassHandle
(
thread
,
_method
->
method_holder
());
Symbol
*
m_name
=
_method
->
name
();
Symbol
*
m_signature
=
_method
->
signature
();
{
ResourceMark
rm
(
thread
);
// PreviousVersionInfo objects returned via PreviousVersionWalker
// contain a GrowableArray of handles. We have to clean up the
// GrowableArray _after_ the PreviousVersionWalker destructor
// has destroyed the handles.
{
// search previous versions if they exist
PreviousVersionWalker
pvw
((
InstanceKlass
*
)
ikh
());
for
(
PreviousVersionInfo
*
pv_info
=
pvw
.
next_previous_version
();
pv_info
!=
NULL
;
pv_info
=
pvw
.
next_previous_version
())
{
GrowableArray
<
methodHandle
>*
methods
=
pv_info
->
prev_EMCP_method_handles
();
if
(
methods
==
NULL
)
{
// We have run into a PreviousVersion generation where
// all methods were made obsolete during that generation's
// RedefineClasses() operation. At the time of that
// operation, all EMCP methods were flushed so we don't
// have to go back any further.
//
// A NULL methods array is different than an empty methods
// array. We cannot infer any optimizations about older
// generations from an empty methods array for the current
// generation.
break
;
}
// search previous versions if they exist
PreviousVersionWalker
pvw
(
thread
,
(
InstanceKlass
*
)
ikh
());
for
(
PreviousVersionNode
*
pv_node
=
pvw
.
next_previous_version
();
pv_node
!=
NULL
;
pv_node
=
pvw
.
next_previous_version
())
{
GrowableArray
<
Method
*>*
methods
=
pv_node
->
prev_EMCP_methods
();
if
(
methods
==
NULL
)
{
// We have run into a PreviousVersion generation where
// all methods were made obsolete during that generation's
// RedefineClasses() operation. At the time of that
// operation, all EMCP methods were flushed so we don't
// have to go back any further.
//
// A NULL methods array is different than an empty methods
// array. We cannot infer any optimizations about older
// generations from an empty methods array for the current
// generation.
break
;
}
for
(
int
i
=
methods
->
length
()
-
1
;
i
>=
0
;
i
--
)
{
methodHandle
method
=
methods
->
at
(
i
);
// obsolete methods that are running are not deleted from
// previous version array, but they are skipped here.
if
(
!
method
->
is_obsolete
()
&&
method
->
name
()
==
m_name
&&
method
->
signature
()
==
m_signature
)
{
RC_TRACE
(
0x00000800
,
(
"%sing breakpoint in %s(%s)"
,
meth_act
==
&
Method
::
set_breakpoint
?
"sett"
:
"clear"
,
method
->
name
()
->
as_C_string
(),
method
->
signature
()
->
as_C_string
()));
((
Method
*
)
method
()
->*
meth_act
)(
_bci
);
break
;
}
}
for
(
int
i
=
methods
->
length
()
-
1
;
i
>=
0
;
i
--
)
{
Method
*
method
=
methods
->
at
(
i
);
// obsolete methods that are running are not deleted from
// previous version array, but they are skipped here.
if
(
!
method
->
is_obsolete
()
&&
method
->
name
()
==
m_name
&&
method
->
signature
()
==
m_signature
)
{
RC_TRACE
(
0x00000800
,
(
"%sing breakpoint in %s(%s)"
,
meth_act
==
&
Method
::
set_breakpoint
?
"sett"
:
"clear"
,
method
->
name
()
->
as_C_string
(),
method
->
signature
()
->
as_C_string
()));
(
method
->*
meth_act
)(
_bci
);
break
;
}
}
// pvw is cleaned up
}
// rm is cleaned up
}
}
}
void
JvmtiBreakpoint
::
set
()
{
...
...
src/share/vm/prims/jvmtiRedefineClasses.cpp
浏览文件 @
cf041cfa
...
...
@@ -2807,28 +2807,20 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
&
trace_name_printed
);
}
}
{
ResourceMark
rm
(
_thread
);
// PreviousVersionInfo objects returned via PreviousVersionWalker
// contain a GrowableArray of handles. We have to clean up the
// GrowableArray _after_ the PreviousVersionWalker destructor
// has destroyed the handles.
{
// the previous versions' constant pool caches may need adjustment
PreviousVersionWalker
pvw
(
ik
);
for
(
PreviousVersionInfo
*
pv_info
=
pvw
.
next_previous_version
();
pv_info
!=
NULL
;
pv_info
=
pvw
.
next_previous_version
())
{
other_cp
=
pv_info
->
prev_constant_pool_handle
();
cp_cache
=
other_cp
->
cache
();
if
(
cp_cache
!=
NULL
)
{
cp_cache
->
adjust_method_entries
(
_matching_old_methods
,
_matching_new_methods
,
_matching_methods_length
,
&
trace_name_printed
);
}
}
}
// pvw is cleaned up
}
// rm is cleaned up
// the previous versions' constant pool caches may need adjustment
PreviousVersionWalker
pvw
(
_thread
,
ik
);
for
(
PreviousVersionNode
*
pv_node
=
pvw
.
next_previous_version
();
pv_node
!=
NULL
;
pv_node
=
pvw
.
next_previous_version
())
{
other_cp
=
pv_node
->
prev_constant_pool
();
cp_cache
=
other_cp
->
cache
();
if
(
cp_cache
!=
NULL
)
{
cp_cache
->
adjust_method_entries
(
_matching_old_methods
,
_matching_new_methods
,
_matching_methods_length
,
&
trace_name_printed
);
}
}
}
}
...
...
@@ -2942,10 +2934,9 @@ void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
// obsolete methods need a unique idnum
u2
num
=
InstanceKlass
::
cast
(
_the_class_oop
)
->
next_method_idnum
();
if
(
num
!=
ConstMethod
::
UNSET_IDNUM
)
{
// u2 old_num = old_method->method_idnum();
old_method
->
set_method_idnum
(
num
);
// TO DO: attach obsolete annotations to obsolete method's new idnum
}
// With tracing we try not to "yack" too much. The position of
// this trace assumes there are fewer obsolete methods than
// EMCP methods.
...
...
src/share/vm/runtime/arguments.cpp
浏览文件 @
cf041cfa
...
...
@@ -1100,6 +1100,7 @@ void Arguments::set_mode_flags(Mode mode) {
}
}
#if defined(COMPILER2) || defined(_LP64) || !INCLUDE_CDS
// Conflict: required to use shared spaces (-Xshare:on), but
// incompatible command line options were chosen.
...
...
@@ -1112,6 +1113,7 @@ static void no_shared_spaces() {
FLAG_SET_DEFAULT
(
UseSharedSpaces
,
false
);
}
}
#endif
void
Arguments
::
set_tiered_flags
()
{
// With tiered, set default policy to AdvancedThresholdPolicy, which is 3.
...
...
@@ -1520,16 +1522,18 @@ void Arguments::set_ergonomics_flags() {
FLAG_SET_ERGO
(
bool
,
UseParallelGC
,
true
);
}
}
// Shared spaces work fine with other GCs but causes bytecode rewriting
// to be disabled, which hurts interpreter performance and decreases
// server performance. On server class machines, keep the default
// off unless it is asked for. Future work: either add bytecode rewriting
// at link time, or rewrite bytecodes in non-shared methods.
if
(
!
DumpSharedSpaces
&&
!
RequireSharedSpaces
&&
(
FLAG_IS_DEFAULT
(
UseSharedSpaces
)
||
!
UseSharedSpaces
))
{
no_shared_spaces
();
}
}
#ifdef COMPILER2
// Shared spaces work fine with other GCs but causes bytecode rewriting
// to be disabled, which hurts interpreter performance and decreases
// server performance. When -server is specified, keep the default off
// unless it is asked for. Future work: either add bytecode rewriting
// at link time, or rewrite bytecodes in non-shared methods.
if
(
!
DumpSharedSpaces
&&
!
RequireSharedSpaces
&&
(
FLAG_IS_DEFAULT
(
UseSharedSpaces
)
||
!
UseSharedSpaces
))
{
no_shared_spaces
();
}
#endif
set_conservative_max_heap_alignment
();
...
...
@@ -2439,21 +2443,6 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) {
return
result
;
}
if
(
AggressiveOpts
)
{
// Insert alt-rt.jar between user-specified bootclasspath
// prefix and the default bootclasspath. os::set_boot_path()
// uses meta_index_dir as the default bootclasspath directory.
const
char
*
altclasses_jar
=
"alt-rt.jar"
;
size_t
altclasses_path_len
=
strlen
(
get_meta_index_dir
())
+
1
+
strlen
(
altclasses_jar
);
char
*
altclasses_path
=
NEW_C_HEAP_ARRAY
(
char
,
altclasses_path_len
,
mtInternal
);
strcpy
(
altclasses_path
,
get_meta_index_dir
());
strcat
(
altclasses_path
,
altclasses_jar
);
scp
.
add_suffix_to_prefix
(
altclasses_path
);
scp_assembly_required
=
true
;
FREE_C_HEAP_ARRAY
(
char
,
altclasses_path
,
mtInternal
);
}
// Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM)
result
=
parse_java_options_environment_variable
(
&
scp
,
&
scp_assembly_required
);
if
(
result
!=
JNI_OK
)
{
...
...
src/share/vm/runtime/globals.hpp
浏览文件 @
cf041cfa
...
...
@@ -2526,6 +2526,9 @@ class CommandLineFlags {
product(bool, PrintStringTableStatistics, false, \
"print statistics about the StringTable and SymbolTable") \
\
diagnostic(bool, VerifyStringTableAtExit, false, \
"verify StringTable contents at exit") \
\
notproduct(bool, PrintSymbolTableSizeHistogram, false, \
"print histogram of the symbol table") \
\
...
...
src/share/vm/runtime/handles.hpp
浏览文件 @
cf041cfa
...
...
@@ -136,7 +136,7 @@ DEF_HANDLE(typeArray , is_typeArray )
// Specific Handles for different oop types
#define DEF_METADATA_HANDLE(name, type) \
class name##Handle; \
class name##Handle
{
\
class name##Handle
: public StackObj {
\
type* _value; \
Thread* _thread; \
protected: \
...
...
@@ -175,7 +175,7 @@ DEF_METADATA_HANDLE(constantPool, ConstantPool)
// Writing this class explicitly, since DEF_METADATA_HANDLE(klass) doesn't
// provide the necessary Klass* <-> Klass* conversions. This Klass
// could be removed when we don't have the Klass* typedef anymore.
class
KlassHandle
{
class
KlassHandle
:
public
StackObj
{
Klass
*
_value
;
protected:
Klass
*
obj
()
const
{
return
_value
;
}
...
...
src/share/vm/runtime/handles.inline.hpp
浏览文件 @
cf041cfa
...
...
@@ -79,6 +79,7 @@ inline name##Handle::name##Handle(const name##Handle &h) { \
} else { \
_thread = Thread::current(); \
} \
assert (_thread->is_in_stack((address)this), "not on stack?"); \
_thread->metadata_handles()->push((Metadata*)_value); \
} else { \
_thread = NULL; \
...
...
@@ -95,6 +96,7 @@ inline name##Handle& name##Handle::operator=(const name##Handle &s) { \
} else { \
_thread = Thread::current(); \
} \
assert (_thread->is_in_stack((address)this), "not on stack?"); \
_thread->metadata_handles()->push((Metadata*)_value); \
} else { \
_thread = NULL; \
...
...
src/share/vm/runtime/java.cpp
浏览文件 @
cf041cfa
...
...
@@ -544,6 +544,19 @@ void before_exit(JavaThread * thread) {
// it will run into trouble when system destroys static variables.
MemTracker
::
shutdown
(
MemTracker
::
NMT_normal
);
if
(
VerifyStringTableAtExit
)
{
int
fail_cnt
=
0
;
{
MutexLocker
ml
(
StringTable_lock
);
fail_cnt
=
StringTable
::
verify_and_compare_entries
();
}
if
(
fail_cnt
!=
0
)
{
tty
->
print_cr
(
"ERROR: fail_cnt=%d"
,
fail_cnt
);
guarantee
(
fail_cnt
==
0
,
"unexpected StringTable verification failures"
);
}
}
#undef BEFORE_EXIT_NOT_RUN
#undef BEFORE_EXIT_RUNNING
#undef BEFORE_EXIT_DONE
...
...
test/runtime/CDSCompressedKPtrs/XShareAuto.java
浏览文件 @
cf041cfa
...
...
@@ -33,16 +33,9 @@ import com.oracle.java.testlibrary.*;
public
class
XShareAuto
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
if
(!
Platform
.
is64bit
())
{
System
.
out
.
println
(
"ObjectAlignmentInBytes for CDS is only "
+
"supported on 64bit platforms; this plaform is "
+
System
.
getProperty
(
"sun.arch.data.model"
));
System
.
out
.
println
(
"Skipping the test"
);
return
;
}
ProcessBuilder
pb
=
ProcessTools
.
createJavaProcessBuilder
(
"-
XX:+UnlockDiagnosticVMOptions"
,
"-XX:SharedArchiveFile=./sample.jsa
"
,
"-Xshare:dump"
);
"-
server"
,
"-XX:+UnlockDiagnosticVMOptions
"
,
"-X
X:SharedArchiveFile=./sample.jsa"
,
"-X
share:dump"
);
OutputAnalyzer
output
=
new
OutputAnalyzer
(
pb
.
start
());
output
.
shouldContain
(
"Loading classes to share"
);
output
.
shouldHaveExitValue
(
0
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录