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. Understanding String Table Size in HotSpot

    In JDK-6962930[2], it requested that string table size be configurable.  The resolved date of that b ...

  2. DI延伸

    延迟初始化Bean 延迟初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean. 配置方式很简单只需在<bean>标签上指定 “lazy-init” 属 ...

  3. [毕业设计][期末作业]二手闲置小程序 免费信息发布系统功能源码(小程序+php后台管理)

    最近做了一个小程序,主要是二手闲置免费信息发布系统的功能,里面包括了登录,发布商品,商品管理,违规投诉,canva商品海报生成,分享等一些基础的功能,可以说代码都是自己辛辛苦苦写出来的.可作为毕业设计 ...

  4. session概要

    一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况 下).因此,在需要保存用户数据时,服 ...

  5. [Erlang30]Erlang shell是如何工作的?

    一些关于Erlang启动进程的分析:希望你会喜欢. 原英文地址:http://ferd.ca/repl-a-bit-more-and-less-than-that.html 研究Erlang shel ...

  6. c# HighCharts使用

    最近接到个图形报表的需求,网络上找了几个插件,最后决定用highcharts 需要的文件 1.bll文件,添加到项目引用   http://files.cnblogs.com/files/loveju ...

  7. 配置sql server 允许远程连接

    如果要想远程连接数据库那么则需要在一个局域网中或一个路由器中才可以做到 接下来就是具体的操作检查sqlserver数据库是否允许远程连接 具体操作为 (1)打开数据库,用本地帐户登录,右击第一个选项, ...

  8. C#实现像微信PC版一样的扫码登录功能

    现在好些网站都支持扫码登录,感觉上安全了很多,但是本地程序扫码登录的不多,就用C#实现了一下,需要作如下准备 在官网上申请一个企业微信,有条件的话做个企业认证吧,我们的是认证过的,所以账号和本地其他系 ...

  9. leetcode 有效的括号

    给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: - 左括号必须用相同类型的右括号闭合. - 左括号必须以正确的顺序闭合. 注意空字符 ...

  10. HTTP Error 502.5 - Process Failure Win10 VS可以正常访问,部署本地IIS报错

    最近本core得升级导致各种问题,之前刚解决了server2012的502.5问题 今天本机又出现这个问题. 情况描述:VS可以正常调试查看,部署本地IIS访问 错误502.5 分析:VS可以使用II ...