Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
cd06fea7
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看板
提交
cd06fea7
编写于
3月 19, 2018
作者:
A
asaha
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
0468c118
309030ed
变更
25
隐藏空白更改
内联
并排
Showing
25 changed file
with
727 addition
and
386 deletion
+727
-386
.hgtags
.hgtags
+5
-0
agent/src/os/linux/Makefile
agent/src/os/linux/Makefile
+4
-1
make/linux/makefiles/gcc.make
make/linux/makefiles/gcc.make
+3
-1
make/linux/makefiles/jsig.make
make/linux/makefiles/jsig.make
+2
-2
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/jvmtiGetLoadedClasses.cpp
src/share/vm/prims/jvmtiGetLoadedClasses.cpp
+19
-1
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
src/share/vm/prims/whitebox.cpp
src/share/vm/prims/whitebox.cpp
+21
-1
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
test/runtime/execstack/TestCheckJDK.java
test/runtime/execstack/TestCheckJDK.java
+67
-0
test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
+4
-1
未找到文件。
.hgtags
浏览文件 @
cd06fea7
...
...
@@ -1131,6 +1131,11 @@ c3618e1cdefdda6c262f082791bfd988e0e9d9c9 jdk8u162-b10
39e2895b795aded8b584626fb019d35f12e9d1e7 jdk8u162-b11
69aec2ca5d905dde1d0f29a89076d02a531808a3 jdk8u162-b12
caac74fe3cfa9a8c859c28c97d1046a58252af27 jdk8u162-b31
c9b7abadf150328d2187de05b9e8a9cba2486e47 jdk8u162-b32
e8041f2ec96eb6a41307732e6cf6ed90901438ae jdk8u162-b33
bf2e8b1e8e8e6bc1f9b9475de54ba0329a6b24b1 jdk8u162-b34
9b3f207379cf6ecfb8603640269e31ff4e064294 jdk8u162-b35
d2ebd6530396b0afc700cd1a8eaf1f7a7f9fce8d jdk8u162-b36
a17bab9405474602b18cd62e060a09b17d6413ac jdk8u171-b00
ebfd57cc21e6b7f0c22b17c666b6b28c9340e207 jdk8u171-b01
1acd7c1b80241def8fac90f70b0df16356adad47 jdk8u171-b02
...
...
agent/src/os/linux/Makefile
浏览文件 @
cd06fea7
#
# Copyright (c) 2002, 201
2
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 201
8
, 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
...
...
@@ -76,6 +76,9 @@ ifneq ($(_HAS_HASH_STYLE_GNU),)
endif
LFLAGS_LIBSA
+=
$(LDFLAGS_HASH_STYLE)
LDFLAGS_NO_EXEC_STACK
=
"-Wl,-z,noexecstack"
LFLAGS_LIBSA
+=
$(LDFLAGS_NO_EXEC_STACK)
$(LIBSA)
:
$(ARCH) $(OBJS) mapfile
$(GCC)
-shared
$(LFLAGS_LIBSA)
-o
$(LIBSA)
$(OBJS)
$(LIBS)
...
...
make/linux/makefiles/gcc.make
浏览文件 @
cd06fea7
#
# Copyright (c) 1999, 201
5
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1999, 201
8
, 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
...
...
@@ -303,6 +303,8 @@ endif
LFLAGS
+=
$(LDFLAGS_HASH_STYLE)
LDFLAGS_NO_EXEC_STACK
=
"-Wl,-z,noexecstack"
# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
MAPFLAG
=
-Xlinker
--version-script
=
FILENAME
...
...
make/linux/makefiles/jsig.make
浏览文件 @
cd06fea7
#
# Copyright (c) 2005, 201
3
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2005, 201
8
, 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
...
...
@@ -44,7 +44,7 @@ LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig
# cause problems with interposing. See CR: 6466665
# LFLAGS_JSIG += $(MAPFLAG:FILENAME=$(LIBJSIG_MAPFILE))
LFLAGS_JSIG
+=
-D_GNU_SOURCE
-D_REENTRANT
$(LDFLAGS_HASH_STYLE)
LFLAGS_JSIG
+=
-D_GNU_SOURCE
-D_REENTRANT
$(LDFLAGS_HASH_STYLE)
$(LDFLAGS_NO_EXEC_STACK)
# DEBUG_BINARIES overrides everything, use full -g debug information
ifeq
($(DEBUG_BINARIES), true)
...
...
src/share/vm/classfile/metadataOnStackMark.cpp
浏览文件 @
cd06fea7
...
...
@@ -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
浏览文件 @
cd06fea7
...
...
@@ -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
浏览文件 @
cd06fea7
...
...
@@ -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
浏览文件 @
cd06fea7
...
...
@@ -2582,16 +2582,6 @@ void InstanceKlass::release_C_heap_structures() {
assert
(
breakpoints
()
==
0x0
,
"should have cleared breakpoints"
);
}
// deallocate information about previous versions
if
(
_previous_versions
!=
NULL
)
{
for
(
int
i
=
_previous_versions
->
length
()
-
1
;
i
>=
0
;
i
--
)
{
PreviousVersionNode
*
pv_node
=
_previous_versions
->
at
(
i
);
delete
pv_node
;
}
delete
_previous_versions
;
_previous_versions
=
NULL
;
}
// deallocate the cached class file
if
(
_cached_class_file
!=
NULL
)
{
os
::
free
(
_cached_class_file
,
mtClass
);
...
...
@@ -3187,16 +3177,17 @@ void InstanceKlass::print_on(outputStream* st) const {
st
->
print
(
BULLET
"field type annotations: "
);
fields_type_annotations
()
->
print_value_on
(
st
);
st
->
cr
();
{
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
())
{
// previous versions are linked together through the InstanceKlass
for
(
InstanceKlass
*
pv_node
=
_previous_versions
;
pv_node
!=
NULL
;
pv_node
=
pv_node
->
previous_versions
())
{
if
(
!
have_pv
)
st
->
print
(
BULLET
"previous version: "
);
have_pv
=
true
;
pv_node
->
prev_constant_pool
()
->
print_value_on
(
st
);
pv_node
->
constants
()
->
print_value_on
(
st
);
}
if
(
have_pv
)
st
->
cr
();
}
// pvw is cleaned up
}
if
(
generic_signature
()
!=
NULL
)
{
st
->
print
(
BULLET
"generic signature: "
);
...
...
@@ -3610,205 +3601,126 @@ void InstanceKlass::set_init_state(ClassState state) {
// RedefineClasses() support for previous versions:
// Purge previous versions
static
void
purge_previous_versions_internal
(
InstanceKlass
*
ik
,
int
emcp_method_count
)
{
void
InstanceKlass
::
purge_previous_versions
(
InstanceKlass
*
ik
)
{
if
(
ik
->
previous_versions
()
!=
NULL
)
{
// This klass has previous versions so see what we can cleanup
// while it is safe to do so.
int
deleted_count
=
0
;
// leave debugging breadcrumbs
int
live_count
=
0
;
ClassLoaderData
*
loader_data
=
ik
->
class_loader_data
()
==
NULL
?
ClassLoaderData
::
the_null_class_loader_data
()
:
ik
->
class_loader_data
();
ClassLoaderData
*
loader_data
=
ik
->
class_loader_data
();
assert
(
loader_data
!=
NULL
,
"should never be null"
);
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE
(
0x00000200
,
(
"purge: %s: previous version length=%d"
,
ik
->
external_name
(),
ik
->
previous_versions
()
->
length
()));
RC_TRACE
(
0x00000200
,
(
"purge: %s: previous versions"
,
ik
->
external_name
()));
// previous versions are linked together through the InstanceKlass
InstanceKlass
*
pv_node
=
ik
->
previous_versions
();
InstanceKlass
*
last
=
ik
;
int
version
=
0
;
// check the previous versions list
for
(;
pv_node
!=
NULL
;
)
{
ConstantPool
*
pvcp
=
pv_node
->
constants
();
assert
(
pvcp
!=
NULL
,
"cp ref was unexpectedly cleared"
);
for
(
int
i
=
ik
->
previous_versions
()
->
length
()
-
1
;
i
>=
0
;
i
--
)
{
// check the previous versions array
PreviousVersionNode
*
pv_node
=
ik
->
previous_versions
()
->
at
(
i
);
ConstantPool
*
cp_ref
=
pv_node
->
prev_constant_pool
();
assert
(
cp_ref
!=
NULL
,
"cp ref was unexpectedly cleared"
);
ConstantPool
*
pvcp
=
cp_ref
;
if
(
!
pvcp
->
on_stack
())
{
// If the constant pool isn't on stack, none of the methods
// are executing. Delete all the methods, the constant pool and
// and this previous version node.
GrowableArray
<
Method
*>*
method_refs
=
pv_node
->
prev_EMCP_methods
();
if
(
method_refs
!=
NULL
)
{
for
(
int
j
=
method_refs
->
length
()
-
1
;
j
>=
0
;
j
--
)
{
Method
*
method
=
method_refs
->
at
(
j
);
assert
(
method
!=
NULL
,
"method ref was unexpectedly cleared"
);
method_refs
->
remove_at
(
j
);
// method will be freed with associated class.
}
}
// Remove the constant pool
delete
pv_node
;
// Since we are traversing the array backwards, we don't have to
// do anything special with the index.
ik
->
previous_versions
()
->
remove_at
(
i
);
// are executing. Unlink this previous_version.
// The previous version InstanceKlass is on the ClassLoaderData deallocate list
// so will be deallocated during the next phase of class unloading.
pv_node
=
pv_node
->
previous_versions
();
last
->
link_previous_versions
(
pv_node
);
deleted_count
++
;
version
++
;
continue
;
}
else
{
RC_TRACE
(
0x00000200
,
(
"purge: previous version @%d is alive"
,
i
));
RC_TRACE
(
0x00000200
,
(
"purge: previous version "
INTPTR_FORMAT
" is alive"
,
pv_node
));
assert
(
pvcp
->
pool_holder
()
!=
NULL
,
"Constant pool with no holder"
);
guarantee
(
!
loader_data
->
is_unloading
(),
"unloaded classes can't be on the stack"
);
live_count
++
;
}
// At least one method is live in this previous version, clean out
// the others or mark them as obsolete.
GrowableArray
<
Method
*>*
method_refs
=
pv_node
->
prev_EMCP_methods
();
// At least one method is live in this previous version so clean its MethodData.
// Reset dead EMCP methods not to get breakpoints.
// All methods are deallocated when all of the methods for this class are no
// longer running.
Array
<
Method
*>*
method_refs
=
pv_node
->
methods
();
if
(
method_refs
!=
NULL
)
{
RC_TRACE
(
0x00000200
,
(
"purge: previous methods length=%d"
,
method_refs
->
length
()));
for
(
int
j
=
method_refs
->
length
()
-
1
;
j
>=
0
;
j
--
)
{
for
(
int
j
=
0
;
j
<
method_refs
->
length
();
j
++
)
{
Method
*
method
=
method_refs
->
at
(
j
);
assert
(
method
!=
NULL
,
"method ref was unexpectedly cleared"
);
// Remove the emcp method if it's not executing
// If it's been made obsolete by a redefinition of a non-emcp
// method, mark it as obsolete but leave it to clean up later.
if
(
!
method
->
on_stack
())
{
method_refs
->
remove_at
(
j
);
}
else
if
(
emcp_method_count
==
0
)
{
method
->
set_is_obsolete
();
// no breakpoints for non-running methods
if
(
method
->
is_running_emcp
())
{
method
->
set_running_emcp
(
false
);
}
}
else
{
assert
(
method
->
is_obsolete
()
||
method
->
is_running_emcp
(),
"emcp method cannot run after emcp bit is cleared"
);
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE
(
0x00000200
,
(
"purge: %s(%s): prev method @%d in version @%d is alive"
,
method
->
name
()
->
as_C_string
(),
method
->
signature
()
->
as_C_string
(),
j
,
i
));
method
->
signature
()
->
as_C_string
(),
j
,
version
));
if
(
method
->
method_data
()
!=
NULL
)
{
// Clean out any weak method links for running methods
// (also should include not EMCP methods)
method
->
method_data
()
->
clean_weak_method_links
();
}
}
}
}
// next previous version
last
=
pv_node
;
pv_node
=
pv_node
->
previous_versions
();
version
++
;
}
assert
(
ik
->
previous_versions
()
->
length
()
==
live_count
,
"sanity check"
);
RC_TRACE
(
0x00000200
,
(
"purge: previous version stats: live=%d, deleted=%d"
,
live_count
,
deleted_count
));
}
}
// External interface for use during class unloading.
void
InstanceKlass
::
purge_previous_versions
(
InstanceKlass
*
ik
)
{
// Call with >0 emcp methods since they are not currently being redefined.
purge_previous_versions_internal
(
ik
,
1
);
}
// Potentially add an information node that contains pointers to the
// interesting parts of the previous version of the_class.
// This is also where we clean out any unused references.
// Note that while we delete nodes from the _previous_versions
// array, we never delete the array itself until the klass is
// unloaded. The has_been_redefined() query depends on that fact.
//
void
InstanceKlass
::
add_previous_version
(
instanceKlassHandle
ikh
,
BitMap
*
emcp_methods
,
int
emcp_method_count
)
{
assert
(
Thread
::
current
()
->
is_VM_thread
(),
"only VMThread can add previous versions"
);
if
(
_previous_versions
==
NULL
)
{
// This is the first previous version so make some space.
// Start with 2 elements under the assumption that the class
// won't be redefined much.
_previous_versions
=
new
(
ResourceObj
::
C_HEAP
,
mtClass
)
GrowableArray
<
PreviousVersionNode
*>
(
2
,
true
);
}
ConstantPool
*
cp_ref
=
ikh
->
constants
();
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE
(
0x00000400
,
(
"adding previous version ref for %s @%d, EMCP_cnt=%d "
"on_stack=%d"
,
ikh
->
external_name
(),
_previous_versions
->
length
(),
emcp_method_count
,
cp_ref
->
on_stack
()));
// If the constant pool for this previous version of the class
// is not marked as being on the stack, then none of the methods
// in this previous version of the class are on the stack so
// we don't need to create a new PreviousVersionNode. However,
// we still need to examine older previous versions below.
Array
<
Method
*>*
old_methods
=
ikh
->
methods
();
if
(
cp_ref
->
on_stack
())
{
PreviousVersionNode
*
pv_node
=
NULL
;
if
(
emcp_method_count
==
0
)
{
// non-shared ConstantPool gets a reference
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
);
}
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
,
method_refs
);
// Clean MethodData of this class's methods so they don't refer to
// old methods that are no longer running.
Array
<
Method
*>*
methods
=
ik
->
methods
();
int
num_methods
=
methods
->
length
();
for
(
int
index2
=
0
;
index2
<
num_methods
;
++
index2
)
{
if
(
methods
->
at
(
index2
)
->
method_data
()
!=
NULL
)
{
methods
->
at
(
index2
)
->
method_data
()
->
clean_weak_method_links
();
}
// append new previous version.
_previous_versions
->
append
(
pv_node
);
}
}
// Since the caller is the VMThread and we are at a safepoint, this
// is a good time to clear out unused references.
RC_TRACE
(
0x00000400
,
(
"add: previous version length=%d"
,
_previous_versions
->
length
()));
// Purge previous versions not executing on the stack
purge_previous_versions_internal
(
this
,
emcp_method_count
);
void
InstanceKlass
::
mark_newly_obsolete_methods
(
Array
<
Method
*>*
old_methods
,
int
emcp_method_count
)
{
int
obsolete_method_count
=
old_methods
->
length
()
-
emcp_method_count
;
if
(
emcp_method_count
!=
0
&&
obsolete_method_count
!=
0
&&
_previous_versions
->
length
()
>
0
)
{
_previous_versions
!=
NULL
)
{
// We have a mix of obsolete and EMCP methods so we have to
// clear out any matching EMCP method entries the hard way.
int
local_count
=
0
;
for
(
int
i
=
0
;
i
<
old_methods
->
length
();
i
++
)
{
if
(
!
emcp_methods
->
at
(
i
))
{
Method
*
old_method
=
old_methods
->
at
(
i
);
if
(
old_method
->
is_obsolete
())
{
// only obsolete methods are interesting
Method
*
old_method
=
old_methods
->
at
(
i
);
Symbol
*
m_name
=
old_method
->
name
();
Symbol
*
m_signature
=
old_method
->
signature
();
// we might not have added the last entry
for
(
int
j
=
_previous_versions
->
length
()
-
1
;
j
>=
0
;
j
--
)
{
// check the previous versions array for non executing obsolete methods
PreviousVersionNode
*
pv_node
=
_previous_versions
->
at
(
j
);
GrowableArray
<
Method
*>*
method_refs
=
pv_node
->
prev_EMCP_methods
();
if
(
method_refs
==
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 method_refs is different than an empty method_refs.
// We cannot infer any optimizations about older generations
// from an empty method_refs for the current generation.
break
;
}
// previous versions are linked together through the InstanceKlass
int
j
=
0
;
for
(
InstanceKlass
*
prev_version
=
_previous_versions
;
prev_version
!=
NULL
;
prev_version
=
prev_version
->
previous_versions
(),
j
++
)
{
for
(
int
k
=
method_refs
->
length
()
-
1
;
k
>=
0
;
k
--
)
{
Array
<
Method
*>*
method_refs
=
prev_version
->
methods
();
for
(
int
k
=
0
;
k
<
method_refs
->
length
();
k
++
)
{
Method
*
method
=
method_refs
->
at
(
k
);
if
(
!
method
->
is_obsolete
()
&&
...
...
@@ -3816,14 +3728,11 @@ void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
method
->
signature
()
==
m_signature
)
{
// The current RedefineClasses() call has made all EMCP
// versions of this method obsolete so mark it as obsolete
// and remove the reference.
RC_TRACE
(
0x00000400
,
(
"add: %s(%s): flush obsolete method @%d in version @%d"
,
m_name
->
as_C_string
(),
m_signature
->
as_C_string
(),
k
,
j
));
method
->
set_is_obsolete
();
// Leave obsolete methods on the previous version list to
// clean up later.
break
;
}
}
...
...
@@ -3831,9 +3740,9 @@ void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
// The previous loop may not find a matching EMCP method, but
// that doesn't mean that we can optimize and not go any
// further back in the PreviousVersion generations. The EMCP
// method for this generation could have already been
deleted
,
// method for this generation could have already been
made obsolete
,
// but there still may be an older EMCP method that has not
// been
deleted
.
// been
made obsolete
.
}
if
(
++
local_count
>=
obsolete_method_count
)
{
...
...
@@ -3843,30 +3752,67 @@ void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
}
}
}
}
// end add_previous_version()
}
// Save the scratch_class as the previous version if any of the methods are running.
// The previous_versions are used to set breakpoints in EMCP methods and they are
// also used to clean MethodData links to redefined methods that are no longer running.
void
InstanceKlass
::
add_previous_version
(
instanceKlassHandle
scratch_class
,
int
emcp_method_count
)
{
assert
(
Thread
::
current
()
->
is_VM_thread
(),
"only VMThread can add previous versions"
);
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE
(
0x00000400
,
(
"adding previous version ref for %s, EMCP_cnt=%d"
,
scratch_class
->
external_name
(),
emcp_method_count
));
// Determine if InstanceKlass has a previous version.
bool
InstanceKlass
::
has_previous_version
()
const
{
return
(
_previous_versions
!=
NULL
&&
_previous_versions
->
length
()
>
0
);
}
// end has_previous_version()
// Clean out old previous versions
purge_previous_versions
(
this
);
// Mark newly obsolete methods in remaining previous versions. An EMCP method from
// a previous redefinition may be made obsolete by this redefinition.
Array
<
Method
*>*
old_methods
=
scratch_class
->
methods
();
mark_newly_obsolete_methods
(
old_methods
,
emcp_method_count
);
InstanceKlass
*
InstanceKlass
::
get_klass_version
(
int
version
)
{
if
(
constants
()
->
version
()
==
version
)
{
return
this
;
// If the constant pool for this previous version of the class
// is not marked as being on the stack, then none of the methods
// in this previous version of the class are on the stack so
// we don't need to add this as a previous version.
ConstantPool
*
cp_ref
=
scratch_class
->
constants
();
if
(
!
cp_ref
->
on_stack
())
{
RC_TRACE
(
0x00000400
,
(
"add: scratch class not added; no methods are running"
));
return
;
}
PreviousVersionWalker
pvw
(
Thread
::
current
(),
(
InstanceKlass
*
)
this
);
for
(
PreviousVersionNode
*
pv_node
=
pvw
.
next_previous_version
();
pv_node
!=
NULL
;
pv_node
=
pvw
.
next_previous_version
())
{
ConstantPool
*
prev_cp
=
pv_node
->
prev_constant_pool
();
if
(
prev_cp
->
version
()
==
version
)
{
return
prev_cp
->
pool_holder
();
if
(
emcp_method_count
!=
0
)
{
// At least one method is still running, check for EMCP methods
for
(
int
i
=
0
;
i
<
old_methods
->
length
();
i
++
)
{
Method
*
old_method
=
old_methods
->
at
(
i
);
if
(
!
old_method
->
is_obsolete
()
&&
old_method
->
on_stack
())
{
// if EMCP method (not obsolete) is on the stack, mark as EMCP so that
// we can add breakpoints for it.
// We set the method->on_stack bit during safepoints for class redefinition and
// class unloading and use this bit to set the is_running_emcp bit.
// After the safepoint, the on_stack bit is cleared and the running emcp
// method may exit. If so, we would set a breakpoint in a method that
// is never reached, but this won't be noticeable to the programmer.
old_method
->
set_running_emcp
(
true
);
RC_TRACE
(
0x00000400
,
(
"add: EMCP method %s is on_stack "
INTPTR_FORMAT
,
old_method
->
name_and_sig_as_C_string
(),
old_method
));
}
else
if
(
!
old_method
->
is_obsolete
())
{
RC_TRACE
(
0x00000400
,
(
"add: EMCP method %s is NOT on_stack "
INTPTR_FORMAT
,
old_method
->
name_and_sig_as_C_string
(),
old_method
));
}
}
}
return
NULL
;
// None found
}
// Add previous version if any methods are still running.
RC_TRACE
(
0x00000400
,
(
"add: scratch class added; one of its methods is on_stack"
));
assert
(
scratch_class
->
previous_versions
()
==
NULL
,
"shouldn't have a previous version"
);
scratch_class
->
link_previous_versions
(
previous_versions
());
link_previous_versions
(
scratch_class
());
}
// end add_previous_version()
Method
*
InstanceKlass
::
method_with_idnum
(
int
idnum
)
{
Method
*
m
=
NULL
;
...
...
@@ -3924,61 +3870,3 @@ jint InstanceKlass::get_cached_class_file_len() {
unsigned
char
*
InstanceKlass
::
get_cached_class_file_bytes
()
{
return
VM_RedefineClasses
::
get_cached_class_file_bytes
(
_cached_class_file
);
}
// Construct a PreviousVersionNode entry for the array hung off
// the InstanceKlass.
PreviousVersionNode
::
PreviousVersionNode
(
ConstantPool
*
prev_constant_pool
,
GrowableArray
<
Method
*>*
prev_EMCP_methods
)
{
_prev_constant_pool
=
prev_constant_pool
;
_prev_EMCP_methods
=
prev_EMCP_methods
;
}
// Destroy a PreviousVersionNode
PreviousVersionNode
::~
PreviousVersionNode
()
{
if
(
_prev_constant_pool
!=
NULL
)
{
_prev_constant_pool
=
NULL
;
}
if
(
_prev_EMCP_methods
!=
NULL
)
{
delete
_prev_EMCP_methods
;
}
}
// Construct a helper for walking the previous versions array
PreviousVersionWalker
::
PreviousVersionWalker
(
Thread
*
thread
,
InstanceKlass
*
ik
)
{
_thread
=
thread
;
_previous_versions
=
ik
->
previous_versions
();
_current_index
=
0
;
_current_p
=
NULL
;
_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.
PreviousVersionNode
*
PreviousVersionWalker
::
next_previous_version
()
{
if
(
_previous_versions
==
NULL
)
{
// no previous versions so nothing to return
return
NULL
;
}
_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
++
);
// 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
;
}
return
NULL
;
}
// end next_previous_version()
src/share/vm/oops/instanceKlass.hpp
浏览文件 @
cd06fea7
...
...
@@ -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
浏览文件 @
cd06fea7
...
...
@@ -468,6 +468,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
浏览文件 @
cd06fea7
...
...
@@ -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
浏览文件 @
cd06fea7
...
...
@@ -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
浏览文件 @
cd06fea7
...
...
@@ -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
浏览文件 @
cd06fea7
...
...
@@ -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/jvmtiGetLoadedClasses.cpp
浏览文件 @
cd06fea7
/*
* Copyright (c) 2003, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 201
8
, 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
...
...
@@ -27,6 +27,9 @@
#include "memory/universe.inline.hpp"
#include "prims/jvmtiGetLoadedClasses.hpp"
#include "runtime/thread.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#endif
// The closure for GetLoadedClasses
...
...
@@ -35,6 +38,20 @@ private:
Stack
<
jclass
,
mtInternal
>
_classStack
;
JvmtiEnv
*
_env
;
// Tell the GC to keep this klass alive
static
void
ensure_klass_alive
(
oop
o
)
{
// A klass that was previously considered dead can be looked up in the
// CLD/SD, and its _java_mirror or _class_loader can be stored in a root
// or a reachable object making it alive again. The SATB part of G1 needs
// to get notified about this potential resurrection, otherwise the marking
// might not find the object.
#if INCLUDE_ALL_GCS
if
(
UseG1GC
&&
o
!=
NULL
)
{
G1SATBCardTableModRefBS
::
enqueue
(
o
);
}
#endif
}
public:
LoadedClassesClosure
(
JvmtiEnv
*
env
)
{
_env
=
env
;
...
...
@@ -43,6 +60,7 @@ public:
void
do_klass
(
Klass
*
k
)
{
// Collect all jclasses
_classStack
.
push
((
jclass
)
_env
->
jni_reference
(
k
->
java_mirror
()));
ensure_klass_alive
(
k
->
java_mirror
());
}
int
extract
(
jclass
*
result_list
)
{
...
...
src/share/vm/prims/jvmtiImpl.cpp
浏览文件 @
cd06fea7
...
...
@@ -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
浏览文件 @
cd06fea7
...
...
@@ -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
浏览文件 @
cd06fea7
...
...
@@ -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
...
...
src/share/vm/prims/whitebox.cpp
浏览文件 @
cd06fea7
/*
* Copyright (c) 2012, 201
6
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 201
8
, 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
...
...
@@ -158,6 +158,9 @@ WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring s
}
WB_END
#ifdef LINUX
#include "utilities/elfFile.hpp"
#endif
WB_ENTRY
(
jlong
,
WB_GetCompressedOopsMaxHeapSize
(
JNIEnv
*
env
,
jobject
o
))
{
return
(
jlong
)
Arguments
::
max_heap_for_compressed_oops
();
...
...
@@ -1010,6 +1013,21 @@ void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread,
}
}
// Checks that the library libfile has the noexecstack bit set.
WB_ENTRY
(
jboolean
,
WB_CheckLibSpecifiesNoexecstack
(
JNIEnv
*
env
,
jobject
o
,
jstring
libfile
))
jboolean
ret
=
false
;
#ifdef LINUX
// Can't be in VM when we call JNI.
ThreadToNativeFromVM
ttnfv
(
thread
);
const
char
*
lf
=
env
->
GetStringUTFChars
(
libfile
,
NULL
);
CHECK_JNI_EXCEPTION_
(
env
,
0
);
ElfFile
ef
(
lf
);
ret
=
(
jboolean
)
ef
.
specifies_noexecstack
();
env
->
ReleaseStringUTFChars
(
libfile
,
lf
);
#endif
return
ret
;
WB_END
#define CC (char*)
static
JNINativeMethod
methods
[]
=
{
...
...
@@ -1121,6 +1139,8 @@ static JNINativeMethod methods[] = {
(
void
*
)
&
WB_GetNMethod
},
{
CC
"isMonitorInflated"
,
CC
"(Ljava/lang/Object;)Z"
,
(
void
*
)
&
WB_IsMonitorInflated
},
{
CC
"forceSafepoint"
,
CC
"()V"
,
(
void
*
)
&
WB_ForceSafepoint
},
{
CC
"checkLibSpecifiesNoexecstack"
,
CC
"(Ljava/lang/String;)Z"
,
(
void
*
)
&
WB_CheckLibSpecifiesNoexecstack
},
};
#undef CC
...
...
test/compiler/profiling/spectrapredefineclass/Agent.java
0 → 100644
浏览文件 @
cd06fea7
/*
* 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
浏览文件 @
cd06fea7
/*
* 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
浏览文件 @
cd06fea7
/*
* 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
浏览文件 @
cd06fea7
/*
* 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
();
}
}
}
test/runtime/execstack/TestCheckJDK.java
0 → 100644
浏览文件 @
cd06fea7
/*
* Copyright (c) 2017, 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
* 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 Testexecstack.java
* @summary Searches for all libraries in test VM and checks that they
* have the noexecstack bit set.
* @requires (os.family == "linux")
* @library /testlibrary /testlibrary/whitebox
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* TestCheckJDK
*/
import
com.oracle.java.testlibrary.Asserts
;
import
sun.hotspot.WhiteBox
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
public
class
TestCheckJDK
{
static
boolean
testPassed
=
true
;
private
static
final
WhiteBox
WB
=
WhiteBox
.
getWhiteBox
();
static
void
checkExecStack
(
Path
file
)
{
String
filename
=
file
.
toString
();
if
(
filename
.
endsWith
(
".so"
))
{
if
(!
WB
.
checkLibSpecifiesNoexecstack
(
filename
))
{
System
.
out
.
println
(
"Library does not have the noexecstack bit set: "
+
filename
);
testPassed
=
false
;
}
}
}
public
static
void
main
(
String
[]
args
)
throws
Throwable
{
String
vmInstallDir
=
System
.
getProperty
(
"java.home"
);
Files
.
walk
(
Paths
.
get
(
vmInstallDir
)).
filter
(
Files:
:
isRegularFile
).
forEach
(
TestCheckJDK:
:
checkExecStack
);
Asserts
.
assertTrue
(
testPassed
,
"The tested VM contains libs that don't have the noexecstack "
+
"bit set. They must be linked with -z,noexecstack."
);
}
}
test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
浏览文件 @
cd06fea7
/*
* Copyright (c) 2012, 201
6
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 201
8
, 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
...
...
@@ -235,4 +235,7 @@ public class WhiteBox {
// Class Data Sharing
public
native
boolean
isSharedClass
(
Class
<?>
c
);
// Returns true on linux if library has the noexecstack flag set.
public
native
boolean
checkLibSpecifiesNoexecstack
(
String
libfilename
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录