java - JVM invokeinterface without type information -
i'm generating code java asm5 , wondering, why can invoke interface method on parameter, declared of type java/lang/object.
methodvisitor mv = cw.visitmethod(acc_public | acc_static, "test", "(ljava/lang/object;)v", null, null); mv.visitvarinsn(aload, 0); mv.visitinsn(dup); mv.visitmethodinsn(invokeinterface, "org/mydomain/foo", "foo", "()v", true); mv.visitmethodinsn(invokeinterface, "org/mydomain/bar", "bar", "()v", true); mv.visitinsn(return); mv.visitmaxs(-1,-1); mv.visitend();
generally have expected code require additional cast before invoking method ensure, object implements interface. safe call method without additional cast, long guarantee object implements interface or can run pitfalls? type checking of vm doesn't seem care it. if invoke object, doesn't implement interface java.lang.incompatibleclasschangeerror, not surprising. maybe have performance loss?
you encountered known sloppiness of hotspot’s verifier, not verify type compatibility of receiver types invokeinterface
calls. not imply such code formally correct.
jvmspec, §4.9.2 structural constraints states:
- the type of every class instance target of method invocation instruction must assignment compatible class or interface type specified in instruction (jls §5.2).
however, there practical problem verifying constraint statically verifiers of older jvms following algorithm called “verification type inference” , still standard class files having version below 50. this answer explains issue. if 2 different reference types have merged after branches, may result in common super type not implementing interface while both types do. rejecting subsequent invokeinterface
call lead in rejecting correct code.
starting version 50, there “verification type checking”, mandatory versions higher 50. uses stackmap tables, explicitly declaring supposed result of type merging, eliminating expensive operations. consequently, “verification type checking” has formal rules mandate static type compatible interface type:
invokeinterface
an invokeinterface instruction type safe iff of following conditions hold:
…
- one can validly replace types matching type
methodintfname
, argument types given indescriptor
on incoming operand stack return type given indescriptor
, yielding outgoing type state.
(note these rules identical the rules of invokevirtual
instruction, except uses methodintfname
instead of methodclassname
)
as side note, code correct in environment java/lang/object
happens implement both, org/mydomain/foo
, org/mydomain/bar
. it’s verification against actual environment missing here.
to put straight, code happens work on hotspot due missing check, not portable, i.e. may fail on other jvms , may fail on future versions of hotspot, type checking rules enforced.
there no performance advantage in omitting checkcast
, there check 1 way or other , throwable thrown if type doesn’t match. therefore, stick creating formally correct code, if particular jvm not enforce it.
Comments
Post a Comment