反编译
# 终端进行反编译,执行
javap -v .\Test.class
堆、栈
- 在JVM中,栈是运行的单位,堆是存储的单位。
- 栈解决程序运行问题,即程序如何执行,或者说如何处理数据,堆解决的是数据存储的问题,即数据怎么放,放在哪。
- 每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的java方法调用。是线程私有的,生命周期和线程一致。
- 虚拟机栈主管Java程序的运行,它保存方法的局部变量(8种数据类型,对象的引用地址),部分结果,并参与方法的调用和返回。
- 栈是先进后出,就像手枪弹夹,先放进去的子弹后被打出,最后放进去的子弹,先被打出。
- 栈遵循先进后出,后进先出的原则
栈空间大小设置
可以使用参数-Xss来设置线程的最大栈空间,栈的大小直接决定了函数调用的最大可达深度。
以KB为单位设置大小,就要在数字后边加上K或k,如:
-Xss1024K
以MB为单位设置大小,就要在数字后边加上M或m,如:
-Xss1024m
以GB为单位设置大小,就要在数字后边加上G或g,如:
-Xss1G
栈的内部结构
每个栈帧中存储着:
局部变量表(Local variables)
- 定义为一个数据数组,主要是用于存储方法参数和定义在方法体内的局部变量
- 这些数据类型包括各类基本数据类型,对象引用,以及returnAddress类型
- 局部变量表中存放编译期克制的各种基本数据类型(8种
- 局部变量表,最基本的存储单元是slot(变量槽)
- 局部变量表中变量也是中要的垃圾回收根节点,主要被局部变量表中直接或间接引用的对象都不会被回收。
操作数栈(Operand Stack)(或表达式栈)
动态链接(Dynamic Linking)(或指向运行时常量池的方法引用)
- 每一个栈帧内部都包含一个指向 运行时常量池中该栈帧所属方法的引用。
方法返回地址(Return Address)(或方法正常退出或者异常退出的定义)
虚方法和非虚方法
非虚方法
如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的,这样的方法称为非虚方法。
静态方法,私有方法,final方法,实例构造器,父类方法都是非虚方法。
其他方法称为虚方法。
- 方法的调用 在JVM中,将符号引用转换为调用方法的直接饮用与方法的绑定机制有关。
静态链接
- 当一个字节码文件被装载进JVM内部时,如果被调用的目标方法在编译期克制,切运行期保持不变时。这种情况下将调用方法的符号引用转换为直接引用的过程城之后静态链接。
动态链接
- 如果被调用的方法在编译期无法被确定下来, 也就是说只能够在程序运行期将调用方法的符号引用转换为直接引用,由于这种医用在转换过程具备动态性,因此也就城之后动态链接。 对应的方法绑定机制为早起绑定和晚期绑定。绑定是一个字段,方法或者类在符号引用被替换为直接引用的过程,这仅仅发生一次。
早期绑定:
- 早期绑定就是指被调用的目标方法如果在编译期可知,却运行期保持不变时,即可将这个方法与所属的类型进行绑定,这样一来,由于明确了被调用的目标方法究竟是哪一个,因此也就可以使用静态链接的方法将符号引用转换为直接引用。
晚期绑定:
- 如果被调用的方法在编译期无法被确定下来,只能在程序运行期根据实际的类型绑定相关的方法,这种绑定放在也就被称之为晚期绑定。 就比如方法参数传了一个父类或者接口,必须在真正运行的时候才能确定是哪一个子类进行操作,这就属于晚期绑定。
本地方法栈
- Java虚拟机栈适用于管理Java方法的调用,而本地方法栈是用于管理本地方法的调用。
- 本地方法
- **本地方法(Native Method)就是一个Java调用非Java代码的接口。**本地方法的实现是由飞Java语言实现,比如c,这个特征并非Java所特有。很多其他变成语言都有这一机制。
- 在定义一个Native Method时,并不提供实现体(像是定义一个Java interface的方法),因为实现体是由非Java语言在外边实现的。
- 在Object中的getClass就是一个本地方法。