ujvm内存
Java的Jvm内存可以分为三个区:堆区,栈区,方法区
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class信息,class的目的是得到操作指令;
2.Jvm只有一个堆区被所有线程共享,堆中不存放基本数据类型和对象引用,只存放对象本身。
栈区:
1.栈中只保存最基本数据类写的对象和自定义对象的引用(非对象),对象都存在堆区
2.每个栈区中的数据(原始类型和对象引用)都是私有,其他栈无法引用访问;
3.栈区为3个部分:基本类型变量区,执行环境上下文,操作指令区;
方法区:
1.方法区又叫做静态区,和堆一样,被所有线程共享,方法去包含所有的class和static变量
2.方法去包含的都是再整个过程中永远唯一的元素,如:class,static变量;
方法的调用
静态链接:当一个字节码文件被装载进 JVM 内部时,如果被调用的目标方法在编译期可知,且运行时期间保持不变,这种情况下将调用方的符号引用转为直接引用的过程称为静态链接。
动态链接:如果被调用的方法无法在编译期被确定下来,只能在运行期将调用的方法的符号引用转为直接引用,这种引用转换过程具备动态性,因此被称为动态链接。
方法绑定
早期绑定:被调用的目标方法如果在编译期可知,且运行期保持不变。
晚期绑定:被调用的方法在编译期无法被确定,只能够在程序运行期根据实际的类型绑定相关的方法。
非虚方法:
如果方法在编译期就确定了具体的调用版本,则这个版本在运行时是不可变的,这样的方法称为非虚方法静态方法。私有方法,final 方法,实例构造器,父类方法都是非虚方法,除了这些以外都是虚方法。
虚方法表:
面向对象的编程中,会很频繁的使用动态分配,如果每次动态分配的过程都要重新在类的方法元数据中搜索合适的目标的话,就可能影响到执行效率,因此为了提高性能,JVM 采用在类的方法区建立一个虚方法表,使用索引表来代替查找。
每个类都有一个虚方法表,表中存放着各个方法的实际入口。
虚方法表会在类加载的链接阶段被创建,并开始初始化,类的变量初始值准备完成之后,JVM 会把该类的方法也初始化完毕。
方法重写的本质
找到操作数栈顶的第一个元素所执行的对象的实际类型,记做 C。如果在类型 C 中找到与常量池中描述符和简单名称都相符的方法,则进行访问权限校验。
如果通过则返回这个方法的直接引用,查找过程结束;如果不通过,则返回 java.lang.IllegalAccessError 异常。
否则,按照继承关系从下往上依次对 C 的各个父类进行上一步的搜索和验证过程。
如果始终没有找到合适的方法,则抛出 java.lang.AbstractMethodError 异常。
Java 中任何一个普通方法都具备虚函数的特征(运行期确认,具备晚期绑定的特点),C++ 中则使用关键字 virtual 来显式定义。如果在 Java 程序中,不希望某个方法拥有虚函数的特征,则可以使用关键字 final 来标记这个方法。
Java 虚拟机栈的特点
-
运行速度特别快,仅仅次于 PC 寄存器。
-
局部变量表随着栈帧的创建而创建,它的大小在编译时确定,创建时只需分配事先规定的大小即可。在方法运行过程中,局部变量表的大小不会发生改变。
-
Java 虚拟机栈会出现两种异常:StackOverFlowError 和 OutOfMemoryError。
StackOverFlowError 若 Java 虚拟机栈的大小不允许动态扩展,那么当线程请求栈的深度超过当前 Java 虚拟机栈的最大深度时,抛出 StackOverFlowError 异常。
OutOfMemoryError 若允许动态扩展,那么当线程请求栈时内存用完了,无法再动态扩展时,抛出 OutOfMemoryError 异常。
Java 虚拟机栈也是线程私有,随着线程创建而创建,随着线程的结束而销毁。
-
出现 StackOverFlowError 时,内存空间可能还有很多。
常见的运行时异常有:
-
NullPointerException - 空指针引用异常
-
ClassCastException - 类型强制转换异
-
IllegalArgumentException - 传递非法参数异常
-
ArithmeticException - 算术运算异常
-
ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
-
IndexOutOfBoundsException - 下标越界异常
-
NegativeArraySizeException - 创建一个大小为负数的数组错误异常
-
NumberFormatException - 数字格式异常
-
SecurityException - 安全异常
-
UnsupportedOperationException - 不支持的操作异常
方法区
1、方法区的定义
Java 虚拟机规范中定义方法区是堆的一个逻辑部分。方法区存放以下信息:
已经被虚拟机加载的类信息
常量
静态变量
即时编译器编译后的代码
2、方法区的特点
线程共享。方法区是堆的一个逻辑部分,因此和堆一样,都是线程共享的。整个虚拟机中只有一个方法区。
永久代。方法区中的信息一般需要长期存在,而且它又是堆的逻辑分区,因此用堆的划分方法,把方法区称为“永久代”。
内存回收效率低。方法区中的信息一般需要长期存在,回收一遍之后可能只有少量信息无效。主要回收目标是:对常量池的回收;对类型的卸载。
Java 虚拟机规范对方法区的要求比较宽松。和堆一样,允许固定大小,也允许动态扩展,还允许不实现垃圾回收。
3、运行时常量池
方法区中存放:类信息、常量、静态变量、即时编译器编译后的代码。常量就存放在运行时常量池中。
当类被 Java 虚拟机加载后, .class 文件中的常量就存放在方法区的运行时常量池中。而且在运行期间,可以向常量池中添加新的常量。如 String 类的 intern() 方法就能在运行期间向常量池中添加字符串常量。
本文采摘于网络,不代表本站立场,转载联系作者并注明出处:https://www.iotsj.com//kuaixun/3201.html