Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
4b2183fb
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看板
提交
4b2183fb
编写于
2月 13, 2013
作者:
S
sspitsyn
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
29c83a97
1b013f8b
变更
39
展开全部
隐藏空白更改
内联
并排
Showing
39 changed file
with
1467 addition
and
1041 deletion
+1467
-1041
agent/src/os/bsd/MacosxDebuggerLocal.m
agent/src/os/bsd/MacosxDebuggerLocal.m
+109
-23
agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java
...are/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java
+1
-1
agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
...lasses/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
+12
-7
agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java
...share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java
+10
-8
agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java
...t/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java
+45
-13
agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java
...hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java
+9
-4
src/os/bsd/vm/osThread_bsd.hpp
src/os/bsd/vm/osThread_bsd.hpp
+9
-0
src/os/bsd/vm/os_bsd.cpp
src/os/bsd/vm/os_bsd.cpp
+14
-0
src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp
src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp
+3
-4
src/share/vm/classfile/classFileParser.cpp
src/share/vm/classfile/classFileParser.cpp
+203
-217
src/share/vm/classfile/classFileParser.hpp
src/share/vm/classfile/classFileParser.hpp
+28
-14
src/share/vm/classfile/defaultMethods.cpp
src/share/vm/classfile/defaultMethods.cpp
+4
-39
src/share/vm/memory/heapInspection.hpp
src/share/vm/memory/heapInspection.hpp
+6
-2
src/share/vm/oops/annotations.cpp
src/share/vm/oops/annotations.cpp
+13
-63
src/share/vm/oops/annotations.hpp
src/share/vm/oops/annotations.hpp
+10
-79
src/share/vm/oops/constMethod.cpp
src/share/vm/oops/constMethod.cpp
+143
-85
src/share/vm/oops/constMethod.hpp
src/share/vm/oops/constMethod.hpp
+128
-43
src/share/vm/oops/cpCache.cpp
src/share/vm/oops/cpCache.cpp
+35
-15
src/share/vm/oops/cpCache.hpp
src/share/vm/oops/cpCache.hpp
+10
-5
src/share/vm/oops/instanceKlass.cpp
src/share/vm/oops/instanceKlass.cpp
+18
-16
src/share/vm/oops/instanceKlass.hpp
src/share/vm/oops/instanceKlass.hpp
+18
-14
src/share/vm/oops/klassVtable.cpp
src/share/vm/oops/klassVtable.cpp
+63
-39
src/share/vm/oops/klassVtable.hpp
src/share/vm/oops/klassVtable.hpp
+9
-11
src/share/vm/oops/method.cpp
src/share/vm/oops/method.cpp
+36
-95
src/share/vm/oops/method.hpp
src/share/vm/oops/method.hpp
+14
-42
src/share/vm/prims/jvm.cpp
src/share/vm/prims/jvm.cpp
+2
-3
src/share/vm/prims/jvm.h
src/share/vm/prims/jvm.h
+1
-2
src/share/vm/prims/jvmtiRedefineClasses.cpp
src/share/vm/prims/jvmtiRedefineClasses.cpp
+144
-167
src/share/vm/prims/jvmtiRedefineClasses.hpp
src/share/vm/prims/jvmtiRedefineClasses.hpp
+6
-8
src/share/vm/prims/jvmtiRedefineClassesTrace.hpp
src/share/vm/prims/jvmtiRedefineClassesTrace.hpp
+9
-2
src/share/vm/runtime/fieldDescriptor.cpp
src/share/vm/runtime/fieldDescriptor.cpp
+3
-6
src/share/vm/runtime/vmStructs.cpp
src/share/vm/runtime/vmStructs.cpp
+13
-10
src/share/vm/utilities/accessFlags.cpp
src/share/vm/utilities/accessFlags.cpp
+3
-3
src/share/vm/utilities/accessFlags.hpp
src/share/vm/utilities/accessFlags.hpp
+5
-1
test/runtime/8007320/ConstMethodTest.java
test/runtime/8007320/ConstMethodTest.java
+148
-0
test/runtime/CommandLine/BooleanFlagWithInvalidValue.java
test/runtime/CommandLine/BooleanFlagWithInvalidValue.java
+49
-0
test/runtime/CommandLine/FlagWithInvalidValue.java
test/runtime/CommandLine/FlagWithInvalidValue.java
+42
-0
test/runtime/CommandLine/NonBooleanFlagWithInvalidBooleanPrefix.java
...e/CommandLine/NonBooleanFlagWithInvalidBooleanPrefix.java
+50
-0
test/runtime/CommandLine/UnrecognizedVMOption.java
test/runtime/CommandLine/UnrecognizedVMOption.java
+42
-0
未找到文件。
agent/src/os/bsd/MacosxDebuggerLocal.m
浏览文件 @
4b2183fb
...
...
@@ -97,7 +97,8 @@ static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
* Method: init0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
JNIEXPORT void JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
taskID = (*env)->GetFieldID(env, cls, "task", "J");
CHECK_EXCEPTION;
...
...
@@ -108,7 +109,11 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(
* Method: lookupByName0
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
JNIEXPORT jlong JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(
JNIEnv *env, jobject this_obj,
jstring objectName, jstring symbolName)
{
jlong address = 0;
JNF_COCOA_ENTER(env);
...
...
@@ -137,7 +142,11 @@ JNF_COCOA_EXIT(env);
* Method: readBytesFromProcess0
* Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
*/
JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
JNIEXPORT jbyteArray JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(
JNIEnv *env, jobject this_obj,
jlong addr, jlong numBytes)
{
if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
// must allocate storage instead of using former parameter buf
...
...
@@ -209,12 +218,74 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_
return array;
}
/*
* Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal
* Lookup the thread_t that corresponds to the given thread_id.
* The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO
* and reading the m_ident_info.thread_id returned.
* The returned thread_t is the mach send right to the kernel port for the corresponding thread.
*
* We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self()
* in the VM, but that thread port is not valid for a remote debugger to access the thread.
*/
thread_t
lookupThreadFromThreadId(task_t task, jlong thread_id) {
if (debug) {
printf("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
}
thread_array_t thread_list = NULL;
mach_msg_type_number_t thread_list_count = 0;
thread_t result_thread = 0;
int i;
// get the list of all the send rights
kern_return_t result = task_threads(task, &thread_list, &thread_list_count);
if (result != KERN_SUCCESS) {
if (debug) {
printf("task_threads returned 0x%x\n", result);
}
return 0;
}
for(i = 0 ; i < thread_list_count; i++) {
thread_identifier_info_data_t m_ident_info;
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
// get the THREAD_IDENTIFIER_INFO for the send right
result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count);
if (result != KERN_SUCCESS) {
if (debug) {
printf("thread_info returned 0x%x\n", result);
}
break;
}
// if this is the one we're looking for, return the send right
if (thread_id == m_ident_info.thread_id)
{
result_thread = thread_list[i];
break;
}
}
vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t));
vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count);
return result_thread;
}
/*
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: getThreadIntegerRegisterSet0
* Signature: (
I
)[J
* Signature: (
J
)[J
*/
JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(JNIEnv *env, jobject this_obj, jint lwp_id) {
JNIEXPORT jlongArray JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(
JNIEnv *env, jobject this_obj,
jlong thread_id)
{
if (debug)
printf("getThreadRegisterSet0 called\n");
...
...
@@ -226,8 +297,9 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_
int i;
jlongArray registerArray;
jlong *primitiveArray;
task_t gTask = getTask(env, this_obj);
tid = l
wp_id
;
tid = l
ookupThreadFromThreadId(gTask, thread_id)
;
result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
...
...
@@ -328,19 +400,21 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_
}
/*
* Class: sun_jvm_hotspot_debugger_
macosx_MacOSX
DebuggerLocal
* Class: sun_jvm_hotspot_debugger_
bsd_Bsd
DebuggerLocal
* Method: translateTID0
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *env, jobject this_obj, jint tid) {
Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(
JNIEnv *env, jobject this_obj, jint tid)
{
if (debug)
printf("translateTID0 called on tid = 0x%x\n", (int)tid);
kern_return_t result;
thread_t foreign_tid, usable_tid;
mach_msg_type_name_t type;
foreign_tid = tid;
task_t gTask = getTask(env, this_obj);
...
...
@@ -361,7 +435,10 @@ Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *e
* Method: attach0
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(JNIEnv *env, jobject this_obj, jint jpid) {
JNIEXPORT void JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
JNIEnv *env, jobject this_obj, jint jpid)
{
JNF_COCOA_ENTER(env);
if (getenv("JAVA_SAPROC_DEBUG") != NULL)
debug = JNI_TRUE;
...
...
@@ -401,7 +478,10 @@ JNF_COCOA_EXIT(env);
* Method: detach0
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(JNIEnv *env, jobject this_obj) {
JNIEXPORT void JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
JNIEnv *env, jobject this_obj)
{
JNF_COCOA_ENTER(env);
if (debug) printf("detach0 called\n");
...
...
@@ -419,10 +499,13 @@ JNF_COCOA_EXIT(env);
* Method: load_library
* Signature: (Ljava/lang/String;)L
*/
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIEnv * env,
jclass disclass,
jstring jrepath_s,
jstring libname_s) {
JNIEXPORT jlong JNICALL
Java_sun_jvm_hotspot_asm_Disassembler_load_1library(
JNIEnv * env,
jclass disclass,
jstring jrepath_s,
jstring libname_s)
{
uintptr_t func = 0;
const char* error_message = NULL;
const char* java_home;
...
...
@@ -533,13 +616,16 @@ static int printf_to_env(void* env_pv, const char* format, ...) {
* Method: decode
* Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V
*/
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env,
jobject dis,
jobject visitor,
jlong startPc,
jbyteArray code,
jstring options_s,
jlong decode_instructions_virtual) {
JNIEXPORT void JNICALL
Java_sun_jvm_hotspot_asm_Disassembler_decode(
JNIEnv * env,
jobject dis,
jobject visitor,
jlong startPc,
jbyteArray code,
jstring options_s,
jlong decode_instructions_virtual)
{
jboolean isCopy;
jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
jbyte* end = start + (*env)->GetArrayLength(env, code);
...
...
agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java
浏览文件 @
4b2183fb
...
...
@@ -49,7 +49,7 @@ public interface BsdDebugger extends JVMDebugger {
public
BsdAddress
readCompKlassAddress
(
long
address
)
throws
DebuggerException
;
public
BsdOopHandle
readOopHandle
(
long
address
)
throws
DebuggerException
;
public
BsdOopHandle
readCompOopHandle
(
long
address
)
throws
DebuggerException
;
public
long
[]
getThreadIntegerRegisterSet
(
int
lwp
_id
)
throws
DebuggerException
;
public
long
[]
getThreadIntegerRegisterSet
(
long
unique_thread
_id
)
throws
DebuggerException
;
public
long
getAddressValue
(
Address
addr
)
throws
DebuggerException
;
public
Address
newAddress
(
long
value
)
throws
DebuggerException
;
...
...
agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
浏览文件 @
4b2183fb
...
...
@@ -90,7 +90,7 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
throws
DebuggerException
;
private
native
ClosestSymbol
lookupByAddress0
(
long
address
)
throws
DebuggerException
;
private
native
long
[]
getThreadIntegerRegisterSet0
(
int
lwp
_id
)
private
native
long
[]
getThreadIntegerRegisterSet0
(
long
unique_thread
_id
)
throws
DebuggerException
;
private
native
byte
[]
readBytesFromProcess0
(
long
address
,
long
numBytes
)
throws
DebuggerException
;
...
...
@@ -400,10 +400,15 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
//
/** From the ThreadAccess interface via Debugger and JVMDebugger */
public
ThreadProxy
getThreadForIdentifierAddress
(
Address
threadIdAddr
,
Address
uniqueThreadIdAddr
)
{
return
new
BsdThread
(
this
,
threadIdAddr
,
uniqueThreadIdAddr
);
}
@Override
public
ThreadProxy
getThreadForIdentifierAddress
(
Address
addr
)
{
return
new
BsdThread
(
this
,
addr
);
throw
new
RuntimeException
(
"unimplemented"
);
}
/** From the ThreadAccess interface via Debugger and JVMDebugger */
public
ThreadProxy
getThreadForThreadId
(
long
id
)
{
return
new
BsdThread
(
this
,
id
);
...
...
@@ -455,22 +460,22 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
// Thread context access
//
public
synchronized
long
[]
getThreadIntegerRegisterSet
(
int
lwp
_id
)
public
synchronized
long
[]
getThreadIntegerRegisterSet
(
long
unique_thread
_id
)
throws
DebuggerException
{
requireAttach
();
if
(
isCore
)
{
return
getThreadIntegerRegisterSet0
(
lwp
_id
);
return
getThreadIntegerRegisterSet0
(
unique_thread
_id
);
}
else
{
class
GetThreadIntegerRegisterSetTask
implements
WorkerThreadTask
{
int
lwp
_id
;
long
unique_thread
_id
;
long
[]
result
;
public
void
doit
(
BsdDebuggerLocal
debugger
)
{
result
=
debugger
.
getThreadIntegerRegisterSet0
(
lwp
_id
);
result
=
debugger
.
getThreadIntegerRegisterSet0
(
unique_thread
_id
);
}
}
GetThreadIntegerRegisterSetTask
task
=
new
GetThreadIntegerRegisterSetTask
();
task
.
lwp_id
=
lwp
_id
;
task
.
unique_thread_id
=
unique_thread
_id
;
workerThread
.
execute
(
task
);
return
task
.
result
;
}
...
...
agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java
浏览文件 @
4b2183fb
...
...
@@ -28,21 +28,23 @@ import sun.jvm.hotspot.debugger.*;
class
BsdThread
implements
ThreadProxy
{
private
BsdDebugger
debugger
;
private
int
lwp_id
;
private
int
thread_id
;
private
long
unique_thread_id
;
/** The address argument must be the address of the _thread_id in the
OSThread. It's value is result ::gettid() call. */
BsdThread
(
BsdDebugger
debugger
,
Address
a
ddr
)
{
BsdThread
(
BsdDebugger
debugger
,
Address
threadIdAddr
,
Address
uniqueThreadIdA
ddr
)
{
this
.
debugger
=
debugger
;
// FIXME: size of data fetched here should be configurable.
// However, making it so would produce a dependency on the "types"
// package from the debugger package, which is not desired.
this
.
lwp_id
=
(
int
)
addr
.
getCIntegerAt
(
0
,
4
,
true
);
this
.
thread_id
=
(
int
)
threadIdAddr
.
getCIntegerAt
(
0
,
4
,
true
);
this
.
unique_thread_id
=
uniqueThreadIdAddr
.
getCIntegerAt
(
0
,
8
,
true
);
}
BsdThread
(
BsdDebugger
debugger
,
long
id
)
{
this
.
debugger
=
debugger
;
this
.
lwp
_id
=
(
int
)
id
;
this
.
thread
_id
=
(
int
)
id
;
}
public
boolean
equals
(
Object
obj
)
{
...
...
@@ -50,19 +52,19 @@ class BsdThread implements ThreadProxy {
return
false
;
}
return
(((
BsdThread
)
obj
).
lwp_id
==
lwp
_id
);
return
(((
BsdThread
)
obj
).
thread_id
==
thread
_id
);
}
public
int
hashCode
()
{
return
lwp
_id
;
return
thread
_id
;
}
public
String
toString
()
{
return
Integer
.
toString
(
lwp
_id
);
return
Integer
.
toString
(
thread
_id
);
}
public
ThreadContext
getContext
()
throws
IllegalThreadStateException
{
long
[]
data
=
debugger
.
getThreadIntegerRegisterSet
(
lwp
_id
);
long
[]
data
=
debugger
.
getThreadIntegerRegisterSet
(
unique_thread
_id
);
ThreadContext
context
=
BsdThreadContextFactory
.
createThreadContext
(
debugger
);
for
(
int
i
=
0
;
i
<
data
.
length
;
i
++)
{
context
.
setRegister
(
i
,
data
[
i
]);
...
...
agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java
浏览文件 @
4b2183fb
/*
* Copyright (c) 2003, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 201
3
, 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
...
...
@@ -49,12 +49,18 @@ public class ConstMethod extends VMObject {
private
static
int
HAS_LOCALVARIABLE_TABLE
;
private
static
int
HAS_EXCEPTION_TABLE
;
private
static
int
HAS_GENERIC_SIGNATURE
;
private
static
int
HAS_METHOD_ANNOTATIONS
;
private
static
int
HAS_PARAMETER_ANNOTATIONS
;
private
static
int
HAS_DEFAULT_ANNOTATIONS
;
private
static
int
HAS_TYPE_ANNOTATIONS
;
private
static
final
int
sizeofShort
=
2
;
private
static
synchronized
void
initialize
(
TypeDataBase
db
)
throws
WrongTypeException
{
Type
type
=
db
.
lookupType
(
"ConstMethod"
);
constants
=
new
MetadataField
(
type
.
getAddressField
(
"_constants"
),
0
);
constMethodSize
=
new
CIntField
(
type
.
getCIntegerField
(
"_constMethod_size"
),
0
);
flags
=
new
ByteField
(
type
.
getJByte
Field
(
"_flags"
),
0
);
flags
=
new
CIntField
(
type
.
getCInteger
Field
(
"_flags"
),
0
);
// enum constants for flags
HAS_LINENUMBER_TABLE
=
db
.
lookupIntConstant
(
"ConstMethod::_has_linenumber_table"
).
intValue
();
...
...
@@ -62,6 +68,10 @@ public class ConstMethod extends VMObject {
HAS_LOCALVARIABLE_TABLE
=
db
.
lookupIntConstant
(
"ConstMethod::_has_localvariable_table"
).
intValue
();
HAS_EXCEPTION_TABLE
=
db
.
lookupIntConstant
(
"ConstMethod::_has_exception_table"
).
intValue
();
HAS_GENERIC_SIGNATURE
=
db
.
lookupIntConstant
(
"ConstMethod::_has_generic_signature"
).
intValue
();
HAS_METHOD_ANNOTATIONS
=
db
.
lookupIntConstant
(
"ConstMethod::_has_method_annotations"
).
intValue
();
HAS_PARAMETER_ANNOTATIONS
=
db
.
lookupIntConstant
(
"ConstMethod::_has_parameter_annotations"
).
intValue
();
HAS_DEFAULT_ANNOTATIONS
=
db
.
lookupIntConstant
(
"ConstMethod::_has_default_annotations"
).
intValue
();
HAS_TYPE_ANNOTATIONS
=
db
.
lookupIntConstant
(
"ConstMethod::_has_type_annotations"
).
intValue
();
// Size of Java bytecodes allocated immediately after ConstMethod*.
codeSize
=
new
CIntField
(
type
.
getCIntegerField
(
"_code_size"
),
0
);
...
...
@@ -92,7 +102,7 @@ public class ConstMethod extends VMObject {
// Fields
private
static
MetadataField
constants
;
private
static
CIntField
constMethodSize
;
private
static
Byte
Field
flags
;
private
static
CInt
Field
flags
;
private
static
CIntField
codeSize
;
private
static
CIntField
nameIndex
;
private
static
CIntField
signatureIndex
;
...
...
@@ -123,7 +133,7 @@ public class ConstMethod extends VMObject {
return
constMethodSize
.
getValue
(
this
);
}
public
byte
getFlags
()
{
public
long
getFlags
()
{
return
flags
.
getValue
(
this
);
}
...
...
@@ -253,7 +263,7 @@ public class ConstMethod extends VMObject {
public
void
iterateFields
(
MetadataVisitor
visitor
)
{
visitor
.
doMetadata
(
constants
,
true
);
visitor
.
doCInt
(
constMethodSize
,
true
);
visitor
.
do
Byte
(
flags
,
true
);
visitor
.
do
CInt
(
flags
,
true
);
visitor
.
doCInt
(
codeSize
,
true
);
visitor
.
doCInt
(
nameIndex
,
true
);
visitor
.
doCInt
(
signatureIndex
,
true
);
...
...
@@ -381,6 +391,22 @@ public class ConstMethod extends VMObject {
return
(
getFlags
()
&
HAS_GENERIC_SIGNATURE
)
!=
0
;
}
private
boolean
hasMethodAnnotations
()
{
return
(
getFlags
()
&
HAS_METHOD_ANNOTATIONS
)
!=
0
;
}
private
boolean
hasParameterAnnotations
()
{
return
(
getFlags
()
&
HAS_PARAMETER_ANNOTATIONS
)
!=
0
;
}
private
boolean
hasDefaultAnnotations
()
{
return
(
getFlags
()
&
HAS_DEFAULT_ANNOTATIONS
)
!=
0
;
}
private
boolean
hasTypeAnnotations
()
{
return
(
getFlags
()
&
HAS_TYPE_ANNOTATIONS
)
!=
0
;
}
//---------------------------------------------------------------------------
// Internals only below this point
...
...
@@ -400,9 +426,15 @@ public class ConstMethod extends VMObject {
return
offsetOfCodeEnd
()
+
(
isNative
()
?
2
*
VM
.
getVM
().
getAddressSize
()
:
0
);
}
// Offset of last short in Method*
// Offset of last short in Method*
before annotations, if present
private
long
offsetOfLastU2Element
()
{
return
getSize
()
*
VM
.
getVM
().
getObjectHeap
().
getOopSize
()
-
2
;
int
offset
=
0
;
if
(
hasMethodAnnotations
())
offset
++;
if
(
hasParameterAnnotations
())
offset
++;
if
(
hasTypeAnnotations
())
offset
++;
if
(
hasDefaultAnnotations
())
offset
++;
long
wordSize
=
VM
.
getVM
().
getObjectHeap
().
getOopSize
();
return
(
getSize
()
*
wordSize
)
-
(
offset
*
wordSize
)
-
sizeofShort
;
}
// Offset of the generic signature index
...
...
@@ -411,7 +443,7 @@ public class ConstMethod extends VMObject {
}
private
long
offsetOfCheckedExceptionsLength
()
{
return
hasGenericSignature
()
?
offsetOfLastU2Element
()
-
2
:
return
hasGenericSignature
()
?
offsetOfLastU2Element
()
-
sizeofShort
:
offsetOfLastU2Element
();
}
...
...
@@ -461,11 +493,11 @@ public class ConstMethod extends VMObject {
}
if
(
hasExceptionTable
())
{
return
offsetOfExceptionTable
()
-
2
;
return
offsetOfExceptionTable
()
-
sizeofShort
;
}
else
if
(
hasCheckedExceptions
())
{
return
offsetOfCheckedExceptions
()
-
2
;
return
offsetOfCheckedExceptions
()
-
sizeofShort
;
}
else
{
return
hasGenericSignature
()
?
offsetOfLastU2Element
()
-
2
:
return
hasGenericSignature
()
?
offsetOfLastU2Element
()
-
sizeofShort
:
offsetOfLastU2Element
();
}
}
...
...
@@ -493,9 +525,9 @@ public class ConstMethod extends VMObject {
Assert
.
that
(
hasExceptionTable
(),
"should only be called if table is present"
);
}
if
(
hasCheckedExceptions
())
{
return
offsetOfCheckedExceptions
()
-
2
;
return
offsetOfCheckedExceptions
()
-
sizeofShort
;
}
else
{
return
hasGenericSignature
()
?
offsetOfLastU2Element
()
-
2
:
return
hasGenericSignature
()
?
offsetOfLastU2Element
()
-
sizeofShort
:
offsetOfLastU2Element
();
}
}
...
...
agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java
浏览文件 @
4b2183fb
...
...
@@ -28,6 +28,8 @@ import java.io.*;
import
java.util.*
;
import
sun.jvm.hotspot.debugger.*
;
import
sun.jvm.hotspot.debugger.amd64.*
;
import
sun.jvm.hotspot.debugger.bsd.BsdDebugger
;
import
sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal
;
import
sun.jvm.hotspot.runtime.*
;
import
sun.jvm.hotspot.runtime.amd64.*
;
import
sun.jvm.hotspot.runtime.x86.*
;
...
...
@@ -38,8 +40,9 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
private
static
AddressField
lastJavaFPField
;
private
static
AddressField
osThreadField
;
// Field from OSThread
// Field
s
from OSThread
private
static
CIntegerField
osThreadThreadIDField
;
private
static
CIntegerField
osThreadUniqueThreadIDField
;
// This is currently unneeded but is being kept in case we change
// the currentFrameGuess algorithm
...
...
@@ -61,7 +64,8 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
lastJavaFPField
=
anchorType
.
getAddressField
(
"_last_Java_fp"
);
Type
osThreadType
=
db
.
lookupType
(
"OSThread"
);
osThreadThreadIDField
=
osThreadType
.
getCIntegerField
(
"_thread_id"
);
osThreadThreadIDField
=
osThreadType
.
getCIntegerField
(
"_thread_id"
);
osThreadUniqueThreadIDField
=
osThreadType
.
getCIntegerField
(
"_unique_thread_id"
);
}
public
Address
getLastJavaFP
(
Address
addr
)
{
...
...
@@ -125,8 +129,9 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
Address
osThreadAddr
=
osThreadField
.
getValue
(
addr
);
// Get the address of the _thread_id from the OSThread
Address
threadIdAddr
=
osThreadAddr
.
addOffsetTo
(
osThreadThreadIDField
.
getOffset
());
Address
uniqueThreadIdAddr
=
osThreadAddr
.
addOffsetTo
(
osThreadUniqueThreadIDField
.
getOffset
());
JVMDebugger
debugger
=
VM
.
getVM
().
getDebugger
();
return
debugger
.
getThreadForIdentifierAddress
(
threadIdAddr
);
BsdDebuggerLocal
debugger
=
(
BsdDebuggerLocal
)
VM
.
getVM
().
getDebugger
();
return
debugger
.
getThreadForIdentifierAddress
(
threadIdAddr
,
uniqueThreadIdAddr
);
}
}
src/os/bsd/vm/osThread_bsd.hpp
浏览文件 @
4b2183fb
...
...
@@ -49,6 +49,11 @@
// (e.g. pthread_kill).
pthread_t
_pthread_id
;
// This is the "thread_id" from struct thread_identifier_info. According to a
// comment in thread_info.h, this is a "system-wide unique 64-bit thread id".
// The value is used by SA to correlate threads.
uint64_t
_unique_thread_id
;
sigset_t
_caller_sigmask
;
// Caller's signal mask
public
:
...
...
@@ -77,6 +82,10 @@
_pthread_id
=
tid
;
}
void
set_unique_thread_id
(
uint64_t
id
)
{
_unique_thread_id
=
id
;
}
// ***************************************************************
// suspension support.
// ***************************************************************
...
...
src/os/bsd/vm/os_bsd.cpp
浏览文件 @
4b2183fb
...
...
@@ -657,6 +657,18 @@ extern "C" objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFu
objc_registerThreadWithCollector_t
objc_registerThreadWithCollectorFunction
=
NULL
;
#endif
#ifdef __APPLE__
static
uint64_t
locate_unique_thread_id
()
{
// Additional thread_id used to correlate threads in SA
thread_identifier_info_data_t
m_ident_info
;
mach_msg_type_number_t
count
=
THREAD_IDENTIFIER_INFO_COUNT
;
thread_info
(
::
mach_thread_self
(),
THREAD_IDENTIFIER_INFO
,
(
thread_info_t
)
&
m_ident_info
,
&
count
);
return
m_ident_info
.
thread_id
;
}
#endif
// Thread start routine for all newly created threads
static
void
*
java_start
(
Thread
*
thread
)
{
// Try to randomize the cache line index of hot stack frames.
...
...
@@ -685,6 +697,7 @@ static void *java_start(Thread *thread) {
#ifdef __APPLE__
// thread_id is mach thread on macos
osthread
->
set_thread_id
(
::
mach_thread_self
());
osthread
->
set_unique_thread_id
(
locate_unique_thread_id
());
#else
// thread_id is pthread_id on BSD
osthread
->
set_thread_id
(
::
pthread_self
());
...
...
@@ -847,6 +860,7 @@ bool os::create_attached_thread(JavaThread* thread) {
// Store pthread info into the OSThread
#ifdef __APPLE__
osthread
->
set_thread_id
(
::
mach_thread_self
());
osthread
->
set_unique_thread_id
(
locate_unique_thread_id
());
#else
osthread
->
set_thread_id
(
::
pthread_self
());
#endif
...
...
src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp
浏览文件 @
4b2183fb
...
...
@@ -35,17 +35,16 @@
/* Threads (NOTE: incomplete) */
\
/******************************/
\
nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \
nonstatic_field(OSThread, _
pthread_id, pthread
_t)
nonstatic_field(OSThread, _
unique_thread_id, uint64
_t)
#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
\
/**********************/
\
/*
Posix Thread IDs
*/
\
/*
Thread IDs
*/
\
/**********************/
\
\
declare_unsigned_integer_type(OSThread::thread_id_t) \
declare_unsigned_integer_type(pthread_t)
declare_unsigned_integer_type(OSThread::thread_id_t)
#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
...
...
src/share/vm/classfile/classFileParser.cpp
浏览文件 @
4b2183fb
此差异已折叠。
点击以展开。
src/share/vm/classfile/classFileParser.hpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 1997, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
3
, 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
...
...
@@ -199,29 +199,17 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
constantPoolHandle
cp
,
bool
is_interface
,
AccessFlags
*
promoted_flags
,
AnnotationArray
**
method_annotations
,
AnnotationArray
**
method_parameter_annotations
,
AnnotationArray
**
method_default_annotations
,
AnnotationArray
**
method_type_annotations
,
TRAPS
);
Array
<
Method
*>*
parse_methods
(
ClassLoaderData
*
loader_data
,
constantPoolHandle
cp
,
bool
is_interface
,
AccessFlags
*
promoted_flags
,
bool
*
has_final_method
,
Array
<
AnnotationArray
*>**
methods_annotations
,
Array
<
AnnotationArray
*>**
methods_parameter_annotations
,
Array
<
AnnotationArray
*>**
methods_default_annotations
,
Array
<
AnnotationArray
*>**
methods_type_annotations
,
bool
*
has_default_method
,
TRAPS
);
Array
<
int
>*
sort_methods
(
ClassLoaderData
*
loader_data
,
Array
<
Method
*>*
methods
,
Array
<
AnnotationArray
*>*
methods_annotations
,
Array
<
AnnotationArray
*>*
methods_parameter_annotations
,
Array
<
AnnotationArray
*>*
methods_default_annotations
,
Array
<
AnnotationArray
*>*
methods_type_annotations
,
TRAPS
);
TRAPS
);
u2
*
parse_exception_table
(
ClassLoaderData
*
loader_data
,
u4
code_length
,
u4
exception_table_length
,
constantPoolHandle
cp
,
TRAPS
);
...
...
@@ -377,6 +365,32 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
:
cp
->
tag_at
(
index
).
is_klass_reference
());
}
void
copy_localvariable_table
(
ConstMethod
*
cm
,
int
lvt_cnt
,
u2
*
localvariable_table_length
,
u2
**
localvariable_table_start
,
int
lvtt_cnt
,
u2
*
localvariable_type_table_length
,
u2
**
localvariable_type_table_start
,
TRAPS
);
void
copy_method_annotations
(
ClassLoaderData
*
loader_data
,
ConstMethod
*
cm
,
u1
*
runtime_visible_annotations
,
int
runtime_visible_annotations_length
,
u1
*
runtime_invisible_annotations
,
int
runtime_invisible_annotations_length
,
u1
*
runtime_visible_parameter_annotations
,
int
runtime_visible_parameter_annotations_length
,
u1
*
runtime_invisible_parameter_annotations
,
int
runtime_invisible_parameter_annotations_length
,
u1
*
runtime_visible_type_annotations
,
int
runtime_visible_type_annotations_length
,
u1
*
runtime_invisible_type_annotations
,
int
runtime_invisible_type_annotations_length
,
u1
*
annotation_default
,
int
annotation_default_length
,
TRAPS
);
public:
// Constructor
ClassFileParser
(
ClassFileStream
*
st
)
{
set_stream
(
st
);
}
...
...
src/share/vm/classfile/defaultMethods.cpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012,
2013,
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -1146,9 +1146,10 @@ static Method* new_method(
address
code_start
=
static_cast
<
address
>
(
bytecodes
->
adr_at
(
0
));
int
code_length
=
bytecodes
->
length
();
InlineTableSizes
sizes
;
Method
*
m
=
Method
::
allocate
(
cp
->
pool_holder
()
->
class_loader_data
(),
code_length
,
flags
,
0
,
0
,
0
,
0
,
0
,
0
,
code_length
,
flags
,
&
sizes
,
mt
,
CHECK_NULL
);
m
->
set_constants
(
NULL
);
// This will get filled in later
...
...
@@ -1285,33 +1286,15 @@ static void merge_in_new_methods(InstanceKlass* klass,
enum
{
ANNOTATIONS
,
PARAMETERS
,
DEFAULTS
,
NUM_ARRAYS
};
Array
<
AnnotationArray
*>*
original_annots
[
NUM_ARRAYS
]
=
{
NULL
};
Array
<
Method
*>*
original_methods
=
klass
->
methods
();
Annotations
*
annots
=
klass
->
annotations
();
if
(
annots
!=
NULL
)
{
original_annots
[
ANNOTATIONS
]
=
annots
->
methods_annotations
();
original_annots
[
PARAMETERS
]
=
annots
->
methods_parameter_annotations
();
original_annots
[
DEFAULTS
]
=
annots
->
methods_default_annotations
();
}
Array
<
int
>*
original_ordering
=
klass
->
method_ordering
();
Array
<
int
>*
merged_ordering
=
Universe
::
the_empty_int_array
();
int
new_size
=
klass
->
methods
()
->
length
()
+
new_methods
->
length
();
Array
<
AnnotationArray
*>*
merged_annots
[
NUM_ARRAYS
];
Array
<
Method
*>*
merged_methods
=
MetadataFactory
::
new_array
<
Method
*>
(
klass
->
class_loader_data
(),
new_size
,
NULL
,
CHECK
);
for
(
int
i
=
0
;
i
<
NUM_ARRAYS
;
++
i
)
{
if
(
original_annots
[
i
]
!=
NULL
)
{
merged_annots
[
i
]
=
MetadataFactory
::
new_array
<
AnnotationArray
*>
(
klass
->
class_loader_data
(),
new_size
,
CHECK
);
}
else
{
merged_annots
[
i
]
=
NULL
;
}
}
if
(
original_ordering
!=
NULL
&&
original_ordering
->
length
()
>
0
)
{
merged_ordering
=
MetadataFactory
::
new_array
<
int
>
(
klass
->
class_loader_data
(),
new_size
,
CHECK
);
...
...
@@ -1338,12 +1321,6 @@ static void merge_in_new_methods(InstanceKlass* klass,
(
new_method
==
NULL
||
orig_method
->
name
()
<
new_method
->
name
()))
{
merged_methods
->
at_put
(
i
,
orig_method
);
original_methods
->
at_put
(
orig_idx
,
NULL
);
for
(
int
j
=
0
;
j
<
NUM_ARRAYS
;
++
j
)
{
if
(
merged_annots
[
j
]
!=
NULL
)
{
merged_annots
[
j
]
->
at_put
(
i
,
original_annots
[
j
]
->
at
(
orig_idx
));
original_annots
[
j
]
->
at_put
(
orig_idx
,
NULL
);
}
}
if
(
merged_ordering
->
length
()
>
0
)
{
merged_ordering
->
at_put
(
i
,
original_ordering
->
at
(
orig_idx
));
}
...
...
@@ -1372,21 +1349,9 @@ static void merge_in_new_methods(InstanceKlass* klass,
// Replace klass methods with new merged lists
klass
->
set_methods
(
merged_methods
);
if
(
annots
!=
NULL
)
{
annots
->
set_methods_annotations
(
merged_annots
[
ANNOTATIONS
]);
annots
->
set_methods_parameter_annotations
(
merged_annots
[
PARAMETERS
]);
annots
->
set_methods_default_annotations
(
merged_annots
[
DEFAULTS
]);
}
else
{
assert
(
merged_annots
[
ANNOTATIONS
]
==
NULL
,
"Must be"
);
assert
(
merged_annots
[
PARAMETERS
]
==
NULL
,
"Must be"
);
assert
(
merged_annots
[
DEFAULTS
]
==
NULL
,
"Must be"
);
}
ClassLoaderData
*
cld
=
klass
->
class_loader_data
();
MetadataFactory
::
free_array
(
cld
,
original_methods
);
for
(
int
i
=
0
;
i
<
NUM_ARRAYS
;
++
i
)
{
MetadataFactory
::
free_array
(
cld
,
original_annots
[
i
]);
}
if
(
original_ordering
->
length
()
>
0
)
{
klass
->
set_method_ordering
(
merged_ordering
);
MetadataFactory
::
free_array
(
cld
,
original_ordering
);
...
...
src/share/vm/memory/heapInspection.hpp
浏览文件 @
4b2183fb
...
...
@@ -85,16 +85,20 @@
"Number of bytes used by the InstanceKlass::singers() array") \
f(class_annotations_bytes, class_annotations, \
"Size of class annotations") \
f(class_type_annotations_bytes, class_type_annotations, \
"Size of class type annotations") \
f(fields_annotations_bytes, fields_annotations, \
"Size of field annotations") \
f(fields_type_annotations_bytes, fields_type_annotations, \
"Size of field type annotations") \
f(methods_annotations_bytes, methods_annotations, \
"Size of method annotations") \
f(methods_parameter_annotations_bytes, methods_parameter_annotations, \
"Size of method parameter annotations") \
f(methods_type_annotations_bytes, methods_type_annotations, \
"Size of methods type annotations") \
f(methods_default_annotations_bytes, methods_default_annotations, \
"Size of methods default annotations") \
f(type_annotations_bytes, type_annotations, \
"Size of type annotations") \
f(annotations_bytes, annotations, \
"Size of all annotations") \
f(cp_bytes, Cp, \
...
...
src/share/vm/oops/annotations.cpp
浏览文件 @
4b2183fb
...
...
@@ -36,16 +36,8 @@ Annotations* Annotations::allocate(ClassLoaderData* loader_data, TRAPS) {
return
new
(
loader_data
,
size
(),
true
,
THREAD
)
Annotations
();
}
Annotations
*
Annotations
::
allocate
(
ClassLoaderData
*
loader_data
,
Array
<
AnnotationArray
*>*
fa
,
Array
<
AnnotationArray
*>*
ma
,
Array
<
AnnotationArray
*>*
mpa
,
Array
<
AnnotationArray
*>*
mda
,
TRAPS
)
{
return
new
(
loader_data
,
size
(),
true
,
THREAD
)
Annotations
(
fa
,
ma
,
mpa
,
mda
);
}
// helper
static
void
free_contents
(
ClassLoaderData
*
loader_data
,
Array
<
AnnotationArray
*>*
p
)
{
void
Annotations
::
free_contents
(
ClassLoaderData
*
loader_data
,
Array
<
AnnotationArray
*>*
p
)
{
if
(
p
!=
NULL
)
{
for
(
int
i
=
0
;
i
<
p
->
length
();
i
++
)
{
MetadataFactory
::
free_array
<
u1
>
(
loader_data
,
p
->
at
(
i
));
...
...
@@ -59,44 +51,16 @@ void Annotations::deallocate_contents(ClassLoaderData* loader_data) {
MetadataFactory
::
free_array
<
u1
>
(
loader_data
,
class_annotations
());
}
free_contents
(
loader_data
,
fields_annotations
());
free_contents
(
loader_data
,
methods_annotations
());
free_contents
(
loader_data
,
methods_parameter_annotations
());
free_contents
(
loader_data
,
methods_default_annotations
());
// Recursively deallocate optional Annotations linked through this one
MetadataFactory
::
free_metadata
(
loader_data
,
type_annotations
());
}
// Set the annotation at 'idnum' to 'anno'.
// We don't want to create or extend the array if 'anno' is NULL, since that is the
// default value. However, if the array exists and is long enough, we must set NULL values.
void
Annotations
::
set_methods_annotations_of
(
instanceKlassHandle
ik
,
int
idnum
,
AnnotationArray
*
anno
,
Array
<
AnnotationArray
*>**
md_p
,
TRAPS
)
{
Array
<
AnnotationArray
*>*
md
=
*
md_p
;
if
(
md
!=
NULL
&&
md
->
length
()
>
idnum
)
{
md
->
at_put
(
idnum
,
anno
);
}
else
if
(
anno
!=
NULL
)
{
// create the array
int
length
=
MAX2
(
idnum
+
1
,
(
int
)
ik
->
idnum_allocated_count
());
md
=
MetadataFactory
::
new_array
<
AnnotationArray
*>
(
ik
->
class_loader_data
(),
length
,
CHECK
);
if
(
*
md_p
!=
NULL
)
{
// copy the existing entries
for
(
int
index
=
0
;
index
<
(
*
md_p
)
->
length
();
index
++
)
{
md
->
at_put
(
index
,
(
*
md_p
)
->
at
(
index
));
}
}
set_annotations
(
md
,
md_p
);
md
->
at_put
(
idnum
,
anno
);
}
// if no array and idnum isn't included there is nothing to do
if
(
class_type_annotations
()
!=
NULL
)
{
MetadataFactory
::
free_array
<
u1
>
(
loader_data
,
class_type_annotations
());
}
free_contents
(
loader_data
,
fields_type_annotations
());
}
// Keep created annotations in a global growable array (should be hashtable)
// need to add, search, delete when class is unloaded.
// Does it need a lock? yes. This sucks.
// Copy annotations to JVM call or reflection to the java heap.
// The alternative to creating this array and adding to Java heap pressure
// is to have a hashtable of the already created typeArrayOops
typeArrayOop
Annotations
::
make_java_array
(
AnnotationArray
*
annotations
,
TRAPS
)
{
if
(
annotations
!=
NULL
)
{
int
length
=
annotations
->
length
();
...
...
@@ -132,28 +96,15 @@ julong Annotations::count_bytes(Array<AnnotationArray*>* p) {
void
Annotations
::
collect_statistics
(
KlassSizeStats
*
sz
)
const
{
sz
->
_annotations_bytes
=
sz
->
count
(
this
);
sz
->
_class_annotations_bytes
=
sz
->
count
(
class_annotations
());
sz
->
_class_type_annotations_bytes
=
sz
->
count
(
class_type_annotations
());
sz
->
_fields_annotations_bytes
=
count_bytes
(
fields_annotations
());
sz
->
_methods_annotations_bytes
=
count_bytes
(
methods_annotations
());
sz
->
_methods_parameter_annotations_bytes
=
count_bytes
(
methods_parameter_annotations
());
sz
->
_methods_default_annotations_bytes
=
count_bytes
(
methods_default_annotations
());
const
Annotations
*
type_anno
=
type_annotations
();
if
(
type_anno
!=
NULL
)
{
sz
->
_type_annotations_bytes
=
sz
->
count
(
type_anno
);
sz
->
_type_annotations_bytes
+=
sz
->
count
(
type_anno
->
class_annotations
());
sz
->
_type_annotations_bytes
+=
count_bytes
(
type_anno
->
fields_annotations
());
sz
->
_type_annotations_bytes
+=
count_bytes
(
type_anno
->
methods_annotations
());
}
sz
->
_fields_type_annotations_bytes
=
count_bytes
(
fields_type_annotations
());
sz
->
_annotations_bytes
+=
sz
->
_class_annotations_bytes
+
sz
->
_class_type_annotations_bytes
+
sz
->
_fields_annotations_bytes
+
sz
->
_methods_annotations_bytes
+
sz
->
_methods_parameter_annotations_bytes
+
sz
->
_methods_default_annotations_bytes
+
sz
->
_type_annotations_bytes
;
sz
->
_fields_type_annotations_bytes
;
sz
->
_ro_bytes
+=
sz
->
_annotations_bytes
;
}
...
...
@@ -165,8 +116,7 @@ void Annotations::collect_statistics(KlassSizeStats *sz) const {
void
Annotations
::
print_on
(
outputStream
*
st
)
const
{
st
->
print
(
BULLET
"class_annotations "
);
class_annotations
()
->
print_value_on
(
st
);
st
->
print
(
BULLET
"fields_annotations "
);
fields_annotations
()
->
print_value_on
(
st
);
st
->
print
(
BULLET
"methods_annotations "
);
methods_annotations
()
->
print_value_on
(
st
);
st
->
print
(
BULLET
"methods_parameter_annotations"
);
methods_parameter_annotations
()
->
print_value_on
(
st
);
st
->
print
(
BULLET
"methods_default_annotations "
);
methods_default_annotations
()
->
print_value_on
(
st
);
st
->
print
(
BULLET
"class_type_annotations "
);
class_type_annotations
()
->
print_value_on
(
st
);
st
->
print
(
BULLET
"fields_type_annotations "
);
fields_type_annotations
()
->
print_value_on
(
st
);
}
#endif // PRODUCT
src/share/vm/oops/annotations.hpp
浏览文件 @
4b2183fb
...
...
@@ -49,38 +49,15 @@ class Annotations: public MetaspaceObj {
// Annotation objects (byte arrays) for fields, or null if no annotations.
// Indices correspond to entries (not indices) in fields array.
Array
<
AnnotationArray
*>*
_fields_annotations
;
// Annotation objects (byte arrays) for methods, or null if no annotations.
// Index is the idnum, which is initially the same as the methods array index.
Array
<
AnnotationArray
*>*
_methods_annotations
;
// Annotation objects (byte arrays) for methods' parameters, or null if no
// such annotations.
// Index is the idnum, which is initially the same as the methods array index.
Array
<
AnnotationArray
*>*
_methods_parameter_annotations
;
// Annotation objects (byte arrays) for methods' default values, or null if no
// such annotations.
// Index is the idnum, which is initially the same as the methods array index.
Array
<
AnnotationArray
*>*
_methods_default_annotations
;
// Type annotations for this class, or null if none.
Annotations
*
_type_annotations
;
// Constructor where some some values are known to not be null
Annotations
(
Array
<
AnnotationArray
*>*
fa
,
Array
<
AnnotationArray
*>*
ma
,
Array
<
AnnotationArray
*>*
mpa
,
Array
<
AnnotationArray
*>*
mda
)
:
_class_annotations
(
NULL
),
_fields_annotations
(
fa
),
_methods_annotations
(
ma
),
_methods_parameter_annotations
(
mpa
),
_methods_default_annotations
(
mda
),
_type_annotations
(
NULL
)
{}
AnnotationArray
*
_class_type_annotations
;
Array
<
AnnotationArray
*>*
_fields_type_annotations
;
public:
// Allocate instance of this class
static
Annotations
*
allocate
(
ClassLoaderData
*
loader_data
,
TRAPS
);
static
Annotations
*
allocate
(
ClassLoaderData
*
loader_data
,
Array
<
AnnotationArray
*>*
fa
,
Array
<
AnnotationArray
*>*
ma
,
Array
<
AnnotationArray
*>*
mpa
,
Array
<
AnnotationArray
*>*
mda
,
TRAPS
);
static
void
free_contents
(
ClassLoaderData
*
loader_data
,
Array
<
AnnotationArray
*>*
p
);
void
deallocate_contents
(
ClassLoaderData
*
loader_data
);
DEBUG_ONLY
(
bool
on_stack
()
{
return
false
;
})
// for template
...
...
@@ -93,61 +70,24 @@ class Annotations: public MetaspaceObj {
// Constructor to initialize to null
Annotations
()
:
_class_annotations
(
NULL
),
_fields_annotations
(
NULL
),
_methods_annotations
(
NULL
),
_methods_parameter_annotations
(
NULL
),
_methods_default_annotations
(
NULL
),
_type_annotations
(
NULL
)
{}
_class_type_annotations
(
NULL
),
_fields_type_annotations
(
NULL
)
{}
AnnotationArray
*
class_annotations
()
const
{
return
_class_annotations
;
}
Array
<
AnnotationArray
*>*
fields_annotations
()
const
{
return
_fields_annotations
;
}
Array
<
AnnotationArray
*>*
methods_annotations
()
const
{
return
_methods_annotations
;
}
Array
<
AnnotationArray
*>*
methods_parameter_annotations
()
const
{
return
_methods_parameter_annotations
;
}
Array
<
AnnotationArray
*>*
methods_default_annotations
()
const
{
return
_methods_default_annotations
;
}
Annotations
*
type_annotations
()
const
{
return
_type_annotations
;
}
AnnotationArray
*
class_type_annotations
()
const
{
return
_class_type_annotations
;
}
Array
<
AnnotationArray
*>*
fields_type_annotations
()
const
{
return
_fields_type_annotations
;
}
void
set_class_annotations
(
AnnotationArray
*
md
)
{
_class_annotations
=
md
;
}
void
set_fields_annotations
(
Array
<
AnnotationArray
*>*
md
)
{
_fields_annotations
=
md
;
}
void
set_methods_annotations
(
Array
<
AnnotationArray
*>*
md
)
{
_methods_annotations
=
md
;
}
void
set_methods_parameter_annotations
(
Array
<
AnnotationArray
*>*
md
)
{
_methods_parameter_annotations
=
md
;
}
void
set_methods_default_annotations
(
Array
<
AnnotationArray
*>*
md
)
{
_methods_default_annotations
=
md
;
}
void
set_type_annotations
(
Annotations
*
annos
)
{
_type_annotations
=
annos
;
}
// Redefine classes support
AnnotationArray
*
get_method_annotations_of
(
int
idnum
)
{
return
get_method_annotations_from
(
idnum
,
_methods_annotations
);
}
AnnotationArray
*
get_method_parameter_annotations_of
(
int
idnum
)
{
return
get_method_annotations_from
(
idnum
,
_methods_parameter_annotations
);
}
AnnotationArray
*
get_method_default_annotations_of
(
int
idnum
)
{
return
get_method_annotations_from
(
idnum
,
_methods_default_annotations
);
}
void
set_method_annotations_of
(
instanceKlassHandle
ik
,
int
idnum
,
AnnotationArray
*
anno
,
TRAPS
)
{
set_methods_annotations_of
(
ik
,
idnum
,
anno
,
&
_methods_annotations
,
THREAD
);
}
void
set_method_parameter_annotations_of
(
instanceKlassHandle
ik
,
int
idnum
,
AnnotationArray
*
anno
,
TRAPS
)
{
set_methods_annotations_of
(
ik
,
idnum
,
anno
,
&
_methods_parameter_annotations
,
THREAD
);
}
void
set_method_default_annotations_of
(
instanceKlassHandle
ik
,
int
idnum
,
AnnotationArray
*
anno
,
TRAPS
)
{
set_methods_annotations_of
(
ik
,
idnum
,
anno
,
&
_methods_default_annotations
,
THREAD
);
}
void
set_class_type_annotations
(
AnnotationArray
*
cta
)
{
_class_type_annotations
=
cta
;
}
void
set_fields_type_annotations
(
Array
<
AnnotationArray
*>*
fta
)
{
_fields_type_annotations
=
fta
;
}
// Turn metadata annotations into a Java heap object (oop)
static
typeArrayOop
make_java_array
(
AnnotationArray
*
annotations
,
TRAPS
);
inline
AnnotationArray
*
get_method_annotations_from
(
int
idnum
,
Array
<
AnnotationArray
*>*
annos
);
void
set_annotations
(
Array
<
AnnotationArray
*>*
md
,
Array
<
AnnotationArray
*>**
md_p
)
{
*
md_p
=
md
;
}
bool
is_klass
()
const
{
return
false
;
}
private:
void
set_methods_annotations_of
(
instanceKlassHandle
ik
,
int
idnum
,
AnnotationArray
*
anno
,
Array
<
AnnotationArray
*>**
md_p
,
TRAPS
);
static
julong
count_bytes
(
Array
<
AnnotationArray
*>*
p
);
public:
const
char
*
internal_name
()
const
{
return
"{constant pool}"
;
}
...
...
@@ -156,13 +96,4 @@ class Annotations: public MetaspaceObj {
#endif
void
print_value_on
(
outputStream
*
st
)
const
;
};
// For method with idnum get the method's Annotations
inline
AnnotationArray
*
Annotations
::
get_method_annotations_from
(
int
idnum
,
Array
<
AnnotationArray
*>*
annos
)
{
if
(
annos
==
NULL
||
annos
->
length
()
<=
idnum
)
{
return
NULL
;
}
return
annos
->
at
(
idnum
);
}
#endif // SHARE_VM_OOPS_ANNOTATIONS_HPP
src/share/vm/oops/constMethod.cpp
浏览文件 @
4b2183fb
...
...
@@ -36,51 +36,26 @@ const u2 ConstMethod::UNSET_IDNUM = 0xFFFF;
ConstMethod
*
ConstMethod
::
allocate
(
ClassLoaderData
*
loader_data
,
int
byte_code_size
,
int
compressed_line_number_size
,
int
localvariable_table_length
,
int
exception_table_length
,
int
checked_exceptions_length
,
int
method_parameters_length
,
u2
generic_signature_index
,
InlineTableSizes
*
sizes
,
MethodType
method_type
,
TRAPS
)
{
int
size
=
ConstMethod
::
size
(
byte_code_size
,
compressed_line_number_size
,
localvariable_table_length
,
exception_table_length
,
checked_exceptions_length
,
method_parameters_length
,
generic_signature_index
);
int
size
=
ConstMethod
::
size
(
byte_code_size
,
sizes
);
return
new
(
loader_data
,
size
,
true
,
THREAD
)
ConstMethod
(
byte_code_size
,
compressed_line_number_size
,
localvariable_table_length
,
exception_table_length
,
checked_exceptions_length
,
method_parameters_length
,
generic_signature_index
,
method_type
,
size
);
byte_code_size
,
sizes
,
method_type
,
size
);
}
ConstMethod
::
ConstMethod
(
int
byte_code_size
,
int
compressed_line_number_size
,
int
localvariable_table_length
,
int
exception_table_length
,
int
checked_exceptions_length
,
int
method_parameters_length
,
u2
generic_signature_index
,
InlineTableSizes
*
sizes
,
MethodType
method_type
,
int
size
)
{
No_Safepoint_Verifier
no_safepoint
;
set_interpreter_kind
(
Interpreter
::
invalid
);
init_fingerprint
();
set_constants
(
NULL
);
set_stackmap_data
(
NULL
);
set_code_size
(
byte_code_size
);
set_constMethod_size
(
size
);
set_inlined_tables_length
(
generic_signature_index
,
checked_exceptions_length
,
compressed_line_number_size
,
localvariable_table_length
,
exception_table_length
,
method_parameters_length
);
set_inlined_tables_length
(
sizes
);
set_method_type
(
method_type
);
assert
(
this
->
size
()
==
size
,
"wrong size for object"
);
}
...
...
@@ -88,47 +63,70 @@ ConstMethod::ConstMethod(int byte_code_size,
// Deallocate metadata fields associated with ConstMethod*
void
ConstMethod
::
deallocate_contents
(
ClassLoaderData
*
loader_data
)
{
set_interpreter_kind
(
Interpreter
::
invalid
);
if
(
stackmap_data
()
!=
NULL
)
{
MetadataFactory
::
free_array
<
u1
>
(
loader_data
,
stackmap_data
());
}
set_stackmap_data
(
NULL
);
// deallocate annotation arrays
if
(
has_method_annotations
())
MetadataFactory
::
free_array
<
u1
>
(
loader_data
,
method_annotations
());
if
(
has_parameter_annotations
())
MetadataFactory
::
free_array
<
u1
>
(
loader_data
,
parameter_annotations
());
if
(
has_type_annotations
())
MetadataFactory
::
free_array
<
u1
>
(
loader_data
,
type_annotations
());
if
(
has_default_annotations
())
MetadataFactory
::
free_array
<
u1
>
(
loader_data
,
default_annotations
());
}
// How big must this constMethodObject be?
int
ConstMethod
::
size
(
int
code_size
,
int
compressed_line_number_size
,
int
local_variable_table_length
,
int
exception_table_length
,
int
checked_exceptions_length
,
int
method_parameters_length
,
u2
generic_signature_index
)
{
InlineTableSizes
*
sizes
)
{
int
extra_bytes
=
code_size
;
if
(
compressed_line_number_size
>
0
)
{
extra_bytes
+=
compressed_line_number_size
;
if
(
sizes
->
compressed_linenumber_size
()
>
0
)
{
extra_bytes
+=
sizes
->
compressed_linenumber_size
()
;
}
if
(
checked_exceptions_length
>
0
)
{
if
(
sizes
->
checked_exceptions_length
()
>
0
)
{
extra_bytes
+=
sizeof
(
u2
);
extra_bytes
+=
checked_exceptions_length
*
sizeof
(
CheckedExceptionElement
);
extra_bytes
+=
sizes
->
checked_exceptions_length
()
*
sizeof
(
CheckedExceptionElement
);
}
if
(
local_variable_table_length
>
0
)
{
if
(
sizes
->
localvariable_table_length
()
>
0
)
{
extra_bytes
+=
sizeof
(
u2
);
extra_bytes
+=
local_variable_table_length
*
sizeof
(
LocalVariableTableElement
);
sizes
->
localvariable_table_length
()
*
sizeof
(
LocalVariableTableElement
);
}
if
(
exception_table_length
>
0
)
{
if
(
sizes
->
exception_table_length
()
>
0
)
{
extra_bytes
+=
sizeof
(
u2
);
extra_bytes
+=
exception_table_length
*
sizeof
(
ExceptionTableElement
);
extra_bytes
+=
sizes
->
exception_table_length
()
*
sizeof
(
ExceptionTableElement
);
}
if
(
generic_signature_index
!=
0
)
{
if
(
sizes
->
generic_signature_index
()
!=
0
)
{
extra_bytes
+=
sizeof
(
u2
);
}
if
(
method_parameters_length
>
0
)
{
if
(
sizes
->
method_parameters_length
()
>
0
)
{
extra_bytes
+=
sizeof
(
u2
);
extra_bytes
+=
method_parameters_length
*
sizeof
(
MethodParametersElement
);
extra_bytes
+=
sizes
->
method_parameters_length
()
*
sizeof
(
MethodParametersElement
);
}
// Align sizes up to a word.
extra_bytes
=
align_size_up
(
extra_bytes
,
BytesPerWord
);
// One pointer per annotation array
if
(
sizes
->
method_annotations_length
()
>
0
)
{
extra_bytes
+=
sizeof
(
AnnotationArray
*
);
}
if
(
sizes
->
parameter_annotations_length
()
>
0
)
{
extra_bytes
+=
sizeof
(
AnnotationArray
*
);
}
if
(
sizes
->
type_annotations_length
()
>
0
)
{
extra_bytes
+=
sizeof
(
AnnotationArray
*
);
}
if
(
sizes
->
default_annotations_length
()
>
0
)
{
extra_bytes
+=
sizeof
(
AnnotationArray
*
);
}
int
extra_words
=
align_size_up
(
extra_bytes
,
BytesPerWord
)
/
BytesPerWord
;
assert
(
extra_words
==
extra_bytes
/
BytesPerWord
,
"should already be aligned"
);
return
align_object_size
(
header_size
()
+
extra_words
);
}
...
...
@@ -145,12 +143,28 @@ u_char* ConstMethod::compressed_linenumber_table() const {
return
code_end
();
}
// Last short in ConstMethod* before annotations
u2
*
ConstMethod
::
last_u2_element
()
const
{
int
offset
=
0
;
if
(
has_method_annotations
())
offset
++
;
if
(
has_parameter_annotations
())
offset
++
;
if
(
has_type_annotations
())
offset
++
;
if
(
has_default_annotations
())
offset
++
;
return
(
u2
*
)((
AnnotationArray
**
)
constMethod_end
()
-
offset
)
-
1
;
}
u2
*
ConstMethod
::
generic_signature_index_addr
()
const
{
// Located at the end of the constMethod.
assert
(
has_generic_signature
(),
"called only if generic signature exists"
);
return
last_u2_element
();
}
u2
*
ConstMethod
::
method_parameters_length_addr
()
const
{
assert
(
has_method_parameters
(),
"called only if table is present"
);
return
has_generic_signature
()
?
(
last_u2_element
()
-
1
)
:
last_u2_element
();
}
u2
*
ConstMethod
::
checked_exceptions_length_addr
()
const
{
// Located immediately before the generic signature index.
assert
(
has_checked_exceptions
(),
"called only if table is present"
);
...
...
@@ -164,12 +178,6 @@ u2* ConstMethod::checked_exceptions_length_addr() const {
}
}
u2
*
ConstMethod
::
method_parameters_length_addr
()
const
{
assert
(
has_method_parameters
(),
"called only if table is present"
);
return
has_generic_signature
()
?
(
last_u2_element
()
-
1
)
:
last_u2_element
();
}
u2
*
ConstMethod
::
exception_table_length_addr
()
const
{
assert
(
has_exception_handler
(),
"called only if table is present"
);
if
(
has_checked_exceptions
())
{
...
...
@@ -181,9 +189,9 @@ u2* ConstMethod::exception_table_length_addr() const {
return
(
u2
*
)
method_parameters_start
()
-
1
;
}
else
{
// Else, the exception table is at the end of the constMethod.
return
has_generic_signature
()
?
(
last_u2_element
()
-
1
)
:
last_u2_element
();
}
return
has_generic_signature
()
?
(
last_u2_element
()
-
1
)
:
last_u2_element
();
}
}
}
...
...
@@ -204,32 +212,38 @@ u2* ConstMethod::localvariable_table_length_addr() const {
// Else, the exception table is at the end of the constMethod.
return
has_generic_signature
()
?
(
last_u2_element
()
-
1
)
:
last_u2_element
();
}
}
}
}
}
// Update the flags to indicate the presence of these optional fields.
void
ConstMethod
::
set_inlined_tables_length
(
u2
generic_signature_index
,
int
checked_exceptions_len
,
int
compressed_line_number_size
,
int
localvariable_table_len
,
int
exception_table_len
,
int
method_parameters_len
)
{
assert
(
_flags
==
0
,
"Error"
);
if
(
compressed_line_number_size
>
0
)
void
ConstMethod
::
set_inlined_tables_length
(
InlineTableSizes
*
sizes
)
{
_flags
=
0
;
if
(
sizes
->
compressed_linenumber_size
()
>
0
)
_flags
|=
_has_linenumber_table
;
if
(
generic_signature_index
!=
0
)
if
(
sizes
->
generic_signature_index
()
!=
0
)
_flags
|=
_has_generic_signature
;
if
(
method_parameters_len
>
0
)
if
(
sizes
->
method_parameters_length
()
>
0
)
_flags
|=
_has_method_parameters
;
if
(
checked_exceptions_len
>
0
)
if
(
sizes
->
checked_exceptions_length
()
>
0
)
_flags
|=
_has_checked_exceptions
;
if
(
exception_table_len
>
0
)
if
(
sizes
->
exception_table_length
()
>
0
)
_flags
|=
_has_exception_table
;
if
(
localvariable_table_len
>
0
)
if
(
sizes
->
localvariable_table_length
()
>
0
)
_flags
|=
_has_localvariable_table
;
// annotations, they are all pointer sized embedded objects so don't have
// a length embedded also.
if
(
sizes
->
method_annotations_length
()
>
0
)
_flags
|=
_has_method_annotations
;
if
(
sizes
->
parameter_annotations_length
()
>
0
)
_flags
|=
_has_parameter_annotations
;
if
(
sizes
->
type_annotations_length
()
>
0
)
_flags
|=
_has_type_annotations
;
if
(
sizes
->
default_annotations_length
()
>
0
)
_flags
|=
_has_default_annotations
;
// This code is extremely brittle and should possibly be revised.
// The *_length_addr functions walk backwards through the
// constMethod data, using each of the length indexes ahead of them,
...
...
@@ -242,17 +256,17 @@ void ConstMethod::set_inlined_tables_length(u2 generic_signature_index,
// Also, the servicability agent needs to be informed anytime
// anything is added here. It might be advisable to have some sort
// of indication of this inline.
if
(
generic_signature_index
!=
0
)
*
(
generic_signature_index_addr
())
=
generic_signature_index
;
if
(
sizes
->
generic_signature_index
()
!=
0
)
*
(
generic_signature_index_addr
())
=
sizes
->
generic_signature_index
()
;
// New data should probably go here.
if
(
method_parameters_len
>
0
)
*
(
method_parameters_length_addr
())
=
method_parameters_len
;
if
(
checked_exceptions_len
>
0
)
*
(
checked_exceptions_length_addr
())
=
checked_exceptions_len
;
if
(
exception_table_len
>
0
)
*
(
exception_table_length_addr
())
=
exception_table_len
;
if
(
localvariable_table_len
>
0
)
*
(
localvariable_table_length_addr
())
=
localvariable_table_len
;
if
(
sizes
->
method_parameters_length
()
>
0
)
*
(
method_parameters_length_addr
())
=
sizes
->
method_parameters_length
()
;
if
(
sizes
->
checked_exceptions_length
()
>
0
)
*
(
checked_exceptions_length_addr
())
=
sizes
->
checked_exceptions_length
()
;
if
(
sizes
->
exception_table_length
()
>
0
)
*
(
exception_table_length_addr
())
=
sizes
->
exception_table_length
()
;
if
(
sizes
->
localvariable_table_length
()
>
0
)
*
(
localvariable_table_length_addr
())
=
sizes
->
localvariable_table_length
()
;
}
int
ConstMethod
::
method_parameters_length
()
const
{
...
...
@@ -307,6 +321,34 @@ ExceptionTableElement* ConstMethod::exception_table_start() const {
return
(
ExceptionTableElement
*
)
addr
;
}
AnnotationArray
**
ConstMethod
::
method_annotations_addr
()
const
{
assert
(
has_method_annotations
(),
"should only be called if method annotations are present"
);
return
(
AnnotationArray
**
)
constMethod_end
()
-
1
;
}
AnnotationArray
**
ConstMethod
::
parameter_annotations_addr
()
const
{
assert
(
has_parameter_annotations
(),
"should only be called if method parameter annotations are present"
);
int
offset
=
1
;
if
(
has_method_annotations
())
offset
++
;
return
(
AnnotationArray
**
)
constMethod_end
()
-
offset
;
}
AnnotationArray
**
ConstMethod
::
type_annotations_addr
()
const
{
assert
(
has_type_annotations
(),
"should only be called if method type annotations are present"
);
int
offset
=
1
;
if
(
has_method_annotations
())
offset
++
;
if
(
has_parameter_annotations
())
offset
++
;
return
(
AnnotationArray
**
)
constMethod_end
()
-
offset
;
}
AnnotationArray
**
ConstMethod
::
default_annotations_addr
()
const
{
assert
(
has_default_annotations
(),
"should only be called if method default annotations are present"
);
int
offset
=
1
;
if
(
has_method_annotations
())
offset
++
;
if
(
has_parameter_annotations
())
offset
++
;
if
(
has_type_annotations
())
offset
++
;
return
(
AnnotationArray
**
)
constMethod_end
()
-
offset
;
}
// Printing
...
...
@@ -339,8 +381,25 @@ void ConstMethod::collect_statistics(KlassSizeStats *sz) const {
sz
->
_bytecode_bytes
+=
(
n2
=
code_size
());
sz
->
_stackmap_bytes
+=
(
n3
=
sz
->
count_array
(
stackmap_data
()));
sz
->
_method_all_bytes
+=
n1
+
n3
;
// note: n2 is part of n3
sz
->
_ro_bytes
+=
n1
+
n3
;
// Count method annotations
int
a1
=
0
,
a2
=
0
,
a3
=
0
,
a4
=
0
;
if
(
has_method_annotations
())
{
sz
->
_methods_annotations_bytes
+=
(
a1
=
sz
->
count_array
(
method_annotations
()));
}
if
(
has_parameter_annotations
())
{
sz
->
_methods_parameter_annotations_bytes
+=
(
a2
=
sz
->
count_array
(
parameter_annotations
()));
}
if
(
has_type_annotations
())
{
sz
->
_methods_type_annotations_bytes
+=
(
a3
=
sz
->
count_array
(
type_annotations
()));
}
if
(
has_default_annotations
())
{
sz
->
_methods_default_annotations_bytes
+=
(
a4
=
sz
->
count_array
(
default_annotations
()));
}
int
size_annotations
=
a1
+
a2
+
a3
+
a4
;
sz
->
_method_all_bytes
+=
n1
+
n3
+
size_annotations
;
// note: n2 is part of n3
sz
->
_ro_bytes
+=
n1
+
n3
+
size_annotations
;
}
#endif // INCLUDE_SERVICES
...
...
@@ -352,10 +411,9 @@ void ConstMethod::verify_on(outputStream* st) {
// Verification can occur during oop construction before the method or
// other fields have been initialized.
guarantee
(
is_metadata
(),
err_msg
(
"Should be metadata "
PTR_FORMAT
,
this
));
guarantee
(
method
()
->
is_method
(),
"should be method"
);
address
m_end
=
(
address
)((
oop
*
)
this
+
size
());
address
m_end
=
(
address
)((
intptr_t
)
this
+
size
());
address
compressed_table_start
=
code_end
();
guarantee
(
compressed_table_start
<=
m_end
,
"invalid method layout"
);
address
compressed_table_end
=
compressed_table_start
;
...
...
src/share/vm/oops/constMethod.hpp
浏览文件 @
4b2183fb
...
...
@@ -86,19 +86,22 @@
// | generic signature index (u2) |
// | (indexed from start of constMethodOop) |
// |------------------------------------------------------|
// | annotations arrays - method, parameter, type, default|
// | pointer to Array<u1> if annotation is present |
// |------------------------------------------------------|
//
// IMPORTANT: If anything gets added here, there need to be changes to
// ensure that ServicabilityAgent doesn't get broken as a result!
// Uti
tily class de
cribing elements in checked exceptions table inlined in Method*.
// Uti
lity class des
cribing elements in checked exceptions table inlined in Method*.
class
CheckedExceptionElement
VALUE_OBJ_CLASS_SPEC
{
public:
u2
class_cp_index
;
};
// Uti
tily class de
cribing elements in local variable table inlined in Method*.
// Uti
lity class des
cribing elements in local variable table inlined in Method*.
class
LocalVariableTableElement
VALUE_OBJ_CLASS_SPEC
{
public:
u2
start_bci
;
...
...
@@ -109,7 +112,7 @@ class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
u2
slot
;
};
// Uti
til
y class describing elements in exception table
// Uti
lit
y class describing elements in exception table
class
ExceptionTableElement
VALUE_OBJ_CLASS_SPEC
{
public:
u2
start_pc
;
...
...
@@ -127,6 +130,51 @@ class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
class
KlassSizeStats
;
// Class to collect the sizes of ConstMethod inline tables
#define INLINE_TABLES_DO(do_element) \
do_element(localvariable_table_length) \
do_element(compressed_linenumber_size) \
do_element(exception_table_length) \
do_element(checked_exceptions_length) \
do_element(method_parameters_length) \
do_element(generic_signature_index) \
do_element(method_annotations_length) \
do_element(parameter_annotations_length) \
do_element(type_annotations_length) \
do_element(default_annotations_length)
#define INLINE_TABLE_DECLARE(sym) int _##sym;
#define INLINE_TABLE_PARAM(sym) int sym,
#define INLINE_TABLE_INIT(sym) _##sym(sym),
#define INLINE_TABLE_NULL(sym) _##sym(0),
#define INLINE_TABLE_ACCESSOR(sym) int sym() const { return _##sym; }
class
InlineTableSizes
:
StackObj
{
// declarations
INLINE_TABLES_DO
(
INLINE_TABLE_DECLARE
)
int
_end
;
public:
InlineTableSizes
(
INLINE_TABLES_DO
(
INLINE_TABLE_PARAM
)
int
end
)
:
INLINE_TABLES_DO
(
INLINE_TABLE_INIT
)
_end
(
end
)
{}
// Default constructor for no inlined tables
InlineTableSizes
()
:
INLINE_TABLES_DO
(
INLINE_TABLE_NULL
)
_end
(
0
)
{}
// Accessors
INLINE_TABLES_DO
(
INLINE_TABLE_ACCESSOR
)
};
#undef INLINE_TABLE_ACCESSOR
#undef INLINE_TABLE_NULL
#undef INLINE_TABLE_INIT
#undef INLINE_TABLE_PARAM
#undef INLINE_TABLE_DECLARE
class
ConstMethod
:
public
MetaspaceObj
{
friend
class
VMStructs
;
...
...
@@ -135,13 +183,17 @@ public:
private:
enum
{
_has_linenumber_table
=
1
,
_has_checked_exceptions
=
2
,
_has_localvariable_table
=
4
,
_has_exception_table
=
8
,
_has_generic_signature
=
16
,
_has_method_parameters
=
32
,
_is_overpass
=
64
_has_linenumber_table
=
0x0001
,
_has_checked_exceptions
=
0x0002
,
_has_localvariable_table
=
0x0004
,
_has_exception_table
=
0x0008
,
_has_generic_signature
=
0x0010
,
_has_method_parameters
=
0x0020
,
_is_overpass
=
0x0040
,
_has_method_annotations
=
0x0080
,
_has_parameter_annotations
=
0x0100
,
_has_type_annotations
=
0x0200
,
_has_default_annotations
=
0x0400
};
// Bit vector of signature
...
...
@@ -158,8 +210,7 @@ private:
Array
<
u1
>*
_stackmap_data
;
int
_constMethod_size
;
jbyte
_interpreter_kind
;
jbyte
_flags
;
u2
_flags
;
// Size of Java bytecodes allocated immediately after Method*.
u2
_code_size
;
...
...
@@ -174,36 +225,21 @@ private:
// Constructor
ConstMethod
(
int
byte_code_size
,
int
compressed_line_number_size
,
int
localvariable_table_length
,
int
exception_table_length
,
int
checked_exceptions_length
,
int
method_parameters_length
,
u2
generic_signature_index
,
InlineTableSizes
*
sizes
,
MethodType
is_overpass
,
int
size
);
public:
static
ConstMethod
*
allocate
(
ClassLoaderData
*
loader_data
,
int
byte_code_size
,
int
compressed_line_number_size
,
int
localvariable_table_length
,
int
exception_table_length
,
int
checked_exceptions_length
,
int
method_parameters_length
,
u2
generic_signature_index
,
InlineTableSizes
*
sizes
,
MethodType
mt
,
TRAPS
);
bool
is_constMethod
()
const
{
return
true
;
}
// Inlined tables
void
set_inlined_tables_length
(
u2
generic_signature_index
,
int
checked_exceptions_len
,
int
compressed_line_number_size
,
int
localvariable_table_len
,
int
exception_table_len
,
int
method_parameters_length
);
void
set_inlined_tables_length
(
InlineTableSizes
*
sizes
);
bool
has_generic_signature
()
const
{
return
(
_flags
&
_has_generic_signature
)
!=
0
;
}
...
...
@@ -235,10 +271,6 @@ public:
}
}
void
set_interpreter_kind
(
int
kind
)
{
_interpreter_kind
=
kind
;
}
int
interpreter_kind
(
void
)
const
{
return
_interpreter_kind
;
}
// constant pool
ConstantPool
*
constants
()
const
{
return
_constants
;
}
void
set_constants
(
ConstantPool
*
c
)
{
_constants
=
c
;
}
...
...
@@ -307,12 +339,7 @@ public:
}
// Size needed
static
int
size
(
int
code_size
,
int
compressed_line_number_size
,
int
local_variable_table_length
,
int
exception_table_length
,
int
checked_exceptions_length
,
int
method_parameters_length
,
u2
generic_signature_index
);
static
int
size
(
int
code_size
,
InlineTableSizes
*
sizes
);
int
size
()
const
{
return
_constMethod_size
;}
void
set_constMethod_size
(
int
size
)
{
_constMethod_size
=
size
;
}
...
...
@@ -354,6 +381,65 @@ public:
int
method_parameters_length
()
const
;
MethodParametersElement
*
method_parameters_start
()
const
;
// method annotations
bool
has_method_annotations
()
const
{
return
(
_flags
&
_has_method_annotations
)
!=
0
;
}
bool
has_parameter_annotations
()
const
{
return
(
_flags
&
_has_parameter_annotations
)
!=
0
;
}
bool
has_type_annotations
()
const
{
return
(
_flags
&
_has_type_annotations
)
!=
0
;
}
bool
has_default_annotations
()
const
{
return
(
_flags
&
_has_default_annotations
)
!=
0
;
}
AnnotationArray
**
method_annotations_addr
()
const
;
AnnotationArray
*
method_annotations
()
const
{
return
has_method_annotations
()
?
*
(
method_annotations_addr
())
:
NULL
;
}
void
set_method_annotations
(
AnnotationArray
*
anno
)
{
*
(
method_annotations_addr
())
=
anno
;
}
AnnotationArray
**
parameter_annotations_addr
()
const
;
AnnotationArray
*
parameter_annotations
()
const
{
return
has_parameter_annotations
()
?
*
(
parameter_annotations_addr
())
:
NULL
;
}
void
set_parameter_annotations
(
AnnotationArray
*
anno
)
{
*
(
parameter_annotations_addr
())
=
anno
;
}
AnnotationArray
**
type_annotations_addr
()
const
;
AnnotationArray
*
type_annotations
()
const
{
return
has_type_annotations
()
?
*
(
type_annotations_addr
())
:
NULL
;
}
void
set_type_annotations
(
AnnotationArray
*
anno
)
{
*
(
type_annotations_addr
())
=
anno
;
}
AnnotationArray
**
default_annotations_addr
()
const
;
AnnotationArray
*
default_annotations
()
const
{
return
has_default_annotations
()
?
*
(
default_annotations_addr
())
:
NULL
;
}
void
set_default_annotations
(
AnnotationArray
*
anno
)
{
*
(
default_annotations_addr
())
=
anno
;
}
int
method_annotations_length
()
const
{
return
has_method_annotations
()
?
method_annotations
()
->
length
()
:
0
;
}
int
parameter_annotations_length
()
const
{
return
has_parameter_annotations
()
?
parameter_annotations
()
->
length
()
:
0
;
}
int
type_annotations_length
()
const
{
return
has_type_annotations
()
?
type_annotations
()
->
length
()
:
0
;
}
int
default_annotations_length
()
const
{
return
has_default_annotations
()
?
default_annotations
()
->
length
()
:
0
;
}
// byte codes
void
set_code
(
address
code
)
{
if
(
code_size
()
>
0
)
{
...
...
@@ -409,11 +495,10 @@ private:
// First byte after ConstMethod*
address
constMethod_end
()
const
{
return
(
address
)((
oop
*
)
this
+
_constMethod_size
);
}
{
return
(
address
)((
intptr_t
*
)
this
+
_constMethod_size
);
}
// Last short in ConstMethod*
u2
*
last_u2_element
()
const
{
return
(
u2
*
)
constMethod_end
()
-
1
;
}
u2
*
last_u2_element
()
const
;
public:
// Printing
...
...
src/share/vm/oops/cpCache.cpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 1998, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 201
3
, 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
...
...
@@ -402,8 +402,9 @@ oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) {
}
#if INCLUDE_JVMTI
// RedefineClasses() API support:
// If this
c
onstantPoolCacheEntry refers to old_method then update it
// If this
C
onstantPoolCacheEntry refers to old_method then update it
// to refer to new_method.
bool
ConstantPoolCacheEntry
::
adjust_method_entry
(
Method
*
old_method
,
Method
*
new_method
,
bool
*
trace_name_printed
)
{
...
...
@@ -461,16 +462,24 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
return
false
;
}
#ifndef PRODUCT
bool
ConstantPoolCacheEntry
::
check_no_old_entries
()
{
// a constant pool cache entry should never contain old or obsolete methods
bool
ConstantPoolCacheEntry
::
check_no_old_
or_obsolete_
entries
()
{
if
(
is_vfinal
())
{
// virtual and final so _f2 contains method ptr instead of vtable index
Metadata
*
f2
=
(
Metadata
*
)
_f2
;
return
(
f2
->
is_valid
()
&&
f2
->
is_method
()
&&
!
((
Method
*
)
f2
)
->
is_old
());
}
else
{
return
(
_f1
==
NULL
||
(
_f1
->
is_valid
()
&&
_f1
->
is_method
()
&&
!
((
Method
*
)
_f1
)
->
is_old
()));
// Return false if _f2 refers to an old or an obsolete method.
// _f2 == NULL || !_f2->is_method() are just as unexpected here.
return
(
f2
!=
NULL
NOT_PRODUCT
(
&&
f2
->
is_valid
())
&&
f2
->
is_method
()
&&
!
((
Method
*
)
f2
)
->
is_old
()
&&
!
((
Method
*
)
f2
)
->
is_obsolete
());
}
else
if
(
_f1
==
NULL
||
(
NOT_PRODUCT
(
_f1
->
is_valid
()
&&
)
!
_f1
->
is_method
()))
{
// _f1 == NULL || !_f1->is_method() are OK here
return
true
;
}
// return false if _f1 refers to an old or an obsolete method
return
(
NOT_PRODUCT
(
_f1
->
is_valid
()
&&
)
_f1
->
is_method
()
&&
!
((
Method
*
)
_f1
)
->
is_old
()
&&
!
((
Method
*
)
_f1
)
->
is_obsolete
());
}
#endif
bool
ConstantPoolCacheEntry
::
is_interesting_method_entry
(
Klass
*
k
)
{
if
(
!
is_method_entry
())
{
...
...
@@ -503,13 +512,15 @@ bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
// the method is in the interesting class so the entry is interesting
return
true
;
}
#endif // INCLUDE_JVMTI
void
ConstantPoolCacheEntry
::
print
(
outputStream
*
st
,
int
index
)
const
{
// print separator
if
(
index
==
0
)
st
->
print_cr
(
" -------------"
);
// print entry
st
->
print
(
"%3d ("
PTR_FORMAT
") "
,
index
,
(
intptr_t
)
this
);
st
->
print_cr
(
"[%02x|%02x|%5d]"
,
bytecode_2
(),
bytecode_1
(),
constant_pool_index
());
st
->
print_cr
(
"[%02x|%02x|%5d]"
,
bytecode_2
(),
bytecode_1
(),
constant_pool_index
());
st
->
print_cr
(
" [ "
PTR_FORMAT
"]"
,
(
intptr_t
)
_f1
);
st
->
print_cr
(
" [ "
PTR_FORMAT
"]"
,
(
intptr_t
)
_f2
);
st
->
print_cr
(
" [ "
PTR_FORMAT
"]"
,
(
intptr_t
)
_flags
);
...
...
@@ -553,8 +564,9 @@ void ConstantPoolCache::initialize(intArray& inverse_index_map, intArray& invoke
}
}
#if INCLUDE_JVMTI
// RedefineClasses() API support:
// If any entry of this
c
onstantPoolCache points to any of
// If any entry of this
C
onstantPoolCache points to any of
// old_methods, replace it with the corresponding new_method.
void
ConstantPoolCache
::
adjust_method_entries
(
Method
**
old_methods
,
Method
**
new_methods
,
int
methods_length
,
bool
*
trace_name_printed
)
{
...
...
@@ -573,7 +585,7 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new
continue
;
}
// The
c
onstantPoolCache contains entries for several different
// The
C
onstantPoolCache contains entries for several different
// things, but we only care about methods. In fact, we only care
// about methods in the same class as the one that contains the
// old_methods. At this point, we have an interesting entry.
...
...
@@ -592,17 +604,25 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new
}
}
#ifndef PRODUCT
bool
ConstantPoolCache
::
check_no_old_entries
()
{
// the constant pool cache should never contain old or obsolete methods
bool
ConstantPoolCache
::
check_no_old_
or_obsolete_
entries
()
{
for
(
int
i
=
1
;
i
<
length
();
i
++
)
{
if
(
entry_at
(
i
)
->
is_interesting_method_entry
(
NULL
)
&&
!
entry_at
(
i
)
->
check_no_old
_entries
())
{
!
entry_at
(
i
)
->
check_no_old_or_obsolete
_entries
())
{
return
false
;
}
}
return
true
;
}
#endif // PRODUCT
void
ConstantPoolCache
::
dump_cache
()
{
for
(
int
i
=
1
;
i
<
length
();
i
++
)
{
if
(
entry_at
(
i
)
->
is_interesting_method_entry
(
NULL
))
{
entry_at
(
i
)
->
print
(
tty
,
i
);
}
}
}
#endif // INCLUDE_JVMTI
// Printing
...
...
src/share/vm/oops/cpCache.hpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 1998, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 201
3
, 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
...
...
@@ -337,16 +337,18 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
static
ByteSize
f2_offset
()
{
return
byte_offset_of
(
ConstantPoolCacheEntry
,
_f2
);
}
static
ByteSize
flags_offset
()
{
return
byte_offset_of
(
ConstantPoolCacheEntry
,
_flags
);
}
#if INCLUDE_JVMTI
// RedefineClasses() API support:
// If this
c
onstantPoolCacheEntry refers to old_method then update it
// If this
C
onstantPoolCacheEntry refers to old_method then update it
// to refer to new_method.
// trace_name_printed is set to true if the current call has
// printed the klass name so that other routines in the adjust_*
// group don't print the klass name.
bool
adjust_method_entry
(
Method
*
old_method
,
Method
*
new_method
,
bool
*
trace_name_printed
);
NOT_PRODUCT
(
bool
check_no_old_entries
();)
bool
check_no_old_or_obsolete_entries
();
bool
is_interesting_method_entry
(
Klass
*
k
);
#endif // INCLUDE_JVMTI
// Debugging & Printing
void
print
(
outputStream
*
st
,
int
index
)
const
;
...
...
@@ -423,15 +425,18 @@ class ConstantPoolCache: public MetaspaceObj {
return
(
base_offset
()
+
ConstantPoolCacheEntry
::
size_in_bytes
()
*
index
);
}
#if INCLUDE_JVMTI
// RedefineClasses() API support:
// If any entry of this
c
onstantPoolCache points to any of
// If any entry of this
C
onstantPoolCache points to any of
// old_methods, replace it with the corresponding new_method.
// trace_name_printed is set to true if the current call has
// printed the klass name so that other routines in the adjust_*
// group don't print the klass name.
void
adjust_method_entries
(
Method
**
old_methods
,
Method
**
new_methods
,
int
methods_length
,
bool
*
trace_name_printed
);
NOT_PRODUCT
(
bool
check_no_old_entries
();)
bool
check_no_old_or_obsolete_entries
();
void
dump_cache
();
#endif // INCLUDE_JVMTI
// Deallocate - no fields to deallocate
DEBUG_ONLY
(
bool
on_stack
()
{
return
false
;
})
...
...
src/share/vm/oops/instanceKlass.cpp
浏览文件 @
4b2183fb
...
...
@@ -166,20 +166,19 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
volatile
int
InstanceKlass
::
_total_instanceKlass_count
=
0
;
Klass
*
InstanceKlass
::
allocate_instance_klass
(
ClassLoaderData
*
loader_data
,
int
vtable_len
,
int
itable_len
,
int
static_field_size
,
int
nonstatic_oop_map_size
,
ReferenceType
rt
,
AccessFlags
access_flags
,
Symbol
*
name
,
int
vtable_len
,
int
itable_len
,
int
static_field_size
,
int
nonstatic_oop_map_size
,
ReferenceType
rt
,
AccessFlags
access_flags
,
Symbol
*
name
,
Klass
*
super_klass
,
KlassHandle
host_klas
s
,
TRAPS
)
{
bool
is_anonymou
s
,
TRAPS
)
{
int
size
=
InstanceKlass
::
size
(
vtable_len
,
itable_len
,
nonstatic_oop_map_size
,
access_flags
.
is_interface
(),
!
host_klass
.
is_null
());
access_flags
.
is_interface
(),
is_anonymous
);
// Allocation
InstanceKlass
*
ik
;
...
...
@@ -187,25 +186,25 @@ Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
if
(
name
==
vmSymbols
::
java_lang_Class
())
{
ik
=
new
(
loader_data
,
size
,
THREAD
)
InstanceMirrorKlass
(
vtable_len
,
itable_len
,
static_field_size
,
nonstatic_oop_map_size
,
rt
,
access_flags
,
!
host_klass
.
is_null
()
);
access_flags
,
is_anonymous
);
}
else
if
(
name
==
vmSymbols
::
java_lang_ClassLoader
()
||
(
SystemDictionary
::
ClassLoader_klass_loaded
()
&&
super_klass
!=
NULL
&&
super_klass
->
is_subtype_of
(
SystemDictionary
::
ClassLoader_klass
())))
{
ik
=
new
(
loader_data
,
size
,
THREAD
)
InstanceClassLoaderKlass
(
vtable_len
,
itable_len
,
static_field_size
,
nonstatic_oop_map_size
,
rt
,
access_flags
,
!
host_klass
.
is_null
()
);
access_flags
,
is_anonymous
);
}
else
{
// normal class
ik
=
new
(
loader_data
,
size
,
THREAD
)
InstanceKlass
(
vtable_len
,
itable_len
,
static_field_size
,
nonstatic_oop_map_size
,
rt
,
access_flags
,
!
host_klass
.
is_null
()
);
access_flags
,
is_anonymous
);
}
}
else
{
// reference klass
ik
=
new
(
loader_data
,
size
,
THREAD
)
InstanceRefKlass
(
vtable_len
,
itable_len
,
static_field_size
,
nonstatic_oop_map_size
,
rt
,
access_flags
,
!
host_klass
.
is_null
()
);
access_flags
,
is_anonymous
);
}
Atomic
::
inc
(
&
_total_instanceKlass_count
);
...
...
@@ -2793,7 +2792,10 @@ void InstanceKlass::print_on(outputStream* st) const {
st
->
print
(
"%s"
,
source_debug_extension
());
st
->
cr
();
}
st
->
print
(
BULLET
"annotations: "
);
annotations
()
->
print_value_on
(
st
);
st
->
cr
();
st
->
print
(
BULLET
"class annotations: "
);
class_annotations
()
->
print_value_on
(
st
);
st
->
cr
();
st
->
print
(
BULLET
"class type annotations: "
);
class_type_annotations
()
->
print_value_on
(
st
);
st
->
cr
();
st
->
print
(
BULLET
"field annotations: "
);
fields_annotations
()
->
print_value_on
(
st
);
st
->
cr
();
st
->
print
(
BULLET
"field type annotations: "
);
fields_type_annotations
()
->
print_value_on
(
st
);
st
->
cr
();
{
ResourceMark
rm
;
// PreviousVersionInfo objects returned via PreviousVersionWalker
...
...
src/share/vm/oops/instanceKlass.hpp
浏览文件 @
4b2183fb
...
...
@@ -155,8 +155,8 @@ class InstanceKlass: public Klass {
ReferenceType
rt
,
AccessFlags
access_flags
,
Symbol
*
name
,
Klass
*
super_klass
,
KlassHandle
host_klas
s
,
Klass
*
super_klass
,
bool
is_anonymou
s
,
TRAPS
);
InstanceKlass
()
{
assert
(
DumpSharedSpaces
||
UseSharedSpaces
,
"only for CDS"
);
}
...
...
@@ -679,19 +679,19 @@ class InstanceKlass: public Klass {
// annotations support
Annotations
*
annotations
()
const
{
return
_annotations
;
}
void
set_annotations
(
Annotations
*
anno
)
{
_annotations
=
anno
;
}
AnnotationArray
*
class_annotations
()
const
{
if
(
annotations
()
==
NULL
)
return
NULL
;
return
annotations
()
->
class_annotations
();
return
(
_annotations
!=
NULL
)
?
_annotations
->
class_annotations
()
:
NULL
;
}
Array
<
AnnotationArray
*>*
fields_annotations
()
const
{
if
(
annotations
()
==
NULL
)
return
NULL
;
return
annotations
()
->
fields_annotations
();
return
(
_annotations
!=
NULL
)
?
_annotations
->
fields_annotations
()
:
NULL
;
}
Annotations
*
type_annotations
()
const
{
if
(
annotations
()
==
NULL
)
return
NULL
;
return
annotations
()
->
type_annotations
();
AnnotationArray
*
class_type_annotations
()
const
{
return
(
_annotations
!=
NULL
)
?
_annotations
->
class_type_annotations
()
:
NULL
;
}
Array
<
AnnotationArray
*>*
fields_type_annotations
()
const
{
return
(
_annotations
!=
NULL
)
?
_annotations
->
fields_type_annotations
()
:
NULL
;
}
// allocation
instanceOop
allocate_instance
(
TRAPS
);
...
...
@@ -810,6 +810,7 @@ class InstanceKlass: public Klass {
// Sizing (in words)
static
int
header_size
()
{
return
align_object_offset
(
sizeof
(
InstanceKlass
)
/
HeapWordSize
);
}
static
int
size
(
int
vtable_length
,
int
itable_length
,
int
nonstatic_oop_map_size
,
bool
is_interface
,
bool
is_anonymous
)
{
...
...
@@ -847,10 +848,14 @@ class InstanceKlass: public Klass {
return
(
OopMapBlock
*
)(
start_of_itable
()
+
align_object_offset
(
itable_length
()));
}
Klass
**
end_of_nonstatic_oop_maps
()
const
{
return
(
Klass
**
)(
start_of_nonstatic_oop_maps
()
+
nonstatic_oop_map_count
());
}
Klass
**
adr_implementor
()
const
{
if
(
is_interface
())
{
return
(
Klass
**
)(
start_of_nonstatic_oop_maps
()
+
nonstatic_oop_map_count
());
return
(
Klass
**
)
end_of_nonstatic_oop_maps
();
}
else
{
return
NULL
;
}
...
...
@@ -862,8 +867,7 @@ class InstanceKlass: public Klass {
if
(
adr_impl
!=
NULL
)
{
return
adr_impl
+
1
;
}
else
{
return
(
Klass
**
)(
start_of_nonstatic_oop_maps
()
+
nonstatic_oop_map_count
());
return
end_of_nonstatic_oop_maps
();
}
}
else
{
return
NULL
;
...
...
src/share/vm/oops/klassVtable.cpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 1997, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
3
, 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
...
...
@@ -610,6 +610,7 @@ void klassVtable::copy_vtable_to(vtableEntry* start) {
Copy
::
disjoint_words
((
HeapWord
*
)
table
(),
(
HeapWord
*
)
start
,
_length
*
vtableEntry
::
size
());
}
#if INCLUDE_JVMTI
void
klassVtable
::
adjust_method_entries
(
Method
**
old_methods
,
Method
**
new_methods
,
int
methods_length
,
bool
*
trace_name_printed
)
{
// search the vtable for uses of either obsolete or EMCP methods
...
...
@@ -638,11 +639,39 @@ void klassVtable::adjust_method_entries(Method** old_methods, Method** new_metho
new_method
->
name
()
->
as_C_string
(),
new_method
->
signature
()
->
as_C_string
()));
}
// cannot 'break' here; see for-loop comment above.
}
}
}
}
// a vtable should never contain old or obsolete methods
bool
klassVtable
::
check_no_old_or_obsolete_entries
()
{
for
(
int
i
=
0
;
i
<
length
();
i
++
)
{
Method
*
m
=
unchecked_method_at
(
i
);
if
(
m
!=
NULL
&&
(
NOT_PRODUCT
(
!
m
->
is_valid
()
||
)
m
->
is_old
()
||
m
->
is_obsolete
()))
{
return
false
;
}
}
return
true
;
}
void
klassVtable
::
dump_vtable
()
{
tty
->
print_cr
(
"vtable dump --"
);
for
(
int
i
=
0
;
i
<
length
();
i
++
)
{
Method
*
m
=
unchecked_method_at
(
i
);
if
(
m
!=
NULL
)
{
tty
->
print
(
" (%5d) "
,
i
);
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
}
}
#endif // INCLUDE_JVMTI
// CDS/RedefineClasses support - clear vtables so they can be reinitialized
void
klassVtable
::
clear_vtable
()
{
for
(
int
i
=
0
;
i
<
_length
;
i
++
)
table
()[
i
].
clear
();
...
...
@@ -805,6 +834,7 @@ void klassItable::initialize_with_method(Method* m) {
}
}
#if INCLUDE_JVMTI
void
klassItable
::
adjust_method_entries
(
Method
**
old_methods
,
Method
**
new_methods
,
int
methods_length
,
bool
*
trace_name_printed
)
{
// search the itable for uses of either obsolete or EMCP methods
...
...
@@ -833,13 +863,44 @@ void klassItable::adjust_method_entries(Method** old_methods, Method** new_metho
new_method
->
name
()
->
as_C_string
(),
new_method
->
signature
()
->
as_C_string
()));
}
//
Cannot break because there might be another entry for this method
//
cannot 'break' here; see for-loop comment above.
}
ime
++
;
}
}
}
// an itable should never contain old or obsolete methods
bool
klassItable
::
check_no_old_or_obsolete_entries
()
{
itableMethodEntry
*
ime
=
method_entry
(
0
);
for
(
int
i
=
0
;
i
<
_size_method_table
;
i
++
)
{
Method
*
m
=
ime
->
method
();
if
(
m
!=
NULL
&&
(
NOT_PRODUCT
(
!
m
->
is_valid
()
||
)
m
->
is_old
()
||
m
->
is_obsolete
()))
{
return
false
;
}
ime
++
;
}
return
true
;
}
void
klassItable
::
dump_itable
()
{
itableMethodEntry
*
ime
=
method_entry
(
0
);
tty
->
print_cr
(
"itable dump --"
);
for
(
int
i
=
0
;
i
<
_size_method_table
;
i
++
)
{
Method
*
m
=
ime
->
method
();
if
(
m
!=
NULL
)
{
tty
->
print
(
" (%5d) "
,
i
);
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
ime
++
;
}
}
#endif // INCLUDE_JVMTI
// Setup
class
InterfaceVisiterClosure
:
public
StackObj
{
...
...
@@ -1126,43 +1187,6 @@ void klassVtable::print_statistics() {
tty
->
print_cr
(
"%6d bytes total"
,
total
);
}
bool
klassVtable
::
check_no_old_entries
()
{
// Check that there really is no entry
for
(
int
i
=
0
;
i
<
length
();
i
++
)
{
Method
*
m
=
unchecked_method_at
(
i
);
if
(
m
!=
NULL
)
{
if
(
!
m
->
is_valid
()
||
m
->
is_old
())
{
return
false
;
}
}
}
return
true
;
}
void
klassVtable
::
dump_vtable
()
{
tty
->
print_cr
(
"vtable dump --"
);
for
(
int
i
=
0
;
i
<
length
();
i
++
)
{
Method
*
m
=
unchecked_method_at
(
i
);
if
(
m
!=
NULL
)
{
tty
->
print
(
" (%5d) "
,
i
);
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
}
}
bool
klassItable
::
check_no_old_entries
()
{
itableMethodEntry
*
ime
=
method_entry
(
0
);
for
(
int
i
=
0
;
i
<
_size_method_table
;
i
++
)
{
Method
*
m
=
ime
->
method
();
if
(
m
!=
NULL
&&
(
!
m
->
is_valid
()
||
m
->
is_old
()))
return
false
;
ime
++
;
}
return
true
;
}
int
klassItable
::
_total_classes
;
// Total no. of classes with itables
long
klassItable
::
_total_size
;
// Total no. of bytes used for itables
...
...
src/share/vm/oops/klassVtable.hpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 1997, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
3
, 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
...
...
@@ -90,6 +90,7 @@ class klassVtable : public ResourceObj {
Array
<
Method
*>*
methods
,
AccessFlags
class_flags
,
Handle
classloader
,
Symbol
*
classname
,
Array
<
Klass
*>*
local_interfaces
,
TRAPS
);
#if INCLUDE_JVMTI
// RedefineClasses() API support:
// If any entry of this vtable points to any of old_methods,
// replace it with the corresponding new_method.
...
...
@@ -98,17 +99,15 @@ class klassVtable : public ResourceObj {
// group don't print the klass name.
void
adjust_method_entries
(
Method
**
old_methods
,
Method
**
new_methods
,
int
methods_length
,
bool
*
trace_name_printed
);
bool
check_no_old_or_obsolete_entries
();
void
dump_vtable
();
#endif // INCLUDE_JVMTI
// Debugging code
void
print
()
PRODUCT_RETURN
;
void
verify
(
outputStream
*
st
,
bool
force
=
false
);
static
void
print_statistics
()
PRODUCT_RETURN
;
#ifndef PRODUCT
bool
check_no_old_entries
();
void
dump_vtable
();
#endif
protected:
friend
class
vtableEntry
;
private:
...
...
@@ -275,6 +274,7 @@ class klassItable : public ResourceObj {
// Updates
void
initialize_with_method
(
Method
*
m
);
#if INCLUDE_JVMTI
// RedefineClasses() API support:
// if any entry of this itable points to any of old_methods,
// replace it with the corresponding new_method.
...
...
@@ -283,6 +283,9 @@ class klassItable : public ResourceObj {
// group don't print the klass name.
void
adjust_method_entries
(
Method
**
old_methods
,
Method
**
new_methods
,
int
methods_length
,
bool
*
trace_name_printed
);
bool
check_no_old_or_obsolete_entries
();
void
dump_itable
();
#endif // INCLUDE_JVMTI
// Setup of itable
static
int
compute_itable_size
(
Array
<
Klass
*>*
transitive_interfaces
);
...
...
@@ -307,11 +310,6 @@ class klassItable : public ResourceObj {
NOT_PRODUCT
(
static
long
_total_size
;)
// Total no. of bytes used for itables
static
void
update_stats
(
int
size
)
PRODUCT_RETURN
NOT_PRODUCT
({
_total_classes
++
;
_total_size
+=
size
;
})
public:
#ifndef PRODUCT
bool
check_no_old_entries
();
#endif
};
#endif // SHARE_VM_OOPS_KLASSVTABLE_HPP
src/share/vm/oops/method.cpp
浏览文件 @
4b2183fb
...
...
@@ -61,24 +61,14 @@
Method
*
Method
::
allocate
(
ClassLoaderData
*
loader_data
,
int
byte_code_size
,
AccessFlags
access_flags
,
int
compressed_line_number_size
,
int
localvariable_table_length
,
int
exception_table_length
,
int
checked_exceptions_length
,
int
method_parameters_length
,
u2
generic_signature_index
,
InlineTableSizes
*
sizes
,
ConstMethod
::
MethodType
method_type
,
TRAPS
)
{
assert
(
!
access_flags
.
is_native
()
||
byte_code_size
==
0
,
"native methods should not contain byte codes"
);
ConstMethod
*
cm
=
ConstMethod
::
allocate
(
loader_data
,
byte_code_size
,
compressed_line_number_size
,
localvariable_table_length
,
exception_table_length
,
checked_exceptions_length
,
method_parameters_length
,
generic_signature_index
,
sizes
,
method_type
,
CHECK_NULL
);
...
...
@@ -317,14 +307,6 @@ Symbol* Method::klass_name() const {
}
void
Method
::
set_interpreter_kind
()
{
int
kind
=
Interpreter
::
method_kind
(
this
);
assert
(
kind
!=
Interpreter
::
invalid
,
"interpreter entry must be valid"
);
set_interpreter_kind
(
kind
);
}
// Attempt to return method oop to original state. Clear any pointers
// (to objects outside the shared spaces). We won't be able to predict
// where they should point in a new JVM. Further initialize some
...
...
@@ -332,7 +314,6 @@ void Method::set_interpreter_kind() {
void
Method
::
remove_unshareable_info
()
{
unlink_method
();
set_interpreter_kind
();
}
...
...
@@ -1045,9 +1026,9 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
methodHandle
m
;
{
InlineTableSizes
sizes
;
Method
*
m_oop
=
Method
::
allocate
(
loader_data
,
0
,
accessFlags_from
(
flags_bits
),
0
,
0
,
0
,
0
,
0
,
0
,
accessFlags_from
(
flags_bits
),
&
sizes
,
ConstMethod
::
NORMAL
,
CHECK_
(
empty
));
m
=
methodHandle
(
THREAD
,
m_oop
);
}
...
...
@@ -1096,22 +1077,35 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n
assert
(
!
m
->
is_native
(),
"cannot rewrite native methods"
);
// Allocate new Method*
AccessFlags
flags
=
m
->
access_flags
();
u2
generic_signature_index
=
m
->
generic_signature_index
();
int
checked_exceptions_len
=
m
->
checked_exceptions_length
();
int
localvariable_len
=
m
->
localvariable_table_length
();
int
exception_table_len
=
m
->
exception_table_length
();
int
method_parameters_len
=
m
->
method_parameters_length
();
ConstMethod
*
cm
=
m
->
constMethod
();
int
checked_exceptions_len
=
cm
->
checked_exceptions_length
();
int
localvariable_len
=
cm
->
localvariable_table_length
();
int
exception_table_len
=
cm
->
exception_table_length
();
int
method_parameters_len
=
cm
->
method_parameters_length
();
int
method_annotations_len
=
cm
->
method_annotations_length
();
int
parameter_annotations_len
=
cm
->
parameter_annotations_length
();
int
type_annotations_len
=
cm
->
type_annotations_length
();
int
default_annotations_len
=
cm
->
default_annotations_length
();
InlineTableSizes
sizes
(
localvariable_len
,
new_compressed_linenumber_size
,
exception_table_len
,
checked_exceptions_len
,
method_parameters_len
,
cm
->
generic_signature_index
(),
method_annotations_len
,
parameter_annotations_len
,
type_annotations_len
,
default_annotations_len
,
0
);
ClassLoaderData
*
loader_data
=
m
->
method_holder
()
->
class_loader_data
();
Method
*
newm_oop
=
Method
::
allocate
(
loader_data
,
new_code_length
,
flags
,
new_compressed_linenumber_size
,
localvariable_len
,
exception_table_len
,
checked_exceptions_len
,
method_parameters_len
,
generic_signature_index
,
&
sizes
,
m
->
method_type
(),
CHECK_
(
methodHandle
()));
methodHandle
newm
(
THREAD
,
newm_oop
);
...
...
@@ -1311,29 +1305,6 @@ void Method::print_short_name(outputStream* st) {
MethodHandles
::
print_as_basic_type_signature_on
(
st
,
signature
(),
true
);
}
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
static
void
reorder_based_on_method_index
(
Array
<
Method
*>*
methods
,
Array
<
AnnotationArray
*>*
annotations
,
GrowableArray
<
AnnotationArray
*>*
temp_array
)
{
if
(
annotations
==
NULL
)
{
return
;
}
int
length
=
methods
->
length
();
int
i
;
// Copy to temp array
temp_array
->
clear
();
for
(
i
=
0
;
i
<
length
;
i
++
)
{
temp_array
->
append
(
annotations
->
at
(
i
));
}
// Copy back using old method indices
for
(
i
=
0
;
i
<
length
;
i
++
)
{
Method
*
m
=
methods
->
at
(
i
);
annotations
->
at_put
(
i
,
temp_array
->
at
(
m
->
method_idnum
()));
}
}
// Comparer for sorting an object array containing
// Method*s.
static
int
method_comparator
(
Method
*
a
,
Method
*
b
)
{
...
...
@@ -1341,48 +1312,13 @@ static int method_comparator(Method* a, Method* b) {
}
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
void
Method
::
sort_methods
(
Array
<
Method
*>*
methods
,
Array
<
AnnotationArray
*>*
methods_annotations
,
Array
<
AnnotationArray
*>*
methods_parameter_annotations
,
Array
<
AnnotationArray
*>*
methods_default_annotations
,
Array
<
AnnotationArray
*>*
methods_type_annotations
,
bool
idempotent
)
{
void
Method
::
sort_methods
(
Array
<
Method
*>*
methods
,
bool
idempotent
)
{
int
length
=
methods
->
length
();
if
(
length
>
1
)
{
bool
do_annotations
=
false
;
if
(
methods_annotations
!=
NULL
||
methods_parameter_annotations
!=
NULL
||
methods_default_annotations
!=
NULL
||
methods_type_annotations
!=
NULL
)
{
do_annotations
=
true
;
}
if
(
do_annotations
)
{
// Remember current method ordering so we can reorder annotations
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
Method
*
m
=
methods
->
at
(
i
);
m
->
set_method_idnum
(
i
);
}
}
{
No_Safepoint_Verifier
nsv
;
QuickSort
::
sort
<
Method
*>
(
methods
->
data
(),
length
,
method_comparator
,
idempotent
);
}
// Sort annotations if necessary
assert
(
methods_annotations
==
NULL
||
methods_annotations
->
length
()
==
methods
->
length
(),
""
);
assert
(
methods_parameter_annotations
==
NULL
||
methods_parameter_annotations
->
length
()
==
methods
->
length
(),
""
);
assert
(
methods_default_annotations
==
NULL
||
methods_default_annotations
->
length
()
==
methods
->
length
(),
""
);
assert
(
methods_type_annotations
==
NULL
||
methods_type_annotations
->
length
()
==
methods
->
length
(),
""
);
if
(
do_annotations
)
{
ResourceMark
rm
;
// Allocate temporary storage
GrowableArray
<
AnnotationArray
*>*
temp_array
=
new
GrowableArray
<
AnnotationArray
*>
(
length
);
reorder_based_on_method_index
(
methods
,
methods_annotations
,
temp_array
);
reorder_based_on_method_index
(
methods
,
methods_parameter_annotations
,
temp_array
);
reorder_based_on_method_index
(
methods
,
methods_default_annotations
,
temp_array
);
reorder_based_on_method_index
(
methods
,
methods_type_annotations
,
temp_array
);
}
// Reset method ordering
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
Method
*
m
=
methods
->
at
(
i
);
...
...
@@ -1393,9 +1329,9 @@ void Method::sort_methods(Array<Method*>* methods,
//-----------------------------------------------------------------------------------
// Non-product code
// Non-product code
unless JVM/TI needs it
#if
ndef PRODUCT
#if
!defined(PRODUCT) || INCLUDE_JVMTI
class
SignatureTypePrinter
:
public
SignatureTypeNames
{
private:
outputStream
*
_st
;
...
...
@@ -1430,8 +1366,13 @@ void Method::print_name(outputStream* st) {
sig
.
print_parameters
();
st
->
print
(
")"
);
}
#endif // !PRODUCT || INCLUDE_JVMTI
//-----------------------------------------------------------------------------------
// Non-product code
#ifndef PRODUCT
void
Method
::
print_codes_on
(
outputStream
*
st
)
const
{
print_codes_on
(
0
,
code_size
(),
st
);
}
...
...
src/share/vm/oops/method.hpp
浏览文件 @
4b2183fb
...
...
@@ -101,6 +101,7 @@ class LocalVariableTableElement;
class
AdapterHandlerEntry
;
class
MethodData
;
class
ConstMethod
;
class
InlineTableSizes
;
class
KlassSizeStats
;
class
Method
:
public
Metadata
{
...
...
@@ -157,12 +158,7 @@ class Method : public Metadata {
static
Method
*
allocate
(
ClassLoaderData
*
loader_data
,
int
byte_code_size
,
AccessFlags
access_flags
,
int
compressed_line_number_size
,
int
localvariable_table_length
,
int
exception_table_length
,
int
checked_exceptions_length
,
int
method_parameters_length
,
u2
generic_signature_index
,
InlineTableSizes
*
sizes
,
ConstMethod
::
MethodType
method_type
,
TRAPS
);
...
...
@@ -207,33 +203,17 @@ class Method : public Metadata {
// annotations support
AnnotationArray
*
annotations
()
const
{
InstanceKlass
*
ik
=
method_holder
();
if
(
ik
->
annotations
()
==
NULL
)
{
return
NULL
;
}
return
ik
->
annotations
()
->
get_method_annotations_of
(
method_idnum
());
return
constMethod
()
->
method_annotations
();
}
AnnotationArray
*
parameter_annotations
()
const
{
InstanceKlass
*
ik
=
method_holder
();
if
(
ik
->
annotations
()
==
NULL
)
{
return
NULL
;
}
return
ik
->
annotations
()
->
get_method_parameter_annotations_of
(
method_idnum
());
return
constMethod
()
->
parameter_annotations
();
}
AnnotationArray
*
annotation_default
()
const
{
InstanceKlass
*
ik
=
method_holder
();
if
(
ik
->
annotations
()
==
NULL
)
{
return
NULL
;
}
return
ik
->
annotations
()
->
get_method_default_annotations_of
(
method_idnum
());
return
constMethod
()
->
default_annotations
();
}
AnnotationArray
*
type_annotations
()
const
{
return
constMethod
()
->
type_annotations
();
}
AnnotationArray
*
type_annotations
()
const
{
InstanceKlass
*
ik
=
method_holder
();
Annotations
*
type_annos
=
ik
->
type_annotations
();
if
(
type_annos
==
NULL
)
return
NULL
;
return
type_annos
->
get_method_annotations_of
(
method_idnum
());
}
#ifdef CC_INTERP
void
set_result_index
(
BasicType
type
);
...
...
@@ -439,13 +419,6 @@ class Method : public Metadata {
address
interpreter_entry
()
const
{
return
_i2i_entry
;
}
// Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry
void
set_interpreter_entry
(
address
entry
)
{
_i2i_entry
=
entry
;
_from_interpreted_entry
=
entry
;
}
int
interpreter_kind
(
void
)
{
return
constMethod
()
->
interpreter_kind
();
}
void
set_interpreter_kind
();
void
set_interpreter_kind
(
int
kind
)
{
constMethod
()
->
set_interpreter_kind
(
kind
);
}
// native function (used for native methods only)
enum
{
...
...
@@ -800,16 +773,15 @@ class Method : public Metadata {
static
bool
has_unloaded_classes_in_signature
(
methodHandle
m
,
TRAPS
);
// Printing
void
print_short_name
(
outputStream
*
st
=
tty
)
/*PRODUCT_RETURN*/
;
// prints as klassname::methodname; Exposed so field engineers can debug VM
void
print_short_name
(
outputStream
*
st
=
tty
);
// prints as klassname::methodname; Exposed so field engineers can debug VM
#if INCLUDE_JVMTI
void
print_name
(
outputStream
*
st
=
tty
);
// prints as "virtual void foo(int)"; exposed for TraceRedefineClasses
#else
void
print_name
(
outputStream
*
st
=
tty
)
PRODUCT_RETURN
;
// prints as "virtual void foo(int)"
#endif
// Helper routine used for method sorting
static
void
sort_methods
(
Array
<
Method
*>*
methods
,
Array
<
AnnotationArray
*>*
methods_annotations
,
Array
<
AnnotationArray
*>*
methods_parameter_annotations
,
Array
<
AnnotationArray
*>*
methods_default_annotations
,
Array
<
AnnotationArray
*>*
methods_type_annotations
,
bool
idempotent
=
false
);
static
void
sort_methods
(
Array
<
Method
*>*
methods
,
bool
idempotent
=
false
);
// Deallocation function for redefine classes or if an error occurs
void
deallocate_contents
(
ClassLoaderData
*
loader_data
);
...
...
src/share/vm/prims/jvm.cpp
浏览文件 @
4b2183fb
...
...
@@ -1573,9 +1573,9 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls))
if
(
!
java_lang_Class
::
is_primitive
(
JNIHandles
::
resolve
(
cls
)))
{
Klass
*
k
=
java_lang_Class
::
as_Klass
(
JNIHandles
::
resolve
(
cls
));
if
(
k
->
oop_is_instance
())
{
Annotation
s
*
type_annotations
=
InstanceKlass
::
cast
(
k
)
->
type_annotations
();
Annotation
Array
*
type_annotations
=
InstanceKlass
::
cast
(
k
)
->
class_
type_annotations
();
if
(
type_annotations
!=
NULL
)
{
typeArrayOop
a
=
Annotations
::
make_java_array
(
type_annotations
->
class_annotations
()
,
CHECK_NULL
);
typeArrayOop
a
=
Annotations
::
make_java_array
(
type_annotations
,
CHECK_NULL
);
return
(
jbyteArray
)
JNIHandles
::
make_local
(
env
,
a
);
}
}
...
...
@@ -4528,6 +4528,5 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i
// consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat
// counter defined in runtimeService.cpp.
info
->
is_attachable
=
AttachListener
::
is_attach_supported
();
info
->
is_kernel_jvm
=
0
;
// false;
}
JVM_END
src/share/vm/prims/jvm.h
浏览文件 @
4b2183fb
...
...
@@ -1559,8 +1559,7 @@ typedef struct {
* the new bit is also added in the main/baseline.
*/
unsigned
int
is_attachable
:
1
;
unsigned
int
is_kernel_jvm
:
1
;
unsigned
int
:
30
;
unsigned
int
:
31
;
unsigned
int
:
32
;
unsigned
int
:
32
;
}
jvm_version_info
;
...
...
src/share/vm/prims/jvmtiRedefineClasses.cpp
浏览文件 @
4b2183fb
...
...
@@ -154,8 +154,15 @@ void VM_RedefineClasses::doit() {
// See jvmtiExport.hpp for detailed explanation.
JvmtiExport
::
set_has_redefined_a_class
();
#ifdef ASSERT
SystemDictionary
::
classes_do
(
check_class
,
thread
);
// check_class() is optionally called for product bits, but is
// always called for non-product bits.
#ifdef PRODUCT
if
(
RC_TRACE_ENABLED
(
0x00004000
))
{
#endif
RC_TRACE_WITH_THREAD
(
0x00004000
,
thread
,
(
"calling check_class"
));
SystemDictionary
::
classes_do
(
check_class
,
thread
);
#ifdef PRODUCT
}
#endif
}
...
...
@@ -485,26 +492,6 @@ int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch
}
// end find_or_append_indirect_entry()
void
VM_RedefineClasses
::
swap_all_method_annotations
(
int
i
,
int
j
,
instanceKlassHandle
scratch_class
,
TRAPS
)
{
AnnotationArray
*
save
;
Annotations
*
sca
=
scratch_class
->
annotations
();
if
(
sca
==
NULL
)
return
;
save
=
sca
->
get_method_annotations_of
(
i
);
sca
->
set_method_annotations_of
(
scratch_class
,
i
,
sca
->
get_method_annotations_of
(
j
),
CHECK
);
sca
->
set_method_annotations_of
(
scratch_class
,
j
,
save
,
CHECK
);
save
=
sca
->
get_method_parameter_annotations_of
(
i
);
sca
->
set_method_parameter_annotations_of
(
scratch_class
,
i
,
sca
->
get_method_parameter_annotations_of
(
j
),
CHECK
);
sca
->
set_method_parameter_annotations_of
(
scratch_class
,
j
,
save
,
CHECK
);
save
=
sca
->
get_method_default_annotations_of
(
i
);
sca
->
set_method_default_annotations_of
(
scratch_class
,
i
,
sca
->
get_method_default_annotations_of
(
j
),
CHECK
);
sca
->
set_method_default_annotations_of
(
scratch_class
,
j
,
save
,
CHECK
);
}
jvmtiError
VM_RedefineClasses
::
compare_and_normalize_class_versions
(
instanceKlassHandle
the_class
,
instanceKlassHandle
scratch_class
)
{
...
...
@@ -686,10 +673,9 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
idnum_owner
->
set_method_idnum
(
new_num
);
}
k_new_method
->
set_method_idnum
(
old_num
);
swap_all_method_annotations
(
old_num
,
new_num
,
scratch_class
,
thread
);
if
(
thread
->
has_pending_exception
())
{
return
JVMTI_ERROR_OUT_OF_MEMORY
;
}
if
(
thread
->
has_pending_exception
())
{
return
JVMTI_ERROR_OUT_OF_MEMORY
;
}
}
}
RC_TRACE
(
0x00008000
,
(
"Method matched: new: %s [%d] == old: %s [%d]"
,
...
...
@@ -722,7 +708,6 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
idnum_owner
->
set_method_idnum
(
new_num
);
}
k_new_method
->
set_method_idnum
(
num
);
swap_all_method_annotations
(
new_num
,
num
,
scratch_class
,
thread
);
if
(
thread
->
has_pending_exception
())
{
return
JVMTI_ERROR_OUT_OF_MEMORY
;
}
...
...
@@ -1564,9 +1549,9 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method,
bcp
,
cp_index
,
new_index
));
// Rewriter::rewrite_method() uses put_native_u2() in this
// situation because it is reusing the constant pool index
// location for a native index into the
c
onstantPoolCache.
// location for a native index into the
C
onstantPoolCache.
// Since we are updating the constant pool index prior to
// verification and
c
onstantPoolCache initialization, we
// verification and
C
onstantPoolCache initialization, we
// need to keep the new index in Java byte order.
Bytes
::
put_Java_u2
(
p
,
new_index
);
}
...
...
@@ -1888,10 +1873,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_element_value(
bool
VM_RedefineClasses
::
rewrite_cp_refs_in_fields_annotations
(
instanceKlassHandle
scratch_class
,
TRAPS
)
{
Annotations
*
sca
=
scratch_class
->
annotations
();
if
(
sca
==
NULL
)
return
true
;
Array
<
AnnotationArray
*>*
fields_annotations
=
sca
->
fields_annotations
();
Array
<
AnnotationArray
*>*
fields_annotations
=
scratch_class
->
fields_annotations
();
if
(
fields_annotations
==
NULL
||
fields_annotations
->
length
()
==
0
)
{
// no fields_annotations so nothing to do
...
...
@@ -1926,21 +1908,10 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
bool
VM_RedefineClasses
::
rewrite_cp_refs_in_methods_annotations
(
instanceKlassHandle
scratch_class
,
TRAPS
)
{
Annotations
*
sca
=
scratch_class
->
annotations
();
if
(
sca
==
NULL
)
return
true
;
Array
<
AnnotationArray
*>*
methods_annotations
=
sca
->
methods_annotations
();
if
(
methods_annotations
==
NULL
||
methods_annotations
->
length
()
==
0
)
{
// no methods_annotations so nothing to do
return
true
;
}
for
(
int
i
=
0
;
i
<
scratch_class
->
methods
()
->
length
();
i
++
)
{
Method
*
m
=
scratch_class
->
methods
()
->
at
(
i
);
AnnotationArray
*
method_annotations
=
m
->
constMethod
()
->
method_annotations
();
RC_TRACE_WITH_THREAD
(
0x02000000
,
THREAD
,
(
"methods_annotations length=%d"
,
methods_annotations
->
length
()));
for
(
int
i
=
0
;
i
<
methods_annotations
->
length
();
i
++
)
{
AnnotationArray
*
method_annotations
=
methods_annotations
->
at
(
i
);
if
(
method_annotations
==
NULL
||
method_annotations
->
length
()
==
0
)
{
// this method does not have any annotations so skip it
continue
;
...
...
@@ -1976,24 +1947,9 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
bool
VM_RedefineClasses
::
rewrite_cp_refs_in_methods_parameter_annotations
(
instanceKlassHandle
scratch_class
,
TRAPS
)
{
Annotations
*
sca
=
scratch_class
->
annotations
();
if
(
sca
==
NULL
)
return
true
;
Array
<
AnnotationArray
*>*
methods_parameter_annotations
=
sca
->
methods_parameter_annotations
();
if
(
methods_parameter_annotations
==
NULL
||
methods_parameter_annotations
->
length
()
==
0
)
{
// no methods_parameter_annotations so nothing to do
return
true
;
}
RC_TRACE_WITH_THREAD
(
0x02000000
,
THREAD
,
(
"methods_parameter_annotations length=%d"
,
methods_parameter_annotations
->
length
()));
for
(
int
i
=
0
;
i
<
methods_parameter_annotations
->
length
();
i
++
)
{
AnnotationArray
*
method_parameter_annotations
=
methods_parameter_annotations
->
at
(
i
);
for
(
int
i
=
0
;
i
<
scratch_class
->
methods
()
->
length
();
i
++
)
{
Method
*
m
=
scratch_class
->
methods
()
->
at
(
i
);
AnnotationArray
*
method_parameter_annotations
=
m
->
constMethod
()
->
parameter_annotations
();
if
(
method_parameter_annotations
==
NULL
||
method_parameter_annotations
->
length
()
==
0
)
{
// this method does not have any parameter annotations so skip it
...
...
@@ -2043,24 +1999,9 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
bool
VM_RedefineClasses
::
rewrite_cp_refs_in_methods_default_annotations
(
instanceKlassHandle
scratch_class
,
TRAPS
)
{
Annotations
*
sca
=
scratch_class
->
annotations
();
if
(
sca
==
NULL
)
return
true
;
Array
<
AnnotationArray
*>*
methods_default_annotations
=
sca
->
methods_default_annotations
();
if
(
methods_default_annotations
==
NULL
||
methods_default_annotations
->
length
()
==
0
)
{
// no methods_default_annotations so nothing to do
return
true
;
}
RC_TRACE_WITH_THREAD
(
0x02000000
,
THREAD
,
(
"methods_default_annotations length=%d"
,
methods_default_annotations
->
length
()));
for
(
int
i
=
0
;
i
<
methods_default_annotations
->
length
();
i
++
)
{
AnnotationArray
*
method_default_annotations
=
methods_default_annotations
->
at
(
i
);
for
(
int
i
=
0
;
i
<
scratch_class
->
methods
()
->
length
();
i
++
)
{
Method
*
m
=
scratch_class
->
methods
()
->
at
(
i
);
AnnotationArray
*
method_default_annotations
=
m
->
constMethod
()
->
default_annotations
();
if
(
method_default_annotations
==
NULL
||
method_default_annotations
->
length
()
==
0
)
{
// this method does not have any default annotations so skip it
...
...
@@ -3065,6 +3006,31 @@ void VM_RedefineClasses::compute_added_deleted_matching_methods() {
}
void
VM_RedefineClasses
::
swap_annotations
(
instanceKlassHandle
the_class
,
instanceKlassHandle
scratch_class
)
{
// Since there is currently no rewriting of type annotations indexes
// into the CP, we null out type annotations on scratch_class before
// we swap annotations with the_class rather than facing the
// possibility of shipping annotations with broken indexes to
// Java-land.
ClassLoaderData
*
loader_data
=
scratch_class
->
class_loader_data
();
AnnotationArray
*
new_class_type_annotations
=
scratch_class
->
class_type_annotations
();
if
(
new_class_type_annotations
!=
NULL
)
{
MetadataFactory
::
free_array
<
u1
>
(
loader_data
,
new_class_type_annotations
);
scratch_class
->
annotations
()
->
set_class_type_annotations
(
NULL
);
}
Array
<
AnnotationArray
*>*
new_field_type_annotations
=
scratch_class
->
fields_type_annotations
();
if
(
new_field_type_annotations
!=
NULL
)
{
Annotations
::
free_contents
(
loader_data
,
new_field_type_annotations
);
scratch_class
->
annotations
()
->
set_fields_type_annotations
(
NULL
);
}
// Swap annotation fields values
Annotations
*
old_annotations
=
the_class
->
annotations
();
the_class
->
set_annotations
(
scratch_class
->
annotations
());
scratch_class
->
set_annotations
(
old_annotations
);
}
// Install the redefinition of a class:
// - house keeping (flushing breakpoints and caches, deoptimizing
...
...
@@ -3275,23 +3241,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
the_class
->
set_access_flags
(
flags
);
}
// Since there is currently no rewriting of type annotations indexes
// into the CP, we null out type annotations on scratch_class before
// we swap annotations with the_class rather than facing the
// possibility of shipping annotations with broken indexes to
// Java-land.
Annotations
*
new_annotations
=
scratch_class
->
annotations
();
if
(
new_annotations
!=
NULL
)
{
Annotations
*
new_type_annotations
=
new_annotations
->
type_annotations
();
if
(
new_type_annotations
!=
NULL
)
{
MetadataFactory
::
free_metadata
(
scratch_class
->
class_loader_data
(),
new_type_annotations
);
new_annotations
->
set_type_annotations
(
NULL
);
}
}
// Swap annotation fields values
Annotations
*
old_annotations
=
the_class
->
annotations
();
the_class
->
set_annotations
(
scratch_class
->
annotations
());
scratch_class
->
set_annotations
(
old_annotations
);
swap_annotations
(
the_class
,
scratch_class
);
// Replace minor version number of class file
u2
old_minor_version
=
the_class
->
minor_version
();
...
...
@@ -3371,7 +3321,6 @@ void VM_RedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) {
}
}
#ifndef PRODUCT
void
VM_RedefineClasses
::
check_class
(
Klass
*
k_oop
,
ClassLoaderData
*
initiating_loader
,
TRAPS
)
{
...
...
@@ -3379,82 +3328,110 @@ void VM_RedefineClasses::check_class(Klass* k_oop,
if
(
k
->
oop_is_instance
())
{
HandleMark
hm
(
THREAD
);
InstanceKlass
*
ik
=
(
InstanceKlass
*
)
k
;
bool
no_old_methods
=
true
;
// be optimistic
ResourceMark
rm
(
THREAD
);
if
(
ik
->
vtable_length
()
>
0
)
{
ResourceMark
rm
(
THREAD
);
if
(
!
ik
->
vtable
()
->
check_no_old_entries
())
{
tty
->
print_cr
(
"klassVtable::check_no_old_entries failure -- OLD method found -- class: %s"
,
ik
->
signature_name
());
// a vtable should never contain old or obsolete methods
if
(
ik
->
vtable_length
()
>
0
&&
!
ik
->
vtable
()
->
check_no_old_or_obsolete_entries
())
{
if
(
RC_TRACE_ENABLED
(
0x00004000
))
{
RC_TRACE_WITH_THREAD
(
0x00004000
,
THREAD
,
(
"klassVtable::check_no_old_or_obsolete_entries failure"
" -- OLD or OBSOLETE method found -- class: %s"
,
ik
->
signature_name
()));
ik
->
vtable
()
->
dump_vtable
();
assert
(
false
,
"OLD method found"
);
}
}
if
(
ik
->
itable_length
()
>
0
)
{
ResourceMark
rm
(
THREAD
);
if
(
!
ik
->
itable
()
->
check_no_old_entries
())
{
tty
->
print_cr
(
"klassItable::check_no_old_entries failure -- OLD method found -- class: %s"
,
ik
->
signature_name
());
assert
(
false
,
"OLD method found"
);
no_old_methods
=
false
;
}
// an itable should never contain old or obsolete methods
if
(
ik
->
itable_length
()
>
0
&&
!
ik
->
itable
()
->
check_no_old_or_obsolete_entries
())
{
if
(
RC_TRACE_ENABLED
(
0x00004000
))
{
RC_TRACE_WITH_THREAD
(
0x00004000
,
THREAD
,
(
"klassItable::check_no_old_or_obsolete_entries failure"
" -- OLD or OBSOLETE method found -- class: %s"
,
ik
->
signature_name
()));
ik
->
itable
()
->
dump_itable
();
}
no_old_methods
=
false
;
}
// Check that the constant pool cache has no deleted entries.
// the constant pool cache should never contain old or obsolete methods
if
(
ik
->
constants
()
!=
NULL
&&
ik
->
constants
()
->
cache
()
!=
NULL
&&
!
ik
->
constants
()
->
cache
()
->
check_no_old_entries
())
{
tty
->
print_cr
(
"klassVtable::check_no_old_entries failure -- OLD method found -- class: %s"
,
ik
->
signature_name
());
assert
(
false
,
"OLD method found"
);
!
ik
->
constants
()
->
cache
()
->
check_no_old_or_obsolete_entries
())
{
if
(
RC_TRACE_ENABLED
(
0x00004000
))
{
RC_TRACE_WITH_THREAD
(
0x00004000
,
THREAD
,
(
"cp-cache::check_no_old_or_obsolete_entries failure"
" -- OLD or OBSOLETE method found -- class: %s"
,
ik
->
signature_name
()));
ik
->
constants
()
->
cache
()
->
dump_cache
();
}
no_old_methods
=
false
;
}
if
(
!
no_old_methods
)
{
if
(
RC_TRACE_ENABLED
(
0x00004000
))
{
dump_methods
();
}
else
{
tty
->
print_cr
(
"INFO: use the '-XX:TraceRedefineClasses=16384' option "
"to see more info about the following guarantee() failure."
);
}
guarantee
(
false
,
"OLD and/or OBSOLETE method(s) found"
);
}
}
}
void
VM_RedefineClasses
::
dump_methods
()
{
int
j
;
tty
->
print_cr
(
"_old_methods --"
);
for
(
j
=
0
;
j
<
_old_methods
->
length
();
++
j
)
{
Method
*
m
=
_old_methods
->
at
(
j
);
tty
->
print
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
(
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
tty
->
print_cr
(
"_new_methods --"
);
for
(
j
=
0
;
j
<
_new_methods
->
length
();
++
j
)
{
Method
*
m
=
_new_methods
->
at
(
j
);
tty
->
print
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
(
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
tty
->
print_cr
(
"_matching_(old/new)_methods --"
);
for
(
j
=
0
;
j
<
_matching_methods_length
;
++
j
)
{
Method
*
m
=
_matching_old_methods
[
j
];
tty
->
print
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
(
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
m
=
_matching_new_methods
[
j
];
tty
->
print
(
" (%5d) "
,
m
->
vtable_index
(
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
cr
();
}
tty
->
print_cr
(
"_deleted_methods --"
);
for
(
j
=
0
;
j
<
_deleted_methods_length
;
++
j
)
{
Method
*
m
=
_deleted_methods
[
j
];
tty
->
print
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
(
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
tty
->
print_cr
(
"_added_methods --"
);
for
(
j
=
0
;
j
<
_added_methods_length
;
++
j
)
{
Method
*
m
=
_added_methods
[
j
];
tty
->
print
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
(
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
int
j
;
RC_TRACE
(
0x00004000
,
(
"_old_methods --"
)
);
for
(
j
=
0
;
j
<
_old_methods
->
length
();
++
j
)
{
Method
*
m
=
_old_methods
->
at
(
j
);
RC_TRACE_NO_CR
(
0x00004000
,
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
()
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
RC_TRACE
(
0x00004000
,
(
"_new_methods --"
)
);
for
(
j
=
0
;
j
<
_new_methods
->
length
();
++
j
)
{
Method
*
m
=
_new_methods
->
at
(
j
);
RC_TRACE_NO_CR
(
0x00004000
,
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
()
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
RC_TRACE
(
0x00004000
,
(
"_matching_(old/new)_methods --"
)
);
for
(
j
=
0
;
j
<
_matching_methods_length
;
++
j
)
{
Method
*
m
=
_matching_old_methods
[
j
];
RC_TRACE_NO_CR
(
0x00004000
,
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
()
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
m
=
_matching_new_methods
[
j
];
RC_TRACE_NO_CR
(
0x00004000
,
(
" (%5d) "
,
m
->
vtable_index
()
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
cr
();
}
RC_TRACE
(
0x00004000
,
(
"_deleted_methods --"
)
);
for
(
j
=
0
;
j
<
_deleted_methods_length
;
++
j
)
{
Method
*
m
=
_deleted_methods
[
j
];
RC_TRACE_NO_CR
(
0x00004000
,
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
()
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
RC_TRACE
(
0x00004000
,
(
"_added_methods --"
)
);
for
(
j
=
0
;
j
<
_added_methods_length
;
++
j
)
{
Method
*
m
=
_added_methods
[
j
];
RC_TRACE_NO_CR
(
0x00004000
,
(
"%4d (%5d) "
,
j
,
m
->
vtable_index
()
));
m
->
access_flags
().
print_on
(
tty
);
tty
->
print
(
" -- "
);
m
->
print_name
(
tty
);
tty
->
cr
();
}
}
#endif
src/share/vm/prims/jvmtiRedefineClasses.hpp
浏览文件 @
4b2183fb
...
...
@@ -384,11 +384,6 @@ class VM_RedefineClasses: public VM_Operation {
jvmtiError
compare_and_normalize_class_versions
(
instanceKlassHandle
the_class
,
instanceKlassHandle
scratch_class
);
// Swap annotations[i] with annotations[j]
// Used by compare_and_normalize_class_versions() when normalizing
// overloaded methods or changing idnum as when adding or deleting methods.
void
swap_all_method_annotations
(
int
i
,
int
j
,
instanceKlassHandle
scratch_class
,
TRAPS
);
// Figure out which new methods match old methods in name and signature,
// which methods have been added, and which are no longer present
void
compute_added_deleted_matching_methods
();
...
...
@@ -417,6 +412,9 @@ class VM_RedefineClasses: public VM_Operation {
void
redefine_single_class
(
jclass
the_jclass
,
Klass
*
scratch_class_oop
,
TRAPS
);
void
swap_annotations
(
instanceKlassHandle
new_class
,
instanceKlassHandle
scratch_class
);
// Increment the classRedefinedCount field in the specific InstanceKlass
// and in all direct and indirect subclasses.
void
increment_class_counter
(
InstanceKlass
*
ik
,
TRAPS
);
...
...
@@ -468,9 +466,9 @@ class VM_RedefineClasses: public VM_Operation {
void
flush_dependent_code
(
instanceKlassHandle
k_h
,
TRAPS
);
static
void
check_class
(
Klass
*
k_oop
,
ClassLoaderData
*
initiating_loader
,
TRAPS
)
PRODUCT_RETURN
;
static
void
dump_methods
()
PRODUCT_RETURN
;
static
void
check_class
(
Klass
*
k_oop
,
ClassLoaderData
*
initiating_loader
,
TRAPS
);
static
void
dump_methods
();
public:
VM_RedefineClasses
(
jint
class_count
,
...
...
src/share/vm/prims/jvmtiRedefineClassesTrace.hpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 2003, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 201
3
, 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
...
...
@@ -54,7 +54,7 @@
// 0x00000800 | 2048 - previous class breakpoint mgmt
// 0x00001000 | 4096 - detect calls to obsolete methods
// 0x00002000 | 8192 - fail a guarantee() in addition to detection
// 0x00004000 | 16384 -
unused
// 0x00004000 | 16384 -
detect old/obsolete methods in metadata
// 0x00008000 | 32768 - old/new method matching/add/delete
// 0x00010000 | 65536 - impl details: CP size info
// 0x00020000 | 131072 - impl details: CP merge pass info
...
...
@@ -82,6 +82,13 @@
tty->print_cr args; \
} while (0)
#define RC_TRACE_NO_CR(level, args) \
if ((TraceRedefineClasses & level) != 0) { \
ResourceMark rm; \
tty->print("RedefineClasses-0x%x: ", level); \
tty->print args; \
} while (0)
#define RC_TRACE_WITH_THREAD(level, thread, args) \
if ((TraceRedefineClasses & level) != 0) { \
ResourceMark rm(thread); \
...
...
src/share/vm/runtime/fieldDescriptor.cpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 1997, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
3
, 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
...
...
@@ -67,13 +67,10 @@ AnnotationArray* fieldDescriptor::annotations() const {
AnnotationArray
*
fieldDescriptor
::
type_annotations
()
const
{
InstanceKlass
*
ik
=
field_holder
();
A
nnotations
*
type_annos
=
ik
->
type_annotations
();
A
rray
<
AnnotationArray
*>*
type_annos
=
ik
->
fields_
type_annotations
();
if
(
type_annos
==
NULL
)
return
NULL
;
Array
<
AnnotationArray
*>*
md
=
type_annos
->
fields_annotations
();
if
(
md
==
NULL
)
return
NULL
;
return
md
->
at
(
index
());
return
type_annos
->
at
(
index
());
}
constantTag
fieldDescriptor
::
initial_value_tag
()
const
{
...
...
src/share/vm/runtime/vmStructs.cpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 2000, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
3
, 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
...
...
@@ -366,11 +366,10 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
volatile_nonstatic_field(Method, _from_compiled_entry, address) \
volatile_nonstatic_field(Method, _from_interpreted_entry, address) \
volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \
nonstatic_field(ConstMethod, _constants, ConstantPool*) \
nonstatic_field(ConstMethod, _constants, ConstantPool*)
\
nonstatic_field(ConstMethod, _stackmap_data, Array<u1>*) \
nonstatic_field(ConstMethod, _constMethod_size, int) \
nonstatic_field(ConstMethod, _interpreter_kind, jbyte) \
nonstatic_field(ConstMethod, _flags, jbyte) \
nonstatic_field(ConstMethod, _flags, u2) \
nonstatic_field(ConstMethod, _code_size, u2) \
nonstatic_field(ConstMethod, _name_index, u2) \
nonstatic_field(ConstMethod, _signature_index, u2) \
...
...
@@ -2261,14 +2260,18 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
declare_constant(Klass::_lh_array_tag_obj_value) \
\
/********************************/
\
/* ConstMethod anon-enum */
\
/* ConstMethod anon-enum */
\
/********************************/
\
\
declare_constant(ConstMethod::_has_linenumber_table) \
declare_constant(ConstMethod::_has_checked_exceptions) \
declare_constant(ConstMethod::_has_localvariable_table) \
declare_constant(ConstMethod::_has_exception_table) \
declare_constant(ConstMethod::_has_generic_signature) \
declare_constant(ConstMethod::_has_linenumber_table) \
declare_constant(ConstMethod::_has_checked_exceptions) \
declare_constant(ConstMethod::_has_localvariable_table) \
declare_constant(ConstMethod::_has_exception_table) \
declare_constant(ConstMethod::_has_generic_signature) \
declare_constant(ConstMethod::_has_method_annotations) \
declare_constant(ConstMethod::_has_parameter_annotations) \
declare_constant(ConstMethod::_has_default_annotations) \
declare_constant(ConstMethod::_has_type_annotations) \
\
/*************************************/
\
/* InstanceKlass enum */
\
...
...
src/share/vm/utilities/accessFlags.cpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 1997, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
3
, 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
...
...
@@ -59,7 +59,7 @@ void AccessFlags::atomic_clear_bits(jint bits) {
}
while
(
f
!=
old_flags
);
}
#if
ndef PRODUCT
#if
!defined(PRODUCT) || INCLUDE_JVMTI
void
AccessFlags
::
print_on
(
outputStream
*
st
)
const
{
if
(
is_public
())
st
->
print
(
"public "
);
...
...
@@ -80,7 +80,7 @@ void AccessFlags::print_on(outputStream* st) const {
if
(
on_stack
())
st
->
print
(
"{on_stack} "
);
}
#endif
#endif
// !PRODUCT || INCLUDE_JVMTI
void
accessFlags_init
()
{
assert
(
sizeof
(
AccessFlags
)
==
sizeof
(
jint
),
"just checking size of flags"
);
...
...
src/share/vm/utilities/accessFlags.hpp
浏览文件 @
4b2183fb
/*
* Copyright (c) 1997, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
3
, 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
...
...
@@ -239,7 +239,11 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
inline
friend
AccessFlags
accessFlags_from
(
jint
flags
);
// Printing/debugging
#if INCLUDE_JVMTI
void
print_on
(
outputStream
*
st
)
const
;
#else
void
print_on
(
outputStream
*
st
)
const
PRODUCT_RETURN
;
#endif
};
inline
AccessFlags
accessFlags_from
(
jint
flags
)
{
...
...
test/runtime/8007320/ConstMethodTest.java
0 → 100644
浏览文件 @
4b2183fb
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8007320
* @summary Test all optional fields in ConstMethod
* @compile -g -parameters ConstMethodTest.java
* @run main ConstMethodTest
*/
import
java.util.*
;
import
java.lang.annotation.*
;
import
java.lang.reflect.*
;
import
java.io.Serializable
;
@Retention
(
RetentionPolicy
.
RUNTIME
)
@interface
MyAnnotation
{
public
String
name
();
public
String
value
();
public
String
date
()
default
"today"
;
}
@Target
(
ElementType
.
TYPE_USE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@interface
TypeAnno
{
String
value
();
}
@Target
(
ElementType
.
TYPE_USE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@interface
TypeAnno2
{
String
value
();
}
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
PARAMETER
)
@interface
Named
{
String
value
();
}
@Retention
(
RetentionPolicy
.
RUNTIME
)
@interface
ScalarTypesWithDefault
{
byte
b
()
default
11
;
short
s
()
default
12
;
int
i
()
default
13
;
long
l
()
default
14
;
char
c
()
default
'V'
;
}
// Some exception class
class
OkException
extends
RuntimeException
{};
@MyAnnotation
(
name
=
"someName"
,
value
=
"Hello World"
)
public
class
ConstMethodTest
{
private
static
void
check
(
boolean
b
)
{
if
(!
b
)
throw
new
RuntimeException
();
}
private
static
void
fail
(
String
msg
)
{
System
.
err
.
println
(
msg
);
throw
new
RuntimeException
();
}
private
static
void
equal
(
Object
x
,
Object
y
)
{
if
(
x
==
null
?
y
==
null
:
x
.
equals
(
y
))
{
}
else
{
fail
(
x
+
" not equal to "
+
y
);
}
}
private
static
final
String
[]
parameter_names
=
{
"parameter"
,
"parameter2"
,
"x"
};
// Declare a function with everything in it.
@MyAnnotation
(
name
=
"someName"
,
value
=
"Hello World"
)
static
<
T
>
void
kitchenSinkFunc
(
@Named
(
value
=
"aName"
)
String
parameter
,
@Named
(
"bName"
)
String
parameter2
,
@ScalarTypesWithDefault
T
x
)
throws
@TypeAnno
(
"RE"
)
@TypeAnno2
(
"RE2"
)
RuntimeException
,
NullPointerException
,
@TypeAnno
(
"AIOOBE"
)
ArrayIndexOutOfBoundsException
{
int
i
,
j
,
k
;
try
{
System
.
out
.
println
(
"calling kitchenSinkFunc "
+
parameter
);
throw
new
OkException
();
// to see stack trace with line numbers
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
private
static
void
test1
()
throws
Throwable
{
for
(
Method
m
:
ConstMethodTest
.
class
.
getDeclaredMethods
())
{
if
(
m
.
getName
().
equals
(
"kitchenSinkFunc"
))
{
Annotation
[][]
ann
=
m
.
getParameterAnnotations
();
equal
(
ann
.
length
,
3
);
Annotation
foo
=
ann
[
0
][
0
];
Annotation
bar
=
ann
[
1
][
0
];
equal
(
foo
.
toString
(),
"@Named(value=aName)"
);
equal
(
bar
.
toString
(),
"@Named(value=bName)"
);
check
(
foo
.
equals
(
foo
));
check
(
bar
.
equals
(
bar
));
check
(!
foo
.
equals
(
bar
));
// method annotations
Annotation
[]
ann2
=
m
.
getAnnotations
();
equal
(
ann2
.
length
,
1
);
Annotation
mann
=
ann2
[
0
];
equal
(
mann
.
toString
(),
"@MyAnnotation(date=today, name=someName, value=Hello World)"
);
// Test Method parameter names
Parameter
[]
parameters
=
m
.
getParameters
();
if
(
parameters
==
null
)
throw
new
Exception
(
"getParameters should never be null"
);
for
(
int
i
=
0
;
i
<
parameters
.
length
;
i
++)
{
Parameter
p
=
parameters
[
i
];
equal
(
parameters
[
i
].
getName
(),
parameter_names
[
i
]);
}
}
}
}
public
static
void
main
(
java
.
lang
.
String
[]
unused
)
throws
Throwable
{
// pass 5 so kitchenSinkFunc is instantiated with an int
kitchenSinkFunc
(
"parameter"
,
"param2"
,
5
);
test1
();
}
};
test/runtime/CommandLine/BooleanFlagWithInvalidValue.java
0 → 100644
浏览文件 @
4b2183fb
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006298
* @summary Setting an invalid value for a bool argument should result in a useful error message
* @library /testlibrary
*/
import
com.oracle.java.testlibrary.*
;
public
class
BooleanFlagWithInvalidValue
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
ProcessBuilder
pb
=
ProcessTools
.
createJavaProcessBuilder
(
"-XX:+UseLargePages=8"
,
"-version"
);
OutputAnalyzer
output
=
new
OutputAnalyzer
(
pb
.
start
());
output
.
shouldContain
(
"Improperly specified VM option 'UseLargePages=8'"
);
output
.
shouldHaveExitValue
(
1
);
pb
=
ProcessTools
.
createJavaProcessBuilder
(
"-XX:-UseLargePages=8"
,
"-version"
);
output
=
new
OutputAnalyzer
(
pb
.
start
());
output
.
shouldContain
(
"Improperly specified VM option 'UseLargePages=8'"
);
output
.
shouldHaveExitValue
(
1
);
}
}
test/runtime/CommandLine/FlagWithInvalidValue.java
0 → 100644
浏览文件 @
4b2183fb
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006298
* @summary Setting a flag to an invalid value should print a useful error message
* @library /testlibrary
*/
import
com.oracle.java.testlibrary.*
;
public
class
FlagWithInvalidValue
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
ProcessBuilder
pb
=
ProcessTools
.
createJavaProcessBuilder
(
"-XX:ObjectAlignmentInBytes=v"
,
"-version"
);
OutputAnalyzer
output
=
new
OutputAnalyzer
(
pb
.
start
());
output
.
shouldContain
(
"Improperly specified VM option 'ObjectAlignmentInBytes=v'"
);
output
.
shouldHaveExitValue
(
1
);
}
}
test/runtime/CommandLine/NonBooleanFlagWithInvalidBooleanPrefix.java
0 → 100644
浏览文件 @
4b2183fb
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006298
* @summary Using a bool (+/-) prefix on non-bool flag should result in a useful error message
* @library /testlibrary
*/
import
com.oracle.java.testlibrary.*
;
public
class
NonBooleanFlagWithInvalidBooleanPrefix
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
ProcessBuilder
pb
=
ProcessTools
.
createJavaProcessBuilder
(
"-XX:-ObjectAlignmentInBytes=16"
,
"-version"
);
OutputAnalyzer
output
=
new
OutputAnalyzer
(
pb
.
start
());
output
.
shouldContain
(
"Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'"
);
output
.
shouldHaveExitValue
(
1
);
pb
=
ProcessTools
.
createJavaProcessBuilder
(
"-XX:+ObjectAlignmentInBytes=16"
,
"-version"
);
output
=
new
OutputAnalyzer
(
pb
.
start
());
output
.
shouldContain
(
"Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'"
);
output
.
shouldHaveExitValue
(
1
);
}
}
test/runtime/CommandLine/UnrecognizedVMOption.java
0 → 100644
浏览文件 @
4b2183fb
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006298
* @summary Using an unrecognized VM option should print the name of the option
* @library /testlibrary
*/
import
com.oracle.java.testlibrary.*
;
public
class
UnrecognizedVMOption
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
ProcessBuilder
pb
=
ProcessTools
.
createJavaProcessBuilder
(
"-XX:bogus_option"
,
"-version"
);
OutputAnalyzer
output
=
new
OutputAnalyzer
(
pb
.
start
());
output
.
shouldContain
(
"Unrecognized VM option 'bogus_option'"
);
output
.
shouldHaveExitValue
(
1
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录