1、关于<init>与<clinit>

At the level of the Java Virtual Machine, every constructor written in the Java programming language (JLS §8.8) appears as an instance initialization method that has the special name <init>. This name is supplied by a compiler. Because the name <init> is not a valid identifier, it cannot be used directly in a program written in the Java programming language. Instance initialization methods may be invoked only within the Java Virtual Machine by the invokespecial instruction (§invokespecial), and they may be invoked only on uninitialized class instances. An instance initialization method takes on the access permissions (JLS §6.6) of the constructor from which it was derived.

A class or interface has at most one class or interface initialization method and is initialized (§5.5) by invoking that method. The initialization method of a class or interface has the special name <clinit>, takes no arguments, and is void (§4.3.3).

<clinit>  在jvm第一次加载class文件时调用,包括静态变量初始化语句和静态块的执行

Other methods named <clinit> in a class file are of no consequence. They are not class or interface initialization methods. They cannot be invoked by any Java Virtual Machine instruction and are never invoked by the Java Virtual Machine itself.

In a class file whose version number is 51.0 or above, the method must additionally have its ACC_STATIC flag (§4.6) set in order to be the class or interface initialization method.

This requirement is new in Java SE 7. In a class file whose version number is 50.0 or below, a method named <clinit> that is void and takes no arguments is considered the class or interface initialization method regardless of the setting of its ACC_STATIC flag.

The name <clinit> is supplied by a compiler. Because the name <clinit> is not a valid identifier, it cannot be used directly in a program written in the Java programming language. Class and interface initialization methods are invoked implicitly by the Java Virtual Machine; they are never invoked directly from any Java Virtual Machine instruction, but are invoked only indirectly as part of the class initialization process.

接口中有<clinit>方法,其owner,也就是所属的symbol为java.lang.Object

2、关于invoke与invokeExact

A method is signature polymorphic if and only if all of the following conditions hold:

  • It is declared in the java.lang.invoke.MethodHandle class.
  • It has a single formal parameter of type Object[].
  • It has a return type of Object.
  • It has the ACC_VARARGS and ACC_NATIVE flags set.

In Java SE 7, the only signature polymorphic methods are the invoke and invokeExact methods of the class java.lang.invoke.MethodHandle.

invoke()与invokeExact()方法的定义在MethodHandle类中,如下:

public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable;

public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;

  

The Java Virtual Machine gives special treatment to signature polymorphic methods in the invokevirtual instruction (§invokevirtual), in order to effect invocation of a method handle. A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation (§5.4.3.5), with optional transformations of arguments or return values. These transformations are quite general, and include such patterns as conversion, insertion, deletion, and substitution. See the java.lang.invoke package in the Java SE platform API for more information.

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class MethodHandleTest {
    public static void main(String[] args) throws Throwable {

        /*
         * Lookup相当于MethodHandle工厂类,通过findxxx方法可以得到相应的
         * MethodHandle,还可以配合反射API创建MethodHandle,对应的方法
         * 有unreflect、unreflectSpecial等
         */
        MethodHandles.Lookup lookup = MethodHandles.lookup();

        /*
         * 调用MethodType的静态方法创建MethodType实例,有三种创建方式:
         * (1)methodType及其重载方法:需要指定返回值类型以及0到多个参数
         * (2)genericMethodType:需要指定参数的个数,类型都为Object
         * (3)fromMethodDescriptorString:通过方法描述来创建
         * 创建好MethodType对象后,还可以对其进行修改,MethodType类中提
         * 供了一系列的修改方法,比如:
         * changeParameterType、changeReturnType等
         */
        MethodType methodType = MethodType.methodType(int.class, int.class);
        MethodHandle handle = lookup.findStatic(MethodHandleTest.class,
        		                               "doubleVal", methodType);

        /*
         * (1)invokeExact:调用此方法与直接调用底层方法一样,需要做到参数类型精确匹配
         *
         * (2)invoke:nvoke方法允许更加松散的调用方式。它会尝试在调用的时候进行返回值
         * 和参数类型的转换工作。这是通过MethodHandle类的asType方法来完成的,
         * asType方法的作用是把当前方法句柄适配到新的MethodType上面,并产生一个新的方法句柄。
         * 当方法句柄在调用时的类型与其声明的类型完全一致的时候,调用invoke方法等于调用
         * invokeExact方法;否则,invoke方法会先调用asType方法来尝试适配到调用时
         * 的类型。如果适配成功,则可以继续调用。否则会抛出相关的异常。这种灵活的适配机制,
         * 使invoke方法成为在绝大多数情况下都应该使用的方法句柄调用方式。
         *
         * (3)invokeWithArguments:直接通过方法参数来调用。
         * 其实现是先通过genericMethodType方法得到MethodType,再通过MethodHandle的
         * asType转换后得到一个新的MethodHandle,最后通过新MethodHandle的
         * invokeExact方法来完成调用。
         */
        Integer temp = (Integer) handle.invoke(2);
        System.out.println(temp); // 4

    }

    public static int doubleVal(int val) {
        return val * 2;
    }
}

