Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
25313cbd
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看板
提交
25313cbd
编写于
1月 26, 2018
作者:
A
asaha
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
35be5a29
bb347539
变更
18
展开全部
隐藏空白更改
内联
并排
Showing
18 changed file
with
603 addition
and
379 deletion
+603
-379
.hgtags
.hgtags
+1
-0
src/share/vm/classfile/metadataOnStackMark.cpp
src/share/vm/classfile/metadataOnStackMark.cpp
+2
-2
src/share/vm/classfile/metadataOnStackMark.hpp
src/share/vm/classfile/metadataOnStackMark.hpp
+1
-1
src/share/vm/code/nmethod.cpp
src/share/vm/code/nmethod.cpp
+2
-2
src/share/vm/oops/instanceKlass.cpp
src/share/vm/oops/instanceKlass.cpp
+126
-238
src/share/vm/oops/instanceKlass.hpp
src/share/vm/oops/instanceKlass.hpp
+28
-71
src/share/vm/oops/klass.cpp
src/share/vm/oops/klass.cpp
+6
-0
src/share/vm/oops/method.cpp
src/share/vm/oops/method.cpp
+1
-0
src/share/vm/oops/method.hpp
src/share/vm/oops/method.hpp
+16
-0
src/share/vm/oops/methodData.cpp
src/share/vm/oops/methodData.cpp
+48
-9
src/share/vm/oops/methodData.hpp
src/share/vm/oops/methodData.hpp
+11
-2
src/share/vm/prims/jvmtiImpl.cpp
src/share/vm/prims/jvmtiImpl.cpp
+7
-24
src/share/vm/prims/jvmtiRedefineClasses.cpp
src/share/vm/prims/jvmtiRedefineClasses.cpp
+18
-21
src/share/vm/prims/jvmtiRedefineClasses.hpp
src/share/vm/prims/jvmtiRedefineClasses.hpp
+3
-8
test/compiler/profiling/spectrapredefineclass/Agent.java
test/compiler/profiling/spectrapredefineclass/Agent.java
+142
-0
test/compiler/profiling/spectrapredefineclass/Launcher.java
test/compiler/profiling/spectrapredefineclass/Launcher.java
+47
-0
test/runtime/RedefineTests/RedefineFinalizer.java
test/runtime/RedefineTests/RedefineFinalizer.java
+1
-1
test/runtime/RedefineTests/RedefineRunningMethods.java
test/runtime/RedefineTests/RedefineRunningMethods.java
+143
-0
未找到文件。
.hgtags
浏览文件 @
25313cbd
...
...
@@ -1131,6 +1131,7 @@ c3618e1cdefdda6c262f082791bfd988e0e9d9c9 jdk8u162-b10
39e2895b795aded8b584626fb019d35f12e9d1e7 jdk8u162-b11
69aec2ca5d905dde1d0f29a89076d02a531808a3 jdk8u162-b12
caac74fe3cfa9a8c859c28c97d1046a58252af27 jdk8u162-b31
c9b7abadf150328d2187de05b9e8a9cba2486e47 jdk8u162-b32
a17bab9405474602b18cd62e060a09b17d6413ac jdk8u171-b00
ebfd57cc21e6b7f0c22b17c666b6b28c9340e207 jdk8u171-b01
1acd7c1b80241def8fac90f70b0df16356adad47 jdk8u171-b02
...
...
src/share/vm/classfile/metadataOnStackMark.cpp
浏览文件 @
25313cbd
...
...
@@ -41,13 +41,13 @@ NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
// Walk metadata on the stack and mark it so that redefinition doesn't delete
// it. Class unloading also walks the previous versions and might try to
// delete it, so this class is used by class unloading also.
MetadataOnStackMark
::
MetadataOnStackMark
(
bool
visit_code_cache
)
{
MetadataOnStackMark
::
MetadataOnStackMark
(
bool
has_redefined_a_class
)
{
assert
(
SafepointSynchronize
::
is_at_safepoint
(),
"sanity check"
);
assert
(
_used_buffers
==
NULL
,
"sanity check"
);
NOT_PRODUCT
(
_is_active
=
true
;)
Threads
::
metadata_do
(
Metadata
::
mark_on_stack
);
if
(
visit_code_cache
)
{
if
(
has_redefined_a_class
)
{
CodeCache
::
alive_nmethods_do
(
nmethod
::
mark_on_stack
);
}
CompileBroker
::
mark_on_stack
();
...
...
src/share/vm/classfile/metadataOnStackMark.hpp
浏览文件 @
25313cbd
...
...
@@ -47,7 +47,7 @@ class MetadataOnStackMark : public StackObj {
static
void
retire_buffer
(
MetadataOnStackBuffer
*
buffer
);
public:
MetadataOnStackMark
(
bool
visit_code_cache
);
MetadataOnStackMark
(
bool
has_redefined_a_class
);
~
MetadataOnStackMark
();
static
void
record
(
Metadata
*
m
,
Thread
*
thread
);
...
...
src/share/vm/code/nmethod.cpp
浏览文件 @
25313cbd
...
...
@@ -2172,7 +2172,7 @@ void nmethod::metadata_do(void f(Metadata*)) {
"metadata must be found in exactly one place"
);
if
(
r
->
metadata_is_immediate
()
&&
r
->
metadata_value
()
!=
NULL
)
{
Metadata
*
md
=
r
->
metadata_value
();
f
(
md
);
if
(
md
!=
_method
)
f
(
md
);
}
}
else
if
(
iter
.
type
()
==
relocInfo
::
virtual_call_type
)
{
// Check compiledIC holders associated with this nmethod
...
...
@@ -2198,7 +2198,7 @@ void nmethod::metadata_do(void f(Metadata*)) {
f
(
md
);
}
//
Visit metadata not embedded in th
e other places.
//
Call function Method*, not embedded in thes
e other places.
if
(
_method
!=
NULL
)
f
(
_method
);
}
...
...
src/share/vm/oops/instanceKlass.cpp
浏览文件 @
25313cbd
此差异已折叠。
点击以展开。
src/share/vm/oops/instanceKlass.hpp
浏览文件 @
25313cbd
...
...
@@ -88,7 +88,6 @@ class BreakpointInfo;
class
fieldDescriptor
;
class
DepChange
;
class
nmethodBucket
;
class
PreviousVersionNode
;
class
JvmtiCachedClassFieldMap
;
class
MemberNameTable
;
...
...
@@ -235,7 +234,8 @@ class InstanceKlass: public Klass {
_misc_is_anonymous
=
1
<<
3
,
// has embedded _host_klass field
_misc_is_contended
=
1
<<
4
,
// marked with contended annotation
_misc_has_default_methods
=
1
<<
5
,
// class/superclass/implemented interfaces has default methods
_misc_declares_default_methods
=
1
<<
6
// directly declares default methods (any access)
_misc_declares_default_methods
=
1
<<
6
,
// directly declares default methods (any access)
_misc_has_been_redefined
=
1
<<
7
// class has been redefined
};
u2
_misc_flags
;
u2
_minor_version
;
// minor version number of class file
...
...
@@ -250,9 +250,8 @@ class InstanceKlass: public Klass {
nmethodBucket
*
_dependencies
;
// list of dependent nmethods
nmethod
*
_osr_nmethods_head
;
// Head of list of on-stack replacement nmethods for this class
BreakpointInfo
*
_breakpoints
;
// bpt lists, managed by Method*
// Array of interesting part(s) of the previous version(s) of this
// InstanceKlass. See PreviousVersionWalker below.
GrowableArray
<
PreviousVersionNode
*>*
_previous_versions
;
// Linked instanceKlasses of previous versions
InstanceKlass
*
_previous_versions
;
// JVMTI fields can be moved to their own structure - see 6315920
// JVMTI: cached class file, before retransformable agent modified it in CFLH
JvmtiCachedClassFileData
*
_cached_class_file
;
...
...
@@ -669,21 +668,31 @@ class InstanceKlass: public Klass {
}
// RedefineClasses() support for previous versions:
void
add_previous_version
(
instanceKlassHandle
ikh
,
BitMap
*
emcp_methods
,
int
emcp_method_count
);
// If the _previous_versions array is non-NULL, then this klass
// has been redefined at least once even if we aren't currently
// tracking a previous version.
bool
has_been_redefined
()
const
{
return
_previous_versions
!=
NULL
;
}
bool
has_previous_version
()
const
;
void
add_previous_version
(
instanceKlassHandle
ikh
,
int
emcp_method_count
);
InstanceKlass
*
previous_versions
()
const
{
return
_previous_versions
;
}
bool
has_been_redefined
()
const
{
return
(
_misc_flags
&
_misc_has_been_redefined
)
!=
0
;
}
void
set_has_been_redefined
()
{
_misc_flags
|=
_misc_has_been_redefined
;
}
void
init_previous_versions
()
{
_previous_versions
=
NULL
;
}
GrowableArray
<
PreviousVersionNode
*>*
previous_versions
()
const
{
return
_previous_versions
;
InstanceKlass
*
get_klass_version
(
int
version
)
{
for
(
InstanceKlass
*
ik
=
this
;
ik
!=
NULL
;
ik
=
ik
->
previous_versions
())
{
if
(
ik
->
constants
()
->
version
()
==
version
)
{
return
ik
;
}
}
return
NULL
;
}
InstanceKlass
*
get_klass_version
(
int
version
);
static
void
purge_previous_versions
(
InstanceKlass
*
ik
);
// JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation
...
...
@@ -1124,6 +1133,10 @@ private:
// Free CHeap allocated fields.
void
release_C_heap_structures
();
// RedefineClasses support
void
link_previous_versions
(
InstanceKlass
*
pv
)
{
_previous_versions
=
pv
;
}
void
mark_newly_obsolete_methods
(
Array
<
Method
*>*
old_methods
,
int
emcp_method_count
);
public:
// CDS support - remove and restore oops from metadata. Oops are not shared.
virtual
void
remove_unshareable_info
();
...
...
@@ -1222,62 +1235,6 @@ class JNIid: public CHeapObj<mtClass> {
};
// If breakpoints are more numerous than just JVMTI breakpoints,
// consider compressing this data structure.
// It is currently a simple linked list defined in method.hpp.
class
BreakpointInfo
;
// A collection point for interesting information about the previous
// 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:
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
// EMCP methods have been collected, then _prev_EMCP_methods can
// have a length of zero.
GrowableArray
<
Method
*>*
_prev_EMCP_methods
;
public:
PreviousVersionNode
(
ConstantPool
*
prev_constant_pool
,
GrowableArray
<
Method
*>*
prev_EMCP_methods
);
~
PreviousVersionNode
();
ConstantPool
*
prev_constant_pool
()
const
{
return
_prev_constant_pool
;
}
GrowableArray
<
Method
*>*
prev_EMCP_methods
()
const
{
return
_prev_EMCP_methods
;
}
};
// Helper object for walking previous versions.
class
PreviousVersionWalker
:
public
StackObj
{
private:
Thread
*
_thread
;
GrowableArray
<
PreviousVersionNode
*>*
_previous_versions
;
int
_current_index
;
// A pointer to the current node object so we can handle the deletes.
PreviousVersionNode
*
_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
(
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.
PreviousVersionNode
*
next_previous_version
();
};
//
// nmethodBucket is used to record dependent nmethods for
// deoptimization. nmethod dependencies are actually <klass, method>
...
...
src/share/vm/oops/klass.cpp
浏览文件 @
25313cbd
...
...
@@ -455,6 +455,12 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive
if
(
clean_alive_klasses
&&
current
->
oop_is_instance
())
{
InstanceKlass
*
ik
=
InstanceKlass
::
cast
(
current
);
ik
->
clean_weak_instanceklass_links
(
is_alive
);
// JVMTI RedefineClasses creates previous versions that are not in
// the class hierarchy, so process them here.
while
((
ik
=
ik
->
previous_versions
())
!=
NULL
)
{
ik
->
clean_weak_instanceklass_links
(
is_alive
);
}
}
}
}
...
...
src/share/vm/oops/method.cpp
浏览文件 @
25313cbd
...
...
@@ -91,6 +91,7 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags, int size) {
set_hidden
(
false
);
set_dont_inline
(
false
);
set_has_injected_profile
(
false
);
set_running_emcp
(
false
);
set_method_data
(
NULL
);
clear_method_counters
();
set_vtable_index
(
Method
::
garbage_vtable_index
);
...
...
src/share/vm/oops/method.hpp
浏览文件 @
25313cbd
...
...
@@ -111,6 +111,7 @@ class Method : public Metadata {
_caller_sensitive
:
1
,
_force_inline
:
1
,
_hidden
:
1
,
_running_emcp
:
1
,
_dont_inline
:
1
,
_has_injected_profile
:
1
,
:
2
;
...
...
@@ -712,6 +713,21 @@ class Method : public Metadata {
void
set_is_obsolete
()
{
_access_flags
.
set_is_obsolete
();
}
bool
is_deleted
()
const
{
return
access_flags
().
is_deleted
();
}
void
set_is_deleted
()
{
_access_flags
.
set_is_deleted
();
}
bool
is_running_emcp
()
const
{
// EMCP methods are old but not obsolete or deleted. Equivalent
// Modulo Constant Pool means the method is equivalent except
// the constant pool and instructions that access the constant
// pool might be different.
// If a breakpoint is set in a redefined method, its EMCP methods that are
// still running must have a breakpoint also.
return
_running_emcp
;
}
void
set_running_emcp
(
bool
x
)
{
_running_emcp
=
x
;
}
bool
on_stack
()
const
{
return
access_flags
().
on_stack
();
}
void
set_on_stack
(
const
bool
value
);
...
...
src/share/vm/oops/methodData.cpp
浏览文件 @
25313cbd
...
...
@@ -1559,9 +1559,35 @@ void MethodData::clean_extra_data_helper(DataLayout* dp, int shift, bool reset)
}
}
// Remove SpeculativeTrapData entries that reference an unloaded
// method
void
MethodData
::
clean_extra_data
(
BoolObjectClosure
*
is_alive
)
{
class
CleanExtraDataClosure
:
public
StackObj
{
public:
virtual
bool
is_live
(
Method
*
m
)
=
0
;
};
// Check for entries that reference an unloaded method
class
CleanExtraDataKlassClosure
:
public
CleanExtraDataClosure
{
private:
BoolObjectClosure
*
_is_alive
;
public:
CleanExtraDataKlassClosure
(
BoolObjectClosure
*
is_alive
)
:
_is_alive
(
is_alive
)
{}
bool
is_live
(
Method
*
m
)
{
return
m
->
method_holder
()
->
is_loader_alive
(
_is_alive
);
}
};
// Check for entries that reference a redefined method
class
CleanExtraDataMethodClosure
:
public
CleanExtraDataClosure
{
public:
CleanExtraDataMethodClosure
()
{}
bool
is_live
(
Method
*
m
)
{
return
m
->
on_stack
();
}
};
// Remove SpeculativeTrapData entries that reference an unloaded or
// redefined method
void
MethodData
::
clean_extra_data
(
CleanExtraDataClosure
*
cl
)
{
DataLayout
*
dp
=
extra_data_base
();
DataLayout
*
end
=
extra_data_limit
();
...
...
@@ -1572,7 +1598,7 @@ void MethodData::clean_extra_data(BoolObjectClosure* is_alive) {
SpeculativeTrapData
*
data
=
new
SpeculativeTrapData
(
dp
);
Method
*
m
=
data
->
method
();
assert
(
m
!=
NULL
,
"should have a method"
);
if
(
!
m
->
method_holder
()
->
is_loader_alive
(
is_alive
))
{
if
(
!
cl
->
is_live
(
m
))
{
// "shift" accumulates the number of cells for dead
// SpeculativeTrapData entries that have been seen so
// far. Following entries must be shifted left by that many
...
...
@@ -1603,9 +1629,9 @@ void MethodData::clean_extra_data(BoolObjectClosure* is_alive) {
}
}
// Verify there's no unloaded method referenced by a
// Verify there's no unloaded
or redefined
method referenced by a
// SpeculativeTrapData entry
void
MethodData
::
verify_extra_data_clean
(
BoolObjectClosure
*
is_alive
)
{
void
MethodData
::
verify_extra_data_clean
(
CleanExtraDataClosure
*
cl
)
{
#ifdef ASSERT
DataLayout
*
dp
=
extra_data_base
();
DataLayout
*
end
=
extra_data_limit
();
...
...
@@ -1615,7 +1641,7 @@ void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) {
case
DataLayout
::
speculative_trap_data_tag
:
{
SpeculativeTrapData
*
data
=
new
SpeculativeTrapData
(
dp
);
Method
*
m
=
data
->
method
();
assert
(
m
!=
NULL
&&
m
->
method_holder
()
->
is_loader_alive
(
is_alive
),
"Method should exist"
);
assert
(
m
!=
NULL
&&
cl
->
is_live
(
m
),
"Method should exist"
);
break
;
}
case
DataLayout
::
bit_data_tag
:
...
...
@@ -1641,6 +1667,19 @@ void MethodData::clean_method_data(BoolObjectClosure* is_alive) {
parameters
->
clean_weak_klass_links
(
is_alive
);
}
clean_extra_data
(
is_alive
);
verify_extra_data_clean
(
is_alive
);
CleanExtraDataKlassClosure
cl
(
is_alive
);
clean_extra_data
(
&
cl
);
verify_extra_data_clean
(
&
cl
);
}
void
MethodData
::
clean_weak_method_links
()
{
for
(
ProfileData
*
data
=
first_data
();
is_valid
(
data
);
data
=
next_data
(
data
))
{
data
->
clean_weak_method_links
();
}
CleanExtraDataMethodClosure
cl
;
clean_extra_data
(
&
cl
);
verify_extra_data_clean
(
&
cl
);
}
src/share/vm/oops/methodData.hpp
浏览文件 @
25313cbd
...
...
@@ -251,6 +251,9 @@ public:
// GC support
void
clean_weak_klass_links
(
BoolObjectClosure
*
cl
);
// Redefinition support
void
clean_weak_method_links
();
};
...
...
@@ -508,6 +511,9 @@ public:
// GC support
virtual
void
clean_weak_klass_links
(
BoolObjectClosure
*
is_alive_closure
)
{}
// Redefinition support
virtual
void
clean_weak_method_links
()
{}
// CI translation: ProfileData can represent both MethodDataOop data
// as well as CIMethodData data. This function is provided for translating
// an oop in a ProfileData to the ci equivalent. Generally speaking,
...
...
@@ -2030,6 +2036,7 @@ public:
//
CC_INTERP_ONLY
(
class
BytecodeInterpreter
;)
class
CleanExtraDataClosure
;
class
MethodData
:
public
Metadata
{
friend
class
VMStructs
;
...
...
@@ -2183,9 +2190,9 @@ private:
static
bool
profile_parameters_jsr292_only
();
static
bool
profile_all_parameters
();
void
clean_extra_data
(
BoolObjectClosure
*
is_alive
);
void
clean_extra_data
(
CleanExtraDataClosure
*
cl
);
void
clean_extra_data_helper
(
DataLayout
*
dp
,
int
shift
,
bool
reset
=
false
);
void
verify_extra_data_clean
(
BoolObjectClosure
*
is_alive
);
void
verify_extra_data_clean
(
CleanExtraDataClosure
*
cl
);
public:
static
int
header_size
()
{
...
...
@@ -2477,6 +2484,8 @@ public:
static
bool
profile_return_jsr292_only
();
void
clean_method_data
(
BoolObjectClosure
*
is_alive
);
void
clean_weak_method_links
();
};
#endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
src/share/vm/prims/jvmtiImpl.cpp
浏览文件 @
25313cbd
...
...
@@ -282,39 +282,22 @@ address JvmtiBreakpoint::getBcp() {
void
JvmtiBreakpoint
::
each_method_version_do
(
method_action
meth_act
)
{
((
Method
*
)
_method
->*
meth_act
)(
_bci
);
// add/remove breakpoint to/from versions of the method that
// are EMCP. Directly or transitively obsolete methods are
// not saved in the PreviousVersionNodes.
// add/remove breakpoint to/from versions of the method that are EMCP.
Thread
*
thread
=
Thread
::
current
();
instanceKlassHandle
ikh
=
instanceKlassHandle
(
thread
,
_method
->
method_holder
());
Symbol
*
m_name
=
_method
->
name
();
Symbol
*
m_signature
=
_method
->
signature
();
// 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
(
InstanceKlass
*
pv_node
=
ikh
->
previous_versions
();
pv_node
!=
NULL
;
pv_node
=
pv_node
->
previous_versions
())
{
Array
<
Method
*>*
methods
=
pv_node
->
methods
();
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
()
&&
// Only set breakpoints in running EMCP methods.
if
(
method
->
is_running_emcp
()
&&
method
->
name
()
==
m_name
&&
method
->
signature
()
==
m_signature
)
{
RC_TRACE
(
0x00000800
,
(
"%sing breakpoint in %s(%s)"
,
...
...
src/share/vm/prims/jvmtiRedefineClasses.cpp
浏览文件 @
25313cbd
...
...
@@ -3435,13 +3435,12 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
}
// 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
();
for
(
InstanceKlass
*
pv_node
=
ik
->
previous_versions
();
pv_node
!=
NULL
;
pv_node
=
pv_node
->
previous_versions
())
{
cp_cache
=
pv_node
->
constants
()
->
cache
();
if
(
cp_cache
!=
NULL
)
{
cp_cache
->
adjust_method_entries
(
other_cp
->
pool_holder
()
,
&
trace_name_printed
);
cp_cache
->
adjust_method_entries
(
pv_node
,
&
trace_name_printed
);
}
}
}
...
...
@@ -3461,9 +3460,8 @@ void VM_RedefineClasses::update_jmethod_ids() {
}
}
void
VM_RedefineClasses
::
check_methods_and_mark_as_obsolete
(
BitMap
*
emcp_methods
,
int
*
emcp_method_count_p
)
{
*
emcp_method_count_p
=
0
;
int
VM_RedefineClasses
::
check_methods_and_mark_as_obsolete
()
{
int
emcp_method_count
=
0
;
int
obsolete_count
=
0
;
int
old_index
=
0
;
for
(
int
j
=
0
;
j
<
_matching_methods_length
;
++
j
,
++
old_index
)
{
...
...
@@ -3537,9 +3535,9 @@ void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
// that we get from effectively overwriting the old methods
// when the new methods are attached to the_class.
//
track which methods are EMCP for add_previous_version() call
emcp_methods
->
set_bit
(
old_index
);
(
*
emcp_method_count_p
)
++
;
//
Count number of methods that are EMCP. The method will be marked
// old but not obsolete if it is EMCP.
emcp_method_count
++
;
// An EMCP method is _not_ obsolete. An obsolete method has a
// different jmethodID than the current method. An EMCP method
...
...
@@ -3589,10 +3587,11 @@ void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
old_method
->
name
()
->
as_C_string
(),
old_method
->
signature
()
->
as_C_string
()));
}
assert
((
*
emcp_method_count_p
+
obsolete_count
)
==
_old_methods
->
length
(),
assert
((
emcp_method_count
+
obsolete_count
)
==
_old_methods
->
length
(),
"sanity check"
);
RC_TRACE
(
0x00000100
,
(
"EMCP_cnt=%d, obsolete_cnt=%d"
,
*
emcp_method_count_p
,
RC_TRACE
(
0x00000100
,
(
"EMCP_cnt=%d, obsolete_cnt=%d"
,
emcp_method_count
,
obsolete_count
));
return
emcp_method_count
;
}
// This internal class transfers the native function registration from old methods
...
...
@@ -3973,11 +3972,8 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
old_constants->set_pool_holder(scratch_class());
#endif
// track which methods are EMCP for add_previous_version() call below
BitMap
emcp_methods
(
_old_methods
->
length
());
int
emcp_method_count
=
0
;
emcp_methods
.
clear
();
// clears 0..(length() - 1)
check_methods_and_mark_as_obsolete
(
&
emcp_methods
,
&
emcp_method_count
);
// track number of methods that are EMCP for add_previous_version() call below
int
emcp_method_count
=
check_methods_and_mark_as_obsolete
();
transfer_old_native_function_registrations
(
the_class
);
// The class file bytes from before any retransformable agents mucked
...
...
@@ -4064,9 +4060,10 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
scratch_class
->
enclosing_method_method_index
());
scratch_class
->
set_enclosing_method_indices
(
old_class_idx
,
old_method_idx
);
the_class
->
set_has_been_redefined
();
// keep track of previous versions of this class
the_class
->
add_previous_version
(
scratch_class
,
&
emcp_methods
,
emcp_method_count
);
the_class
->
add_previous_version
(
scratch_class
,
emcp_method_count
);
RC_TIMER_STOP
(
_timer_rsc_phase1
);
RC_TIMER_START
(
_timer_rsc_phase2
);
...
...
src/share/vm/prims/jvmtiRedefineClasses.hpp
浏览文件 @
25313cbd
...
...
@@ -403,14 +403,9 @@ class VM_RedefineClasses: public VM_Operation {
// Change jmethodIDs to point to the new methods
void
update_jmethod_ids
();
// In addition to marking methods as obsolete, this routine
// records which methods are EMCP (Equivalent Module Constant
// Pool) in the emcp_methods BitMap and returns the number of
// EMCP methods via emcp_method_count_p. This information is
// used when information about the previous version of the_class
// is squirreled away.
void
check_methods_and_mark_as_obsolete
(
BitMap
*
emcp_methods
,
int
*
emcp_method_count_p
);
// In addition to marking methods as old and/or obsolete, this routine
// counts the number of methods that are EMCP (Equivalent Module Constant Pool).
int
check_methods_and_mark_as_obsolete
();
void
transfer_old_native_function_registrations
(
instanceKlassHandle
the_class
);
// Install the redefinition of a class
...
...
test/compiler/profiling/spectrapredefineclass/Agent.java
0 → 100644
浏览文件 @
25313cbd
/*
* 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.
*/
import
java.security.*
;
import
java.lang.instrument.*
;
import
java.lang.reflect.*
;
import
java.lang.management.ManagementFactory
;
import
com.sun.tools.attach.VirtualMachine
;
class
A
{
void
m
()
{
}
}
class
B
extends
A
{
void
m
()
{
}
}
class
C
extends
A
{
void
m
()
{
}
}
class
Test
{
static
public
void
m
()
throws
Exception
{
for
(
int
i
=
0
;
i
<
20000
;
i
++)
{
m1
(
a
);
}
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
m1
(
b
);
}
}
static
boolean
m1
(
A
a
)
{
boolean
res
=
Agent
.
m2
(
a
);
return
res
;
}
static
public
A
a
=
new
A
();
static
public
B
b
=
new
B
();
static
public
C
c
=
new
C
();
}
public
class
Agent
implements
ClassFileTransformer
{
static
class
MemoryChunk
{
MemoryChunk
other
;
long
[]
array
;
MemoryChunk
(
MemoryChunk
other
)
{
other
=
other
;
array
=
new
long
[
1024
*
1024
*
1024
];
}
}
static
public
boolean
m2
(
A
a
)
{
boolean
res
=
false
;
if
(
a
.
getClass
()
==
B
.
class
)
{
a
.
m
();
}
else
{
res
=
true
;
}
return
res
;
}
static
public
void
main
(
String
[]
args
)
throws
Exception
{
// Create speculative trap entries
Test
.
m
();
String
nameOfRunningVM
=
ManagementFactory
.
getRuntimeMXBean
().
getName
();
int
p
=
nameOfRunningVM
.
indexOf
(
'@'
);
String
pid
=
nameOfRunningVM
.
substring
(
0
,
p
);
// Make the nmethod go away
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
System
.
gc
();
}
// Redefine class
try
{
VirtualMachine
vm
=
VirtualMachine
.
attach
(
pid
);
vm
.
loadAgent
(
System
.
getProperty
(
"test.classes"
,
"."
)
+
"/agent.jar"
,
""
);
vm
.
detach
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
Test
.
m
();
// GC will hit dead method pointer
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
System
.
gc
();
}
}
public
synchronized
byte
[]
transform
(
final
ClassLoader
classLoader
,
final
String
className
,
Class
<?>
classBeingRedefined
,
ProtectionDomain
protectionDomain
,
byte
[]
classfileBuffer
)
{
System
.
out
.
println
(
"Transforming class "
+
className
);
return
classfileBuffer
;
}
public
static
void
redefine
(
String
agentArgs
,
Instrumentation
instrumentation
,
Class
to_redefine
)
{
try
{
instrumentation
.
retransformClasses
(
to_redefine
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
public
static
void
agentmain
(
String
agentArgs
,
Instrumentation
instrumentation
)
throws
Exception
{
Agent
transformer
=
new
Agent
();
instrumentation
.
addTransformer
(
transformer
,
true
);
redefine
(
agentArgs
,
instrumentation
,
Test
.
class
);
}
}
test/compiler/profiling/spectrapredefineclass/Launcher.java
0 → 100644
浏览文件 @
25313cbd
/*
* 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.
*/
import
java.io.PrintWriter
;
import
com.oracle.java.testlibrary.*
;
/*
* @test
* @bug 8038636
* @library /testlibrary
* @build Agent
* @run main ClassFileInstaller Agent
* @run main Launcher
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -Xmx1M -XX:ReservedCodeCacheSize=3M Agent
*/
public
class
Launcher
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
PrintWriter
pw
=
new
PrintWriter
(
"MANIFEST.MF"
);
pw
.
println
(
"Agent-Class: Agent"
);
pw
.
println
(
"Can-Retransform-Classes: true"
);
pw
.
close
();
ProcessBuilder
pb
=
new
ProcessBuilder
();
pb
.
command
(
new
String
[]
{
JDKToolFinder
.
getJDKTool
(
"jar"
),
"cmf"
,
"MANIFEST.MF"
,
System
.
getProperty
(
"test.classes"
,
"."
)
+
"/agent.jar"
,
"Agent.class"
});
pb
.
start
().
waitFor
();
}
}
test/runtime/Redefine
Finalizer
/RedefineFinalizer.java
→
test/runtime/Redefine
Tests
/RedefineFinalizer.java
浏览文件 @
25313cbd
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014,
2018,
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
...
...
test/runtime/RedefineTests/RedefineRunningMethods.java
0 → 100644
浏览文件 @
25313cbd
/*
* 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 8055008
* @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
* @library /testlibrary
* @build RedefineClassHelper
* @run main RedefineClassHelper
* @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethods
*/
public
class
RedefineRunningMethods
{
public
static
String
newB
=
"class RedefineRunningMethods$B {"
+
" static int count1 = 0;"
+
" static int count2 = 0;"
+
" public static volatile boolean stop = false;"
+
" static void localSleep() { "
+
" try{ "
+
" Thread.currentThread().sleep(10);"
+
" } catch(InterruptedException ie) { "
+
" } "
+
" } "
+
" public static void infinite() { "
+
" System.out.println(\"infinite called\");"
+
" }"
+
" public static void infinite_emcp() { "
+
" while (!stop) { count2++; localSleep(); }"
+
" }"
+
"}"
;
public
static
String
evenNewerB
=
"class RedefineRunningMethods$B {"
+
" static int count1 = 0;"
+
" static int count2 = 0;"
+
" public static volatile boolean stop = false;"
+
" static void localSleep() { "
+
" try{ "
+
" Thread.currentThread().sleep(1);"
+
" } catch(InterruptedException ie) { "
+
" } "
+
" } "
+
" public static void infinite() { }"
+
" public static void infinite_emcp() { "
+
" System.out.println(\"infinite_emcp now obsolete called\");"
+
" }"
+
"}"
;
static
class
B
{
static
int
count1
=
0
;
static
int
count2
=
0
;
public
static
volatile
boolean
stop
=
false
;
static
void
localSleep
()
{
try
{
Thread
.
currentThread
().
sleep
(
10
);
//sleep for 10 ms
}
catch
(
InterruptedException
ie
)
{
}
}
public
static
void
infinite
()
{
while
(!
stop
)
{
count1
++;
localSleep
();
}
}
public
static
void
infinite_emcp
()
{
while
(!
stop
)
{
count2
++;
localSleep
();
}
}
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
Thread
()
{
public
void
run
()
{
B
.
infinite
();
}
}.
start
();
new
Thread
()
{
public
void
run
()
{
B
.
infinite_emcp
();
}
}.
start
();
RedefineClassHelper
.
redefineClass
(
B
.
class
,
newB
);
System
.
gc
();
B
.
infinite
();
// Start a thread with the second version of infinite_emcp running
new
Thread
()
{
public
void
run
()
{
B
.
infinite_emcp
();
}
}.
start
();
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
String
s
=
new
String
(
"some garbage"
);
System
.
gc
();
}
RedefineClassHelper
.
redefineClass
(
B
.
class
,
evenNewerB
);
System
.
gc
();
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
B
.
infinite
();
String
s
=
new
String
(
"some garbage"
);
System
.
gc
();
}
B
.
infinite_emcp
();
// purge should clean everything up.
B
.
stop
=
true
;
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
B
.
infinite
();
String
s
=
new
String
(
"some garbage"
);
System
.
gc
();
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录