文章目录

  • 导读
  • 导读的解读
  • 类加载器深入剖析
    • Java虚拟机结束生命周期的时机
    • 加载
    • 链接
    • 初始化
    • 使用
    • 卸载
  • Java程序对类的使用方式
    • 主动使用
    • 被动使用
    • 加载`.class`文件的方式
  • 应当注意的点

导读

在Java代码中,类型的加载、链接与初始化过程都是程序运行期间完成的。类加载给程序提供了更大的灵活性。

导读的解读

  • 运行的时候,我们往往就是直接点击编译器的运行按钮;而C、C++则是先点击编译,再点击运行。所以类似C、C++这类语言就是在程序运行之前的编译期间完成,而Java则是在运行期间完成。

  • 这里的类型是特指一些类,而不是对象,比如我们一开始所写的public class HelloWorld,这个HelloWorld就是这里所指的类其中一种情况

  • 还有一种情况就是动态代理。在动态代理中获得生成类的增强类,也会加载、链接、初始化。

类加载器深入剖析

顾名思义,类加载器就是用于加载类的工具。首先先来了解一下Java虚拟机的结束时间。

Java虚拟机结束生命周期的时机

  • 执行了System.exit()方法

  • 程序正常执行结束

  • 程序在执行过程中遇到了异常或错误而终止

    异常或错误会被Java虚拟机在当前位置一直向上抛出。但是如果没有什么机制接住异常的话,将会一直抛出到main方法中,最后因为无法处理而终止。

  • 由于操作系统出现错误而导致Java虚拟机进程终止 (不可控,所以不展开讨论)

加载

类的加载过程是“查找并加载类的二进制数据”,也就是生成字节码,并将字节码放入内存中

jdk1.7以及以前的版本会将这些放入运行时数据区的方法区内,而jdk8添加了原空间来存放这些字节码。接着在内存中创建唯一一个java.lang.Class对象用于封装方法区内的数据结构

这正是反射机制的源头。不觉得“是什么”慢慢填补了之后“为什么”也就迎刃而解了吗?

但是规范中并没有规定这些Class对象应该位于哪里,Oracle的HotSpot虚拟机导师把这些放在了方法区内。这倒不是什么重点。

虽说这些字节码是编译器自动生成的,但是这些字节码可以被人为修改,所以在链接之前将会在后续阶段中好好地验证一遍。

链接

  • 验证:确保被加载类的正确性(验证字节码)

  • 准备:为类的静态变量分配内存,将其初始化为默认值。

    需要强调的是,这里的默认值是编译器定义的默认值。也就是说,在加载这个类的时候,将会给类内的静态变量分配一个内存空间,而这个变量立马就被规定为默认值。比如int类型将会获得数字“0”等等。

  • 解析:将类中的符号引用转换为直接引用

初始化

在连接完成后,为类的静态变量赋予正确的初始值。举个例子:

public static int a = 1;

链接阶段的准备工作,a被赋予了数字“0”,但是在连接完成后的初始化阶段中,将会重新将a赋值为“1”。

使用

也就是正常的调用等等操作,包括访问、修改和删除等等。

卸载

将类的字节码从内存中删除,这样就不能继续使用这个类了,需要时可以重新加载到内存中。平时使用场景非常少。

Java程序对类的使用方式

使用方式可以分为两种,主动使用被动使用

所有的Java虚拟机实现必须在每个类或接口被程序“首次主动使用”时才初始化他们。

而什么是“首次主动使用”?就是只有在第一次主动使用的时候初始化。