关于invoke()与invokeExact()方法:

  • The types of its parameters are the static types of the actual argument expressions.

    An argument expression which is the null literal null(§3.10.7) is treated as having the static type Void.

  • The result type is determined as follows:

    • If the method invocation expression is an expression statement, the method is void.

    • Otherwise, if the method invocation expression is the operand of a cast expression (§15.16), the return type is the erasure (§4.6) of the type of the cast expression.

    • Otherwise, the return type is the method's declared return type, Object.

再看一个例子,如下:

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class MethodHandleTest {

	public MethodHandle getHandler_print() {
		MethodHandle mh = null;
		MethodType mt = MethodType.methodType(void.class);
		MethodHandles.Lookup lk = MethodHandles.lookup();

		try {
			mh = lk.findVirtual(MethodHandleTest.class, "print", mt);
		} catch (Throwable e) {
			e.printStackTrace();
		}

		return mh;
	}

	public MethodHandle getHandler_substring() {
		MethodHandle mh = null;
		MethodType mt = MethodType.methodType(String.class, int.class, int.class);
		MethodHandles.Lookup lk = MethodHandles.lookup();

		try {
			mh = lk.findVirtual(String.class, "substring", mt);
		} catch (Throwable e) {
			e.printStackTrace();
		}

		return mh;
	}

	public void test_substring() throws Throwable {
		MethodHandle mh = new MethodHandleTest().getHandler_substring();
		String str = "hello world";

		Object result1 = mh.invoke(str, 1, 3);
		Object result2 = (String) mh.invokeExact(str, 1, 3);
		// 方法执行时报错,因为方法返回的类型为Object,与声明中为String不符合
		// Object result3 = mh.invokeExact(str, 1, 3);
		// 第二个参数类型为Integer,与声明中为int不符合,则类型适配不符合,系统报错
		// Object result4 = (String)mh.invokeExact(str, new Integer(1), 3);

		System.out.println("result 1:" + result1);
		System.out.println("result 1:" + result2);

	}

	public void test_print() throws Throwable {
		MethodHandleTest mht = new MethodHandleTest();
		MethodHandle mh = mht.getHandler_print();

		int result5 = (int) mh.invoke(mht);
		Object result6 = mh.invoke(mht);

		System.out.println("result 5:" + result5);
		System.out.println("result 6:" + result6);
	}

	public static void main(String[] args) throws Throwable {
		MethodHandleTest m = new MethodHandleTest();
		m.test_substring();
		m.test_print();
	}

	public void print() {
		System.out.println("invoke print");
	}
}
class Test{

	// e.g 1

	// a variable arity parameter,Otherwise,it is a fixed arity method
	// b 的英文叫法为 a variable arity parameter
	public int m1(final int a[][],int ...b)[][]{
		return a;
	}

	// e.g 2 如下m2方法不能共存

	public  static final void m2(List list){

	}

	public void m2(List<String> list) {

	}	

}

3、Miranda Method

In early VM's there was a bug -- the VM didn't walk the interfaces
of a class looking for a method, they only walked the superclass
chain. This meant that abstract methods defined only in interfaces
were not being found. To fix this bug, a counter-bug was introduced
in the compiler -- the so-called Miranda methods. If a class
does not provide a definition for an abstract method in one of
its interfaces then the compiler inserts one in the class artificially.
That way the VM didn't have to bother looking at the interfaces.

This is a problem. Miranda methods are not part of the specification.
But they continue to be inserted so that old VM's can run new code.
Someday, when the old VM's are gone, perhaps classes can be compiled
without Miranda methods. Towards this end, the compiler has a
flag, -nomiranda, which can turn off the creation of these methods.
Eventually that behavior should become the default.

