Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
f2a7a11c
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看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f2a7a11c
编写于
10月 01, 2013
作者:
A
acorn
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8011311: Private interface methods. Default conflicts:ICCE. no erased_super_default.
Reviewed-by: coleenp, bharadwaj, minqi
上级
b65ffa09
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
200 addition
and
268 deletion
+200
-268
src/share/vm/classfile/classFileParser.cpp
src/share/vm/classfile/classFileParser.cpp
+3
-1
src/share/vm/classfile/defaultMethods.cpp
src/share/vm/classfile/defaultMethods.cpp
+15
-201
src/share/vm/classfile/defaultMethods.hpp
src/share/vm/classfile/defaultMethods.hpp
+1
-11
src/share/vm/interpreter/linkResolver.cpp
src/share/vm/interpreter/linkResolver.cpp
+171
-51
src/share/vm/oops/instanceKlass.cpp
src/share/vm/oops/instanceKlass.cpp
+3
-1
src/share/vm/oops/klassVtable.cpp
src/share/vm/oops/klassVtable.cpp
+7
-3
未找到文件。
src/share/vm/classfile/classFileParser.cpp
浏览文件 @
f2a7a11c
...
...
@@ -2545,7 +2545,9 @@ Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
if
(
method
->
is_final
())
{
*
has_final_method
=
true
;
}
if
(
is_interface
&&
!
method
->
is_abstract
()
&&
!
method
->
is_static
())
{
if
(
is_interface
&&
!
(
*
has_default_methods
)
&&
!
method
->
is_abstract
()
&&
!
method
->
is_static
()
&&
!
method
->
is_private
())
{
// default method
*
has_default_methods
=
true
;
}
...
...
src/share/vm/classfile/defaultMethods.cpp
浏览文件 @
f2a7a11c
...
...
@@ -325,6 +325,7 @@ class MethodFamily : public ResourceObj {
Method
*
_selected_target
;
// Filled in later, if a unique target exists
Symbol
*
_exception_message
;
// If no unique target is found
Symbol
*
_exception_name
;
// If no unique target is found
bool
contains_method
(
Method
*
method
)
{
int
*
lookup
=
_member_index
.
get
(
method
);
...
...
@@ -350,7 +351,7 @@ class MethodFamily : public ResourceObj {
public:
MethodFamily
()
:
_selected_target
(
NULL
),
_exception_message
(
NULL
)
{}
:
_selected_target
(
NULL
),
_exception_message
(
NULL
)
,
_exception_name
(
NULL
)
{}
void
set_target_if_empty
(
Method
*
m
)
{
if
(
_selected_target
==
NULL
&&
!
m
->
is_overpass
())
{
...
...
@@ -383,6 +384,7 @@ class MethodFamily : public ResourceObj {
Method
*
get_selected_target
()
{
return
_selected_target
;
}
Symbol
*
get_exception_message
()
{
return
_exception_message
;
}
Symbol
*
get_exception_name
()
{
return
_exception_name
;
}
// Either sets the target or the exception error message
void
determine_target
(
InstanceKlass
*
root
,
TRAPS
)
{
...
...
@@ -400,15 +402,18 @@ class MethodFamily : public ResourceObj {
if
(
qualified_methods
.
length
()
==
0
)
{
_exception_message
=
generate_no_defaults_message
(
CHECK
);
_exception_name
=
vmSymbols
::
java_lang_AbstractMethodError
();
}
else
if
(
qualified_methods
.
length
()
==
1
)
{
Method
*
method
=
qualified_methods
.
at
(
0
);
if
(
method
->
is_abstract
())
{
_exception_message
=
generate_abstract_method_message
(
method
,
CHECK
);
_exception_name
=
vmSymbols
::
java_lang_AbstractMethodError
();
}
else
{
_selected_target
=
qualified_methods
.
at
(
0
);
}
}
else
{
_exception_message
=
generate_conflicts_message
(
&
qualified_methods
,
CHECK
);
_exception_name
=
vmSymbols
::
java_lang_IncompatibleClassChangeError
();
}
assert
((
has_target
()
^
throws_exception
())
==
1
,
...
...
@@ -459,8 +464,9 @@ class MethodFamily : public ResourceObj {
void
print_exception
(
outputStream
*
str
,
int
indent
)
{
assert
(
throws_exception
(),
"Should be called otherwise"
);
assert
(
_exception_name
!=
NULL
,
"exception_name should be set"
);
streamIndentor
si
(
str
,
indent
*
2
);
str
->
indent
().
print_cr
(
"%s
"
,
_exception_message
->
as_C_string
());
str
->
indent
().
print_cr
(
"%s
: %s"
,
_exception_name
->
as_C_string
()
,
_exception_message
->
as_C_string
());
}
#endif // ndef PRODUCT
};
...
...
@@ -670,7 +676,10 @@ class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> {
InstanceKlass
*
iklass
=
current_class
();
Method
*
m
=
iklass
->
find_method
(
_method_name
,
_method_signature
);
if
(
m
!=
NULL
)
{
// private interface methods are not candidates for default methods
// invokespecial to private interface methods doesn't use default method logic
// future: take access controls into account for superclass methods
if
(
m
!=
NULL
&&
(
!
iklass
->
is_interface
()
||
m
->
is_public
()))
{
if
(
_family
==
NULL
)
{
_family
=
new
StatefulMethodFamily
();
}
...
...
@@ -782,200 +791,7 @@ void DefaultMethods::generate_default_methods(
#endif // ndef PRODUCT
}
/**
* Interface inheritance rules were used to find a unique default method
* candidate for the resolved class. This
* method is only viable if it would also be in the set of default method
* candidates if we ran a full analysis on the current class.
*
* The only reason that the method would not be in the set of candidates for
* the current class is if that there's another matching method
* which is "more specific" than the found method -- i.e., one could find a
* path in the interface hierarchy in which the matching method appears
* before we get to '_target'.
*
* In order to determine this, we examine all of the implemented
* interfaces. If we find path that leads to the '_target' interface, then
* we examine that path to see if there are any methods that would shadow
* the selected method along that path.
*/
class
ShadowChecker
:
public
HierarchyVisitor
<
ShadowChecker
>
{
protected:
Thread
*
THREAD
;
InstanceKlass
*
_target
;
Symbol
*
_method_name
;
InstanceKlass
*
_method_holder
;
bool
_found_shadow
;
public:
ShadowChecker
(
Thread
*
thread
,
Symbol
*
name
,
InstanceKlass
*
holder
,
InstanceKlass
*
target
)
:
THREAD
(
thread
),
_method_name
(
name
),
_method_holder
(
holder
),
_target
(
target
),
_found_shadow
(
false
)
{}
void
*
new_node_data
(
InstanceKlass
*
cls
)
{
return
NULL
;
}
void
free_node_data
(
void
*
data
)
{
return
;
}
bool
visit
()
{
InstanceKlass
*
ik
=
current_class
();
if
(
ik
==
_target
&&
current_depth
()
==
1
)
{
return
false
;
// This was the specified super -- no need to search it
}
if
(
ik
==
_method_holder
||
ik
==
_target
)
{
// We found a path that should be examined to see if it shadows _method
if
(
path_has_shadow
())
{
_found_shadow
=
true
;
cancel_iteration
();
}
return
false
;
// no need to continue up hierarchy
}
return
true
;
}
virtual
bool
path_has_shadow
()
=
0
;
bool
found_shadow
()
{
return
_found_shadow
;
}
};
// Used for Invokespecial.
// Invokespecial is allowed to invoke a concrete interface method
// and can be used to disambuiguate among qualified candidates,
// which are methods in immediate superinterfaces,
// but may not be used to invoke a candidate that would be shadowed
// from the perspective of the caller.
// Invokespecial is also used in the overpass generation today
// We re-run the shadowchecker because we can't distinguish this case,
// but it should return the same answer, since the overpass target
// is now the invokespecial caller.
class
ErasedShadowChecker
:
public
ShadowChecker
{
private:
bool
path_has_shadow
()
{
for
(
int
i
=
current_depth
()
-
1
;
i
>
0
;
--
i
)
{
InstanceKlass
*
ik
=
class_at_depth
(
i
);
if
(
ik
->
is_interface
())
{
int
end
;
int
start
=
ik
->
find_method_by_name
(
_method_name
,
&
end
);
if
(
start
!=
-
1
)
{
return
true
;
}
}
}
return
false
;
}
public:
ErasedShadowChecker
(
Thread
*
thread
,
Symbol
*
name
,
InstanceKlass
*
holder
,
InstanceKlass
*
target
)
:
ShadowChecker
(
thread
,
name
,
holder
,
target
)
{}
};
// Find the unique qualified candidate from the perspective of the super_class
// which is the resolved_klass, which must be an immediate superinterface
// of klass
Method
*
find_erased_super_default
(
InstanceKlass
*
current_class
,
InstanceKlass
*
super_class
,
Symbol
*
method_name
,
Symbol
*
sig
,
TRAPS
)
{
FindMethodsByErasedSig
visitor
(
method_name
,
sig
);
visitor
.
run
(
super_class
);
// find candidates from resolved_klass
MethodFamily
*
family
;
visitor
.
get_discovered_family
(
&
family
);
if
(
family
!=
NULL
)
{
family
->
determine_target
(
current_class
,
CHECK_NULL
);
// get target from current_class
if
(
family
->
has_target
())
{
Method
*
target
=
family
->
get_selected_target
();
InstanceKlass
*
holder
=
InstanceKlass
::
cast
(
target
->
method_holder
());
// Verify that the identified method is valid from the context of
// the current class, which is the caller class for invokespecial
// link resolution, i.e. ensure there it is not shadowed.
// You can use invokespecial to disambiguate interface methods, but
// you can not use it to skip over an interface method that would shadow it.
ErasedShadowChecker
checker
(
THREAD
,
target
->
name
(),
holder
,
super_class
);
checker
.
run
(
current_class
);
if
(
checker
.
found_shadow
())
{
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
tty
->
print_cr
(
" Only candidate found was shadowed."
);
}
#endif // ndef PRODUCT
THROW_MSG_
(
vmSymbols
::
java_lang_AbstractMethodError
(),
"Accessible default method not found"
,
NULL
);
}
else
{
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
family
->
print_sig_on
(
tty
,
target
->
signature
(),
1
);
}
#endif // ndef PRODUCT
return
target
;
}
}
else
{
assert
(
family
->
throws_exception
(),
"must have target or throw"
);
THROW_MSG_
(
vmSymbols
::
java_lang_AbstractMethodError
(),
family
->
get_exception_message
()
->
as_C_string
(),
NULL
);
}
}
else
{
// no method found
ResourceMark
rm
(
THREAD
);
THROW_MSG_
(
vmSymbols
::
java_lang_NoSuchMethodError
(),
Method
::
name_and_sig_as_C_string
(
current_class
,
method_name
,
sig
),
NULL
);
}
}
// This is called during linktime when we find an invokespecial call that
// refers to a direct superinterface. It indicates that we should find the
// default method in the hierarchy of that superinterface, and if that method
// would have been a candidate from the point of view of 'this' class, then we
// return that method.
// This logic assumes that the super is a direct superclass of the caller
Method
*
DefaultMethods
::
find_super_default
(
Klass
*
cls
,
Klass
*
super
,
Symbol
*
method_name
,
Symbol
*
sig
,
TRAPS
)
{
ResourceMark
rm
(
THREAD
);
assert
(
cls
!=
NULL
&&
super
!=
NULL
,
"Need real classes"
);
InstanceKlass
*
current_class
=
InstanceKlass
::
cast
(
cls
);
InstanceKlass
*
super_class
=
InstanceKlass
::
cast
(
super
);
// Keep entire hierarchy alive for the duration of the computation
KeepAliveRegistrar
keepAlive
(
THREAD
);
KeepAliveVisitor
loadKeepAlive
(
&
keepAlive
);
loadKeepAlive
.
run
(
current_class
);
// get hierarchy from current class
#ifndef PRODUCT
if
(
TraceDefaultMethods
)
{
tty
->
print_cr
(
"Finding super default method %s.%s%s from %s"
,
super_class
->
name
()
->
as_C_string
(),
method_name
->
as_C_string
(),
sig
->
as_C_string
(),
current_class
->
name
()
->
as_C_string
());
}
#endif // ndef PRODUCT
assert
(
super_class
->
is_interface
(),
"only call for default methods"
);
Method
*
target
=
NULL
;
target
=
find_erased_super_default
(
current_class
,
super_class
,
method_name
,
sig
,
CHECK_NULL
);
#ifndef PRODUCT
if
(
target
!=
NULL
)
{
if
(
TraceDefaultMethods
)
{
tty
->
print
(
" Returning "
);
print_method
(
tty
,
target
,
true
);
tty
->
print_cr
(
""
);
}
}
#endif // ndef PRODUCT
return
target
;
}
#ifndef PRODUCT
// Return true is broad type is a covariant return of narrow type
...
...
@@ -1035,10 +851,9 @@ static int assemble_redirect(
return
parameter_count
;
}
static
int
assemble_
abstract_
method_error
(
BytecodeConstantPool
*
cp
,
BytecodeBuffer
*
buffer
,
Symbol
*
message
,
TRAPS
)
{
static
int
assemble_method_error
(
BytecodeConstantPool
*
cp
,
BytecodeBuffer
*
buffer
,
Symbol
*
errorName
,
Symbol
*
message
,
TRAPS
)
{
Symbol
*
errorName
=
vmSymbols
::
java_lang_AbstractMethodError
();
Symbol
*
init
=
vmSymbols
::
object_initializer_name
();
Symbol
*
sig
=
vmSymbols
::
string_void_signature
();
...
...
@@ -1150,8 +965,7 @@ static void create_overpasses(
&
bpool
,
&
buffer
,
slot
->
signature
(),
selected
,
CHECK
);
}
}
else
if
(
method
->
throws_exception
())
{
max_stack
=
assemble_abstract_method_error
(
&
bpool
,
&
buffer
,
method
->
get_exception_message
(),
CHECK
);
max_stack
=
assemble_method_error
(
&
bpool
,
&
buffer
,
method
->
get_exception_name
(),
method
->
get_exception_message
(),
CHECK
);
}
if
(
max_stack
!=
0
)
{
AccessFlags
flags
=
accessFlags_from
(
...
...
src/share/vm/classfile/defaultMethods.hpp
浏览文件 @
f2a7a11c
/*
* 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
...
...
@@ -44,15 +44,5 @@ class DefaultMethods : AllStatic {
// the class.
static
void
generate_default_methods
(
InstanceKlass
*
klass
,
GrowableArray
<
Method
*>*
mirandas
,
TRAPS
);
// Called during linking when an invokespecial to an direct interface
// method is found. Selects and returns a method if there is a unique
// default method in the 'super_iface' part of the hierarchy which is
// also a candidate default for 'this_klass'. Otherwise throws an AME.
static
Method
*
find_super_default
(
Klass
*
this_klass
,
Klass
*
super_iface
,
Symbol
*
method_name
,
Symbol
*
method_sig
,
TRAPS
);
};
#endif // SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
src/share/vm/interpreter/linkResolver.cpp
浏览文件 @
f2a7a11c
/*
* Copyright (c) 1997, 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
...
...
@@ -573,6 +572,16 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
}
if
(
check_access
)
{
// JDK8 adds non-public interface methods, and accessability check requirement
assert
(
current_klass
.
not_null
()
,
"current_klass should not be null"
);
// check if method can be accessed by the referring class
check_method_accessability
(
current_klass
,
resolved_klass
,
KlassHandle
(
THREAD
,
resolved_method
->
method_holder
()),
resolved_method
,
CHECK
);
HandleMark
hm
(
THREAD
);
Handle
loader
(
THREAD
,
InstanceKlass
::
cast
(
current_klass
())
->
class_loader
());
Handle
class_loader
(
THREAD
,
resolved_method
->
method_holder
()
->
class_loader
());
...
...
@@ -604,6 +613,20 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
}
}
}
if
(
TraceItables
&&
Verbose
)
{
ResourceMark
rm
(
THREAD
);
tty
->
print
(
"invokeinterface resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: "
,
(
current_klass
.
is_null
()
?
"<NULL>"
:
current_klass
->
internal_name
()),
(
resolved_klass
.
is_null
()
?
"<NULL>"
:
resolved_klass
->
internal_name
()),
Method
::
name_and_sig_as_C_string
(
resolved_klass
(),
resolved_method
->
name
(),
resolved_method
->
signature
()),
resolved_method
->
method_holder
()
->
internal_name
()
);
resolved_method
->
access_flags
().
print_on
(
tty
);
tty
->
cr
();
}
}
//------------------------------------------------------------------------------------------------------------------------
...
...
@@ -795,26 +818,12 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
Symbol
*
method_name
,
Symbol
*
method_signature
,
KlassHandle
current_klass
,
bool
check_access
,
TRAPS
)
{
if
(
resolved_klass
->
is_interface
()
&&
current_klass
()
!=
NULL
)
{
// If the target class is a direct interface, treat this as a "super"
// default call.
//
// If the current method is an overpass that happens to call a direct
// super-interface's method, then we'll end up rerunning the default method
// analysis even though we don't need to, but that's ok since it will end
// up with the same answer.
InstanceKlass
*
ik
=
InstanceKlass
::
cast
(
current_klass
());
Array
<
Klass
*>*
interfaces
=
ik
->
local_interfaces
();
int
num_interfaces
=
interfaces
->
length
();
for
(
int
index
=
0
;
index
<
num_interfaces
;
index
++
)
{
if
(
interfaces
->
at
(
index
)
==
resolved_klass
())
{
Method
*
method
=
DefaultMethods
::
find_super_default
(
current_klass
(),
resolved_klass
(),
method_name
,
method_signature
,
CHECK
);
resolved_method
=
methodHandle
(
THREAD
,
method
);
return
;
}
}
}
// Invokespecial is called for multiple special reasons:
// <init>
// local private method invocation, for classes and interfaces
// superclass.method, which can also resolve to a default method
// and the selected method is recalculated relative to the direct superclass
// superinterface.method, which explicitly does not check shadowing
resolve_method
(
resolved_method
,
resolved_klass
,
method_name
,
method_signature
,
current_klass
,
check_access
,
CHECK
);
...
...
@@ -844,6 +853,26 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
resolved_method
->
signature
()));
THROW_MSG
(
vmSymbols
::
java_lang_IncompatibleClassChangeError
(),
buf
);
}
if
(
TraceItables
&&
Verbose
)
{
ResourceMark
rm
(
THREAD
);
tty
->
print
(
"invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: "
,
(
current_klass
.
is_null
()
?
"<NULL>"
:
current_klass
->
internal_name
()),
(
resolved_klass
.
is_null
()
?
"<NULL>"
:
resolved_klass
->
internal_name
()),
Method
::
name_and_sig_as_C_string
(
resolved_klass
(),
resolved_method
->
name
(),
resolved_method
->
signature
()),
resolved_method
->
method_holder
()
->
internal_name
()
);
resolved_method
->
access_flags
().
print_on
(
tty
);
if
(
resolved_method
->
method_holder
()
->
is_interface
()
&&
!
resolved_method
->
is_abstract
())
{
tty
->
print
(
"default"
);
}
if
(
resolved_method
->
is_overpass
())
{
tty
->
print
(
"overpass"
);
}
tty
->
cr
();
}
}
// throws runtime exceptions
...
...
@@ -851,23 +880,24 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle
KlassHandle
current_klass
,
bool
check_access
,
TRAPS
)
{
// resolved method is selected method unless we have an old-style lookup
// for a superclass method
// Invokespecial for a superinterface, resolved method is selected method,
// no checks for shadowing
methodHandle
sel_method
(
THREAD
,
resolved_method
());
// check if this is an old-style super call and do a new lookup if so
{
KlassHandle
method_klass
=
KlassHandle
(
THREAD
,
resolved_method
->
method_holder
());
const
bool
direct_calling_default_method
=
resolved_klass
()
!=
NULL
&&
resolved_method
()
!=
NULL
&&
resolved_klass
->
is_interface
()
&&
!
resolved_method
->
is_abstract
();
if
(
!
direct_calling_default_method
&&
check_access
&&
if
(
check_access
&&
// a) check if ACC_SUPER flag is set for the current class
(
current_klass
->
is_super
()
||
!
AllowNonVirtualCalls
)
&&
// b) check if the method class is a superclass of the current class (superclass relation is not reflexive!)
current_klass
->
is_subtype_of
(
method_klass
())
&&
current_klass
()
!=
method_klass
()
&&
// b) check if the class of the resolved_klass is a superclass
// (not supertype in order to exclude interface classes) of the current class.
// This check is not performed for super.invoke for interface methods
// in super interfaces.
current_klass
->
is_subclass_of
(
resolved_klass
())
&&
current_klass
()
!=
resolved_klass
()
&&
// c) check if the method is not <init>
resolved_method
->
name
()
!=
vmSymbols
::
object_initializer_name
())
{
// Lookup super method
...
...
@@ -905,6 +935,23 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle
sel_method
->
signature
()));
}
if
(
TraceItables
&&
Verbose
)
{
ResourceMark
rm
(
THREAD
);
tty
->
print
(
"invokespecial selected method: resolved-class:%s, method:%s, method_holder:%s, access_flags: "
,
(
resolved_klass
.
is_null
()
?
"<NULL>"
:
resolved_klass
->
internal_name
()),
Method
::
name_and_sig_as_C_string
(
resolved_klass
(),
sel_method
->
name
(),
sel_method
->
signature
()),
sel_method
->
method_holder
()
->
internal_name
()
);
sel_method
->
access_flags
().
print_on
(
tty
);
if
(
sel_method
->
method_holder
()
->
is_interface
()
&&
!
sel_method
->
is_abstract
())
{
tty
->
print
(
"default"
);
}
tty
->
cr
();
}
// setup result
result
.
set_static
(
resolved_klass
,
sel_method
,
CHECK
);
}
...
...
@@ -927,6 +974,18 @@ void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method
assert
(
resolved_method
->
name
()
!=
vmSymbols
::
object_initializer_name
(),
"should have been checked in verifier"
);
assert
(
resolved_method
->
name
()
!=
vmSymbols
::
class_initializer_name
(),
"should have been checked in verifier"
);
// check if private interface method
if
(
resolved_klass
->
is_interface
()
&&
resolved_method
->
is_private
())
{
ResourceMark
rm
(
THREAD
);
char
buf
[
200
];
jio_snprintf
(
buf
,
sizeof
(
buf
),
"private interface method requires invokespecial, not invokevirtual: method %s, caller-class:%s"
,
Method
::
name_and_sig_as_C_string
(
resolved_klass
(),
resolved_method
->
name
(),
resolved_method
->
signature
()),
(
current_klass
.
is_null
()
?
"<NULL>"
:
current_klass
->
internal_name
()));
THROW_MSG
(
vmSymbols
::
java_lang_IncompatibleClassChangeError
(),
buf
);
}
// check if not static
if
(
resolved_method
->
is_static
())
{
ResourceMark
rm
(
THREAD
);
...
...
@@ -936,6 +995,27 @@ void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method
resolved_method
->
signature
()));
THROW_MSG
(
vmSymbols
::
java_lang_IncompatibleClassChangeError
(),
buf
);
}
if
(
PrintVtables
&&
Verbose
)
{
ResourceMark
rm
(
THREAD
);
tty
->
print
(
"invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: "
,
(
current_klass
.
is_null
()
?
"<NULL>"
:
current_klass
->
internal_name
()),
(
resolved_klass
.
is_null
()
?
"<NULL>"
:
resolved_klass
->
internal_name
()),
Method
::
name_and_sig_as_C_string
(
resolved_klass
(),
resolved_method
->
name
(),
resolved_method
->
signature
()),
resolved_method
->
method_holder
()
->
internal_name
()
);
resolved_method
->
access_flags
().
print_on
(
tty
);
if
(
resolved_method
->
method_holder
()
->
is_interface
()
&&
!
resolved_method
->
is_abstract
())
{
tty
->
print
(
"default"
);
}
if
(
resolved_method
->
is_overpass
())
{
tty
->
print
(
"overpass"
);
}
tty
->
cr
();
}
}
// throws runtime exceptions
...
...
@@ -1012,6 +1092,27 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
selected_method
->
signature
()));
}
if
(
PrintVtables
&&
Verbose
)
{
ResourceMark
rm
(
THREAD
);
tty
->
print
(
"invokevirtual selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, vtable_index:%d, access_flags: "
,
(
recv_klass
.
is_null
()
?
"<NULL>"
:
recv_klass
->
internal_name
()),
(
resolved_klass
.
is_null
()
?
"<NULL>"
:
resolved_klass
->
internal_name
()),
Method
::
name_and_sig_as_C_string
(
resolved_klass
(),
resolved_method
->
name
(),
resolved_method
->
signature
()),
selected_method
->
method_holder
()
->
internal_name
(),
vtable_index
);
selected_method
->
access_flags
().
print_on
(
tty
);
if
(
selected_method
->
method_holder
()
->
is_interface
()
&&
!
selected_method
->
is_abstract
())
{
tty
->
print
(
"default"
);
}
if
(
resolved_method
->
is_overpass
())
{
tty
->
print
(
"overpass"
);
}
tty
->
cr
();
}
// setup result
result
.
set_virtual
(
resolved_klass
,
recv_klass
,
resolved_method
,
selected_method
,
vtable_index
,
CHECK
);
}
...
...
@@ -1042,6 +1143,17 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
THROW
(
vmSymbols
::
java_lang_NullPointerException
());
}
// check if private interface method
if
(
resolved_klass
->
is_interface
()
&&
resolved_method
->
is_private
())
{
ResourceMark
rm
(
THREAD
);
char
buf
[
200
];
jio_snprintf
(
buf
,
sizeof
(
buf
),
"private interface method requires invokespecial, not invokeinterface: method %s"
,
Method
::
name_and_sig_as_C_string
(
resolved_klass
(),
resolved_method
->
name
(),
resolved_method
->
signature
()));
THROW_MSG
(
vmSymbols
::
java_lang_IncompatibleClassChangeError
(),
buf
);
}
// check if receiver klass implements the resolved interface
if
(
!
recv_klass
->
is_subtype_of
(
resolved_klass
()))
{
ResourceMark
rm
(
THREAD
);
...
...
@@ -1071,28 +1183,15 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
resolved_method
->
signature
()));
}
// check access
if
(
sel_method
->
method_holder
()
->
is_interface
())
{
// Method holder is an interface. Throw Illegal Access Error if sel_method
// is neither public nor private.
if
(
!
(
sel_method
->
is_public
()
||
sel_method
->
is_private
()))
{
ResourceMark
rm
(
THREAD
);
THROW_MSG
(
vmSymbols
::
java_lang_IllegalAccessError
(),
Method
::
name_and_sig_as_C_string
(
recv_klass
(),
sel_method
->
name
(),
sel_method
->
signature
()));
}
}
else
{
// Method holder is a class. Throw Illegal Access Error if sel_method
// is not public.
if
(
!
sel_method
->
is_public
())
{
ResourceMark
rm
(
THREAD
);
THROW_MSG
(
vmSymbols
::
java_lang_IllegalAccessError
(),
Method
::
name_and_sig_as_C_string
(
recv_klass
(),
sel_method
->
name
(),
sel_method
->
signature
()));
}
// Throw Illegal Access Error if sel_method is not public.
if
(
!
sel_method
->
is_public
())
{
ResourceMark
rm
(
THREAD
);
THROW_MSG
(
vmSymbols
::
java_lang_IllegalAccessError
(),
Method
::
name_and_sig_as_C_string
(
recv_klass
(),
sel_method
->
name
(),
sel_method
->
signature
()));
}
// check if abstract
if
(
check_null_and_abstract
&&
sel_method
->
is_abstract
())
{
ResourceMark
rm
(
THREAD
);
...
...
@@ -1109,6 +1208,27 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand
return
;
}
int
itable_index
=
resolved_method
()
->
itable_index
();
if
(
TraceItables
&&
Verbose
)
{
ResourceMark
rm
(
THREAD
);
tty
->
print
(
"invokeinterface selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, access_flags: "
,
(
recv_klass
.
is_null
()
?
"<NULL>"
:
recv_klass
->
internal_name
()),
(
resolved_klass
.
is_null
()
?
"<NULL>"
:
resolved_klass
->
internal_name
()),
Method
::
name_and_sig_as_C_string
(
resolved_klass
(),
resolved_method
->
name
(),
resolved_method
->
signature
()),
sel_method
->
method_holder
()
->
internal_name
()
);
sel_method
->
access_flags
().
print_on
(
tty
);
if
(
sel_method
->
method_holder
()
->
is_interface
()
&&
!
sel_method
->
is_abstract
())
{
tty
->
print
(
"default"
);
}
if
(
resolved_method
->
is_overpass
())
{
tty
->
print
(
"overpass"
);
}
tty
->
cr
();
}
result
.
set_interface
(
resolved_klass
,
recv_klass
,
resolved_method
,
sel_method
,
itable_index
,
CHECK
);
}
...
...
src/share/vm/oops/instanceKlass.cpp
浏览文件 @
f2a7a11c
...
...
@@ -1419,6 +1419,8 @@ Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) c
}
// lookup a method in all the interfaces that this class implements
// Do NOT return private or static methods, new in JDK8 which are not externally visible
// They should only be found in the initial InterfaceMethodRef
Method
*
InstanceKlass
::
lookup_method_in_all_interfaces
(
Symbol
*
name
,
Symbol
*
signature
)
const
{
Array
<
Klass
*>*
all_ifs
=
transitive_interfaces
();
...
...
@@ -1427,7 +1429,7 @@ Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name,
for
(
int
i
=
0
;
i
<
num_ifs
;
i
++
)
{
ik
=
InstanceKlass
::
cast
(
all_ifs
->
at
(
i
));
Method
*
m
=
ik
->
lookup_method
(
name
,
signature
);
if
(
m
!=
NULL
)
{
if
(
m
!=
NULL
&&
m
->
is_public
()
&&
!
m
->
is_static
()
)
{
return
m
;
}
}
...
...
src/share/vm/oops/klassVtable.cpp
浏览文件 @
f2a7a11c
...
...
@@ -292,9 +292,10 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
return
allocate_new
;
}
// private methods always have a new entry in the vtable
// private methods
in classes
always have a new entry in the vtable
// specification interpretation since classic has
// private methods not overriding
// JDK8 adds private methods in interfaces which require invokespecial
if
(
target_method
()
->
is_private
())
{
return
allocate_new
;
}
...
...
@@ -442,9 +443,10 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
return
true
;
}
// private methods always have a new entry in the vtable
// private methods
in classes
always have a new entry in the vtable
// specification interpretation since classic has
// private methods not overriding
// JDK8 adds private methods in interfaces which require invokespecial
if
(
target_method
()
->
is_private
())
{
return
true
;
}
...
...
@@ -520,7 +522,7 @@ bool klassVtable::is_miranda_entry_at(int i) {
Klass
*
method_holder
=
m
->
method_holder
();
InstanceKlass
*
mhk
=
InstanceKlass
::
cast
(
method_holder
);
// miranda methods are interface methods in a class's vtable
// miranda methods are
public abstract instance
interface methods in a class's vtable
if
(
mhk
->
is_interface
())
{
assert
(
m
->
is_public
(),
"should be public"
);
assert
(
ik
()
->
implements_interface
(
method_holder
)
,
"this class should implement the interface"
);
...
...
@@ -534,6 +536,8 @@ bool klassVtable::is_miranda_entry_at(int i) {
// "miranda" means not static, not defined by this class, and not defined
// in super unless it is private and therefore inaccessible to this class.
// the caller must make sure that the method belongs to an interface implemented by the class
// Miranda methods only include public interface instance methods
// Not private methods, not static methods, not default = concrete abstract
bool
klassVtable
::
is_miranda
(
Method
*
m
,
Array
<
Method
*>*
class_methods
,
Klass
*
super
)
{
if
(
m
->
is_static
())
{
return
false
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录