ClassNotFoundException 和 NoClassDefFoundError 等异常 。
对于任意一个类 , 都需要由它的类加载器和这个类本身一同确定其在 JVM 中的唯一性 。 也就是说 , 如果两个类的加载器不同 , 即使两个类来源于同一个字节码文件 , 那这两个类就必定不相等(比如两个类的 Class 对象不 equals) 。
是不是有点晕 , 来来来 , 通过一段简单的代码了解下 。
每个Java 类都维护着一个指向定义它的类加载器的引用 , 通过 类名.class.getClassLoader() 可以获取到此引用;然后通过 loader.getParent() 可以获取类加载器的上层类加载器 。
上面这段代码的输出结果如下:
第一行输出为 Test 的类加载器 , 即应用类加载器 , 它是 sun.misc.Launcher$AppClassLoader 类的实例;第二行输出为扩展类加载器 , 是 sun.misc.Launcher$ExtClassLoader 类的实例 。 那启动类加载器呢?
按理说 , 扩展类加载器的上层类加载器是启动类加载器 , 但在我这个版本的 JDK 中 ,扩展类加载器的 getParent() 返回 null 。 所以没有输出 。
2)运行时数据区
运行时数据区又包含以下内容:
- PC寄存器(PC Register) , 也叫程序计数器(Program Counter Register) , 是一块较小的内存空间 , 它的作用可以看做是当前线程所执行的字节码的信号指示器 。
- JVM 栈(Java Virtual Machine Stack) , 与 PC 寄存器一样 , JVM 栈也是线程私有的 。 每一个 JVM 线程都有自己的 JVM 栈 , 这个栈与线程同时创建 , 它的生命周期与线程相同 。
- 本地方法栈(Native Method Stack) , JVM 可能会使用到传统的栈来支持 Native 方法(使用 Java 语言以外的其它语言[C语言]编写的方法)的执行 , 这个栈就是本地方法栈 。
- 堆(Heap) , 在 JVM 中 , 堆是可供各条线程共享的运行时内存区域 , 也是供所有类实例和数据对象分配内存的区域 。
- 方法区(Method area) , 在 JVM 中 , 被加载类型的信息都保存在方法区中 。 包括类型信息(Type Information)和方法列表(Method Tables) 。 方法区是所有线程共享的 , 所以访问方法区信息的方法必须是线程安全的 。
- 运行时常量池(Runtime Constant Pool) , 运行时常量池是每一个类或接口的常量池在运行时的表现形式 , 它包括了编译器可知的数值字面量 , 以及运行期解析后才能获得的方法或字段的引用 。 简而言之 , 当一个方法或者变量被引用时 , JVM 通过运行时常量区来查找方法或者变量在内存里的实际地址 。
执行引擎包含了:
- 解释器:读取字节码流 , 然后执行指令 。 因为它一条一条地解释和执行指令 , 所以它可以很快地解释字节码 , 但是执行起来会比较慢 。
- 即时(Just-In-Time , JIT)编译器:即时编译器用来弥补解释器的缺点 , 提高性能 。 执行引擎首先按照解释执行的方式来执行 , 然后在合适的时候 , 即时编译器把整段字节码编译成本地代码 。 然后 , 执行引擎就没有必要再去解释执行方法了 , 它可以直接通过本地代码去执行 。 执行本地代码比一条一条进行解释执行的速度快很多 。 编译后的代码可以执行的很快 , 因为本地代码是保存在缓存里的 。
- 本文转自:新民晚报在这段日子里医务工作者们坚守在抗疫一线在核酸检测工作量激增的同时物资需...|8000人社区封控后,“黑科技”来帮忙!无人车精准
- iPhone|荣耀Magic4和小米12对比:哪一款更值得入手?
- 本文转自:中国新闻网新冠一体化核酸检测盒。|20个硬核项目现场对接 “黑科技”赋能成都大运会
- 打着小米的旗号卖产品,深圳“小米”被告了,赔了3000万
- 固态硬盘|首创SSD塞进手机!曝小米商城将开启黑鲨5预售:骁龙8游戏旗舰
- 欧洲市场小米正式“接棒”华为,谁也没想到,一切来得这么快
- 本文转自:上观为有效阻断疫情传播链|封闭管理,这家汽车电子高科技企业生产有序
- 人工智能作为新一轮科技革命和产业革命的重要驱动力量|2022人工智能教育蓝皮书:现状、挑战与发展建议
- 网易云音乐|团队超1000人,2024年上市:小米汽车团队进步这么大!
- 3月24日消息|耗资超4000万!小米集团宣布:回购340.94万股股票