Why are they called Miranda methods? Well the sentence "If the
class is not able to provide a method, then one will be provided
by the compiler" is very similar to the sentence "If you cannot
afford an attorney, one will be provided by the court," -- one
of the so-called "Miranda" rights in the United States.

参考文章:

(1)https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandle.html

  

java7之Special Methods的更多相关文章

  1. Python Special Methods - 特殊方法

    特殊方法 特殊方法的存在是为了给 Python 解释器调用的,通常自己并不需要直接调用它们.也就是说不应该使用 my_object.__len__() 这种写法,而应该使用 len(my_object ...

  2. 关于Class的invokeDynamic指令

    (1)java7之Special Methods (2)invokedynamic指令 https://www.cnblogs.com/wade-luffy/p/6058087.html public ...

  3. Effective Java 54 Use native methods judiciously

    Java Native Interface(JNI) allows Java applications to call native methods, which are special method ...

  4. Think Python - Chapter 17 - Classes and methods

    17.1 Object-oriented featuresPython is an object-oriented programming language, which means that it ...

  5. Overview over available Turtle and Screen methods

    24.5.2.1. Turtle methods Turtle motion Move and draw forward() | fd() backward() | bk() | back() rig ...

  6. Python中的"Special Method"

    The first thing to know about special methods is that they are meant to be called by the Python inte ...

  7. 对特殊方法的访问 - Special method lookup

    对特殊方法的访问 - Special method lookup 对于用户自定义的 class 来说, 特殊方法只有通过定义对象的类型object’s type (而非通过 instance 的 __ ...

  8. Chapter 7 -- Functional

    Caveats 说明 As of Java 7, functional programming in Java can only be approximated through awkward and ...

  9. .NET平台开源项目速览(13)机器学习组件Accord.NET框架功能介绍

    Accord.NET Framework是在AForge.NET项目的基础上封装和进一步开发而来.因为AForge.NET更注重与一些底层和广度,而Accord.NET Framework更注重与机器 ...

随机推荐

  1. Image 和byte[]之间的转换

    1.Image 转 byte[] public byte[] GetByteByImage(Image image) { byte[] bt = null; try { if (!image.Equa ...

  2. HRBUST1315 火影忍者之~大战之后 2017-03-06 16:14 54人阅读 评论(0) 收藏

    火影忍者之-大战之后 经历了大战的木叶村现在急需重建,人手又少,所以需要尽可能多的接受外来的任务,以赚取报酬,重建村庄,假设你现在是木叶的一名高级忍者,有一大堆的任务等着你来做,但毕竟个人时间有限,所 ...

  3. How To Make A DFF Read Only Through Form Personalisations? (文档 ID 1289789.1)

    In this Document   Goal   Solution   References APPLIES TO: Oracle Application Object Library - Vers ...

  4. 自我介绍和Github的初次体验

    姓名:袁宇鹏    学号:1413042045    班级:网络工程142    兴趣爱好:篮球,看书 写过的代码:用C++写过,只能算是看看这源程序修改. 没有开发过任何程序 Github使用流程: ...

  5. [c# 20问] 1. 何时使用class与struct

    POINTS struct为可以包含数据和函数的值类型 struct为值类型所以不需要堆(heap)而是在栈(stack)上分配空间 struct将数据直接存在struct中,而class只存引用类型 ...

  6. MVC中控制器向视图传值的四种方式

    MVC中的控制器向视图传值有四种方式分别是 1 ViewDate  2.ViewBag   3.TempDate  4.Model 下面分别介绍四种传值方式 首先先显示出控制器中的代码 using S ...

  7. 开源应用框架BitAdminCore:更新日志20180903

    索引 NET Core应用框架之BitAdminCore框架应用篇系列 框架演示:https://www.bitadmincore.com 框架源码:https://github.com/chenyi ...

  8. 知识记录——Session与Cookie

    Session: Session是“会话”的意思,然而,因为http协议是无状态的,那么每次客户端请求服务器端,服务器端都会以“崭新”的页面展示给客户端,这在静态的html页面中是不会存在任何影响,但 ...

  9. 【OCP-12c】CUUG 071题库考试原题及答案解析(16)

    16.(7-5) choose the best answerThe PRODUCTS table has the following structure:Evaluate the following ...

  10. memcache内存存储

    memcache的内存分配默认是采用了Slab Allocator的机制分配.管理内存.在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的. 但是,这种方式会导致内存 ...