sdad分析:
sdad①、Java中是能正常编译的,但运行会出现NegativeArraySizeException
异常,《Java虚拟机规范》中规定是一个运行时异常。
sdad②、C中直接在编译期报错。
sdad总结:一门语言的哪一种检查行为要在运行期进行,哪一种检查要在编译期进行并没有什么必然的因果逻辑关系。
===========================================================================
背景介绍:
sdad 目前已经有许多动态类型语言运行于Java虚拟机之上了,如Clojure、Groovy、Jython和JRuby等,也就是说我们可以在JVM上实现静态类语言的严谨与动态类型语言的灵活。
sd ad但是JDK7以前,JVM层面对动态类型语言的支持一直都还有所欠缺,主要表现在方法调用方面,只有4条方法调用指令(invokevirtual、invokespecial、invokestatic、invokeinterface),且它们的第一个参数(操作数)都是被调用的方法的符号引用(CONSTANT_Methodref_info或者CONSTANT_InterfaceMethodref_info常量)。
sda
sdad这时就有一个问题:方法的符号引用在编译时产生,而动态类型语言只有在运行期才能确定方法的接收者。
sda
sdad那怎么解决这个问题的呢?
sda
sdad ①、曲线救国:比如编译时留个占位符类型,运行时动态生成字节码实现具体类型到占位符类型的适配。但是这样有两个缺点:
sdaadⅠ、让动态类型语言实现的复杂度增加,也会带来额外的性能和内存开销sdadⅡ、由于无法确定调用对象的静态类型,而导致的方法内联无法有效进行。
sda
sdaad基于以上背景,在JVM层面上提供动态类型的直接支持就成为Java平台发展必须解决的问题,直到JDK 7,JSR-292提出了invokedynamic
指令以及java.lang.invoke
包解决了此问题。
sdad这个包的主要目的:在之前单纯依靠符号引用来确定调用的目标方法这条路之外,提供一种新的动态确定目标方法的机制,称为“方法句柄”(Method Handle)。
sda
sdad**[注]:** 在Java语言中做不到像C那样,单独把一个函数作为参数(函数指针的功劳)进行传递。普遍的做法是设计一个带有compare()方法的Comparator接口,以实现这个接口的对象作为参数。比如void sort(List list, Comparator c)
。
sda
sdad不过在有了方法句柄之后,Java语言就可以像C那样,拥有类似于函数指针或者委托的方法别名这样的工具了。
sasdasdsad
sasdasdsadsadsadsadasdasdasdasdsadsadsaasddad方法句柄演示
import static java.lang.invoke.MethodHandles.lookup;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
public class MethodHandleTest {
static class ClassA {
public void println(String s) {
System.out.println(s);
}
}
public static void main(String[] args) throws Throwable {
Object obj = System.currentTimeMillis() % 2 == 0 ? System.out : new ClassA();
// 无论obj最终是哪个实现类,下面这句都能正确调用到println方法。
getPrintlnMH(obj).invokeExact("icyfenix");
}
private static MethodHandle getPrintlnMH(Object reveiver) throws Throwable {
// MethodType:代表“方法类型”,包含了方法的返回值(methodType()的第一个参数)
//和具体参数(methodType()第二个及以后的参数)。
MethodType mt = MethodType.methodType(void.class, String.class); //pritln的返回值、以及具体参数
/*lookup()方法来自于MethodHandles.lookup,这句的作用是在指定类中查找(符合给定的方法名称、
方法类型,并且符合调用权限的)方法句柄。
因为这里调用的是一个虚方法,按照Java语言的规则,方法第一个参数是隐式的,代表该方法的接收者,
也即this指向的对象,这个参数以前是放在参数列表中进行传递,现在提供了bindTo()方法来完成这件事情。
*/
return lookup().findVirtual(reveiver.getClass(), "println",mt).bindTo(reveiver);//方法类型、名称、即返回值和参数
}
}
方法解析:
sdad方法getPrintlnMH()中实际上是模拟了invokevirtual指令的执行过程,只不过它的分派逻辑并非固化在Class文件的字节码上,而是通过一个由用户设计的Java方法来实现。而这个方法本身的返回值(MethodHandle对象),可以视为对最终调用方法的一个“引用”。
sdad我们再次回顾sort()方法,有了MethodHandle就可以写出类似于C/C++那样的函数声明了:
sdasdasdasdasdsadasdsadasdasdasdasadvoid sort(List list, MethodHandle compare)
到此,我们发现MethodHandle在使用方法和效果上与Reflection有众多相似之处。但是它们也有 很大的区别:
sasad①、Reflection和MethodHandle机制本质上都是在模拟方法调用。但是Reflection是在模拟Java代码层次的方法调用,而MethodHandle是在模拟字节码层次的方法调用。在MethodHandles.Lookup上的3个方法findStatic()、findVirtual()、findSpecial()正是为了对应于invokestatic、invokevirtual(以及invokeinterface)和invokespecial这几条字节码指令的执行权限校验行为,而这些底层细节在使用Reflection API时是不需要关心的。
sasad②、Reflection中的java.lang.reflect.Method对象远比MethodHandle机制中的java.lang.invoke.MethodHandle对象所包含的信息来得多。
ssadasdasad前者是方法在Java端的全面映像,包含了方法的签名、描述符以及方法属性表中各种属性的Java端表示方式,还包含执行权限等的运行期信息。
ssadasdasad后者仅包含执行该方法的相关信息。
sasad③、Reflection API的设计目标是只为Java语言服务的,而MethodHandle则设计为可服务于所有Java虚拟机之上的语言。
sasad总之,Reflection是重量级,而MethodHandle是轻量级。
sasad[注]:由于MethodHandle是对字节码的方法指令调用的模拟,那理论上虚拟机在这方面做的各种优化(如方法内联),在MethodHandle上也应当可以采用类似思路去支持(但目前实现还在继续完善中),而通过反射去调用方法则几乎不可能直接去实施各类调用点优化措施。
sdasdasdasda
invokedynamic指令与MethodHandle方法的对比:
sdasdasdasda
sdaa相同点:某种意义上可以说invokedynamic指令与MethodHandle机制的作用是一样的,都是为了解决原有4条“invoke*”指令方法分派规则完全固化在虚拟机之中的问题,把如何查找目标方法的决定权从虚拟机转嫁到具体用户代码之中,让用户(广义的用户,包含其他程序语言的设计者)有更高的自由度。
sdasdasdasda
sdaa不同点:invokedynamic指令用字节码和Class中其他属性、常量来完成。MethodHandle是用上层代码和API来实现。
sdasdasdasda
sdaa**[注]:** 每一处含有invokedynamic指令的位置都被称作"动态调用点"。这条指令的第一个参数(操作数)不再是代表方法符号引用的CONSTANT_Methodref_info常量,而是变为JDK 7时新加入的CONSTANT_InvokeDynamic_info常量,从这个新常量中可以得到3项信息:
sdsdasaa①、引导方法(Bootstrap Method,该方法存放在新增的 BootstrapMethods属性中)②、方法类型 ③、名称
sdaa引导方法是有固定的参数,并且返回值规定是java.lang.invoke.CallSite对象,这个对象代表了真正要执行的目标方法调用。根据CONSTANT_InvokeDynamic_info常量中提供的信息,虚拟机可以找到并且执行引导方法,从而获得一个CallSite对象,最终调用到要执行的目标方法上。
sasdasdsad
sasdasdsadsadsadsadasdasdasdassaasddad InvokeDynamic指令演示
import static java.lang.invoke.MethodHandles.lookup;
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class InvokeDynamicTest {
public static void main(String[] args) throws Throwable {
INDY_BootstrapMethod().invokeExact("icyfenix");
}
public static void testMethod(String s) {
System.out.println("hello String:" + s);
# Spring全套教学资料
**Spring是Java程序员的《葵花宝典》,其中提供的各种大招,能简化我们的开发,大大提升开发效率!目前99%的公司使用了Spring,大家可以去各大招聘网站看一下,Spring算是必备技能,所以一定要掌握。**
**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](https://codechina.csdn.net/m0_60958482/java-p7)**
**目录:**
![](https://img-blog.csdnimg.cn/img_convert/93bac8bd0b4d91c7e171bdb57ba0258e.png)
![](https://img-blog.csdnimg.cn/img_convert/cfb9a2dfd763ebdb944782c1e6cff471.png)
**部分内容:**
![](https://img-blog.csdnimg.cn/img_convert/e38488e69d6b833b0075ceea0d47f398.png)
![](https://img-blog.csdnimg.cn/img_convert/f0e8f64d27939beeba970066007817b5.png)
# Spring源码
* 第一部分 Spring 概述
* 第二部分 核心思想
* 第三部分 手写实现 IoC 和 AOP(自定义Spring框架)
* 第四部分 Spring IOC 高级应用
基础特性
高级特性
* 第五部分 Spring IOC源码深度剖析
设计优雅
设计模式
注意:原则、方法和技巧
* 第六部分 Spring AOP 应用
声明事务控制
* 第七部分 Spring AOP源码深度剖析
必要的笔记、必要的图、通俗易懂的语言化解知识难点
![](https://img-blog.csdnimg.cn/img_convert/f2657c16c4fa6a41b1ca5a6dde7edced.png)
![](https://img-blog.csdnimg.cn/img_convert/68a7e593782c3c05d84d318e10f44c39.png)
# 脚手框架:SpringBoot技术
> 它的目标是简化Spring应用和服务的创建、开发与部署,简化了配置文件,使用嵌入式web服务器,含有诸多开箱即用的微服务功能,可以和spring cloud联合部署。
>
> Spring Boot的核心思想是约定大于配置,应用只需要很少的配置即可,简化了应用开发模式。
* SpringBoot入门
* 配置文件
* 日志
* Web开发
* Docker
* SpringBoot与数据访问
* 启动配置原理
* 自定义starter
![](https://img-blog.csdnimg.cn/img_convert/0f21fe89662766127ab0d53852e44c16.png)
![](https://img-blog.csdnimg.cn/img_convert/450bc9acfa2709f65e8b1bdab10fa6a0.png)
# 微服务架构:Spring Cloud Alibaba
> 同 Spring Cloud 一样,Spring Cloud Alibaba 也是一套微服务解决方案,包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
* 微服务架构介绍
* Spring Cloud Alibaba介绍
* 微服务环境搭建
* 服务治理
* 服务容错
* 服务网关
* 链路追踪
* ZipKin集成及数据持久化
* 消息驱动
* 短信服务
* Nacos Confifig—服务配置
* Seata—分布式事务
* Dubbo—rpc通信
![](https://img-blog.csdnimg.cn/img_convert/0462d0145314139a4d16517aacc10552.png)
![](https://img-blog.csdnimg.cn/img_convert/0d3eed462286a9a528bb7755363b03a5.png)
# Spring MVC
**目录:**
![](https://img-blog.csdnimg.cn/img_convert/8aa8efef8a9d7669bf439a41864140c4.png)
![](https://img-blog.csdnimg.cn/img_convert/429068be9259d4f69aa3867694a2d6bb.png)
![](https://img-blog.csdnimg.cn/img_convert/29fef5bb2e6f2deb2bc57fd1d79df02b.png)
**部分内容:**
![](https://img-blog.csdnimg.cn/img_convert/c0534a001500f7e02db13103f69fe93d.png)
![](https://img-blog.csdnimg.cn/img_convert/50d51a0519c41aef9586366e5f0b24b4.png)
..(img-Vc0XojDs-1630937128251)]
[外链图片转存中...(img-znu6f1Jy-1630937128252)]
# Spring MVC
**目录:**
[外链图片转存中...(img-baDezoEc-1630937128253)]
[外链图片转存中...(img-vct3uhI4-1630937128253)]
[外链图片转存中...(img-GC8MXdiz-1630937128254)]
**部分内容:**
[外链图片转存中...(img-iuRG5W1X-1630937128255)]
[外链图片转存中...(img-D7oIR0BP-1630937128255)]