主动使用

  • 创建类的实例(new

  • 访问某个类或者接口的静态变量,或者对该静态变量赋值

  • 调用类的静态方法

  • 反射

  • 初始化一个类的子类(子类被创建的时候,所有的父类都会被创建)

  • Java虚拟机启动时被标名为启动类的类

  • 动态语言支持(从jdk1.7开始支持)

被动使用

除了上述七种情况,其他的所有情况都是类的被动使用,也就不会导致类的初始化。

加载.class文件的方式

由于JVM规范并没有规定我们一定要从哪里加载这些.class文件,所以我们甚至可以加载不在本地的文件。这也正是为什么我们可以往我们的项目中添加jar包,也正是Spring框架中的Maven如此好用的原因。

所以有很多种方法可以加载:

  • 从本地系统中直接加载

  • 通过网络下载.class文件

  • 从zip、jar等归档文件中加载.class文件

  • 从专有数据库中提取.class文件(用的极少)

  • 将Java源文件动态编译为.class文件

    • 动态代理

    • jsp在运行期间会被转换成servlet,最终会被编译成.class文件

应当注意的点

  • 主动使用

    • 对于静态字段来说,只有直接定义了该字段的类才会被初始化

      也就是说子类如果是从父类继承得到了静态变量而不是直接在子类内部定义的话,调用子类继承而得的静态变量时子类不会被初始化。

    • 当一个类在初始化时,要求其父类全部都初始化完毕才开始执行初始化

所以,Java在实际运行中将会占用非常大的内存,这对于吞吐量极大的项目来说并不是一个好的选择,这也正是为什么腾讯和bilibili都正在逐渐使用Go重写整个系统。

不过,即使Java依然在性能上有着无法反驳的劣势,却在生态上有着无可撼动的地位。基于Spring Cloud的微服务框架能够集成RabbitMQRedisZuulConsul等一切企业级信息管理框架所需要的内容,再加上基于Spring Boot的模块可以使用yml轻松集成,如此强大的生态已经成为了Java立于不败之地的重要因素。不仅如此,在面对海量的并发控制和请求处理的时候,可以使用非常多的服务器并联处理,做到了物理意义上的“三个臭皮匠,顶个诸葛亮”。这也是为什么Java依然能够在运行内存占用非常高的情况下依然保持这么高的支持率的原因之一。也正因为高支持率,才有了强大的社区和丰富的库。这就是一个良性循环了。

当然,随着微服务、RPC协议、RESTful接口规范等的提出,单个模块中使用什么语言逐渐变得不再重要了。只对外暴露输入和输出接口屏蔽了中间过程的一切实现,已经成为了现在开发的主流。每个模块是选择开发效率更高的语言,或者是选择执行效率更高的语言,就看每个公司的追求了。所以,也无所谓Java还是Go的抉择,只要适合该企业,能够在该企业的要求时间内完成所有内容,并且该企业有足够的资金维护该系统,那么使用该语言就是合适的。

是不是有点能理解了呢?

有关JVM类加载器的一点点想法相关推荐

  1. Java高并发编程详解系列-JVM类加载器

    之前的博客中提到了类加载的过程,提到了双亲委托机制,提到了关于类加载器的概念,这篇博客就来给大家分享一下什么是JVM的类加载器.通过实战的方式来了解一下类加载器器到底是什么. JVM类加载器分类    ...

  2. 《Java虚拟机原理图解》5. JVM类加载器机制与类加载过程

    参考网址:http://blog.csdn.net/luanlouis/article/details/50529868 0.前言 读完本文,你将了解到: 一.为什么说Jabalpur语言是跨平台的 ...

  3. 彻底搞懂JVM类加载器:基本概念

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 阿杜的世界 来源 | javaadu 在Java面试中,在考察完项目经验.基础技术 ...

  4. jvm:类加载器与双亲委派模型

    两个类相等需要类本身相等,并且使用同一个类加载器进行加载.这是因为每一个类加载器都拥有一个独立的类名称空间. 这里的相等,包括类的 Class 对象的 equals() 方法.isAssignable ...

  5. jvm类加载器以及双亲委派

    首先来了解几个概念: 类加载: 概念:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验--转换解析--初始化,最终形成能被java虚拟机直接使用的java类型,就是jvm的类加载机制. ...

  6. jvm运行时类加载机制_JVM体系结构:JVM类加载器和运行时数据区

    jvm运行时类加载机制 各位读者好! 在JVM系列的上一篇文章中,开发人员了解了Java虚拟机(JVM)及其体系结构. 本教程将帮助开发人员正确回答以下主题的问题: ClassLoader子系统 运行 ...

  7. JVM体系结构:JVM类加载器和运行时数据区

    各位读者好! 在JVM系列的上一篇文章中,开发人员了解了Java虚拟机(JVM)及其体系结构. 本教程将帮助开发人员正确回答以下主题的问题: ClassLoader子系统 运行时数据区 1.简介 在继 ...

  8. JVM 类加载器(引导类加载器、扩展类加载器、系统类加载器、用户自定义类加载器)

    1 引导类加载器 引导类加载器(Boostrap ClassLoader),又叫启动类加载器. 由C/C++语言实现,嵌套在JVM内部. 用来加载 Java 的核心库(JAVA_HOME/jre/li ...

  9. 22-09-02 西安 JVM 类加载器、栈、堆体系、堆参数调优、GC垃圾判定、垃圾回收算法、对象的finalize机制

    这篇文章不少地方都截图了宋红康老师的课件,实在他jvm这块讲的真好.连接地址如下: 尚硅谷宋红康JVM全套教程(详解java虚拟机)_哔哩哔哩_bilibili JVM入门 1.JVM结构图 JVM是 ...

最新文章

  1. Overleaf-LaTex表格制作
  2. 第 1 章 虚拟化 - 013 - 动手实践 Linux VLAN
  3. SpringBoot配置Mybatis在控制台打印sql
  4. 【论文解读】A Survey on Visual Transformer及引文理解
  5. Django购物网站使用说明
  6. Shell 脚本知识回顾 (四) —— Shell 命令及Shell 相关语句
  7. CSU 1111 三家人
  8. 小米10官宣首发骁龙865,小米6“钉子户”可以考虑换机了
  9. MySql中的变量定义
  10. SQLSERVER的视图、函数、存储过程、触发器
  11. 解决:My97DatePicker 日期插件引用在PHP文件中maxDate和minDate控制失效问题
  12. 马云:大部分失败企业都是因为不够专注
  13. Linux下建立MySQL数据库,并安装RMySQL包,报错及解决
  14. ROS机器人语音交互(一)
  15. 单片机是什么?51单片机和stm32有什么区别?
  16. 京东到家搜索系统架构演进
  17. 微信发送图文消息,查看图文media_id
  18. 【中危】Sweet32: TLS 64位分组密码生日攻击(CVE-2016-2183)
  19. 基于矢量的水下路由协议
  20. 【Posts阅读】关于 Deep Sets 和 Neural Processes的简单介绍

热门文章

  1. C++ 标准模板库 STL 容器适配器
  2. token系列2—解析(解码)及实际应用
  3. 【论文笔记】DARDet: A Dense Anchor-free Rotated Object Detector in Aerial Images
  4. python bs4标签中含有标签string为空
  5. 余子式与代数余子式的辨析应用
  6. 星舆科技又双叒叕获奖了!雷锋网年度最佳高精度定位奖
  7. 联合高德推AR实景导航,OPPO手机的又一差异化策略
  8. 主成分分析法(PCA)的理解(附python代码案例)
  9. 棋牌软件被恶意攻击应该怎么办
  10. Waiting (TTFB)