Java丨JVM虚拟机与类加载器

2023-11-16

一丶JVM 虚拟机介绍;

  •  Sun HotSpot VM

这个目前看起来“血统纯正”的虚拟机在最初并非由Sun公司开发,而是由一家名为“Longview Technologies” 的小公
司设计的;甚至这个虚拟机最初并非是为Java语言而开发的,它来源于Strongtalk VM,而这款虚拟机中相当多的技术
又是来源于一款支 持Self语言实现“达到C语言50%以上的执行效率”的目标而设计的虚拟机,Sun公司注意到了 这款虚
拟机在JIT编译上有许多优秀的理念和实际效果,在1997年收购了Longvi ew Technologies公司,从而获得了HotSpot VM。

 

  • BEA JRockit VM

JRockit VM曾经号称“世界上速度最快的JAVA 虚拟机”它是BEA公司在2002年从Appeal Virtual Machines 公司收
购的虚拟机。BEA公司将其发展为一款专门为服务器硬件和服务器端应用场景高度优化的虚拟机,由于专注于服务器端
应用,它可以不太关注程序启动速度,因此JRockit内部不包含解析器实现,全部代码都靠即时编译器译后执行。除此
之外,JRocki t的垃圾收集器和MissionControl服务套件等部分的实现,在众多JAVA虚拟机中也一直处于领先水平。

 

  • IBM J9 VM

IBM J9 VM并不是IBM公司唯一的JAVA虚拟机,不过是目前其主力发展的JAVA虚拟机。IBM J9 VM原本是内部开
发代号,正式名称是“IBM Technology for Java Virtual Machine” ,它最早是由IBM Ottawa 实验室-一个
SmallTalk的虚拟机扩展来的。那时候,这个虚拟机有一个bug是因为8K值定义错误引起,工程师们花了很长时间
终于发现并解决了这个错误,此后这个版本的虚拟机就被称为K8了。于是,后来出现的支持Java这个版本的虚拟机
就被称为J9了。J9市场定位与HotSpot比较接近,从服务器到桌面应用再到嵌入式都全面考虑的多用途虚拟机。

 

  • 其他

 

 

 

二丶JVM 运行时数据区结构;

 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都
各司其职,以及创建和销毁的时间,在《Java虚拟机规范(Java SE 8版)》的规定中,Java虛拟机
所管理的内存包括五大部分区域:分别是程序计数器、虚拟机栈、本地方法栈、堆和方法区。

PS:我们把程序代码抽象一下, 可以理解为由三个部分组成,分别是数据、指令、控制流,所谓数据,可以理解为定义的成员变量,静态变量,常量;指令理解为在方法中执行的语句,控制流理解为分支、循环、跳转、异常处理、线程恢复等。我们在编写代码的过程中,可以理解为都是围绕着这三部分来展开组织代码的。

程序计数器是一-块较小的内存空间,指的是当前线程所执行的字节码的行号指示器。这是比较官方的解释,通俗一-点来说,首先程序计数器是与线程绑定的,也就是说每个线程在运行期都有独立的程序计数器,在上图中也可以看出,程序计数器是属于线程隔离的数据区。我们在学习Java多线程的时候讲过,多线程是通过线程间切换抢夺CPU分配的时间片来竞争执行的(多核CPU来说指的是-一个内核),一个CPU处理器只会在同- -时间执行一条线程指令。

举个例子,有两个线程A和B,当A线程获取到运行时间并执行到一半时,CPU分配的时间片用完了,此时A线程就要被挂起,然后两个线程再次竞争下一-次的CPU时间片,因此A线程就需要-一个计数器来记录上次执行的位置,好让下次再获取到CPU时间片时可以恢复到正确位置继续执行下去。各个线程之间的计数器是独立的,互不影响,独立存储,如果线程在执行一个方法时,此线程记录的是正在执行的字节码指令的地址,如果执行的是本地(Native)方法,则计数器的值为空(undefined),由于程序计数器的内存空间非常小,所以JVM规范中没有规定此区域的内存溢出的情况。

 

虚拟机栈
Java虚拟机栈也是线程独立的,多个线程有独立的Java虚拟机栈,栈的生命周期与线程相同,在线程启动时被创建,线程结束时被销毁,栈是用来存储Java方法运行时数据的,那栈中存储的数据是什么方式来组织的呢?其实在栈中存储的数据结构是一个数据单位来体现的,这个数据单位称为栈帧(Stack Frame),当程序执行一个方法时,会创建-一个栈帧,我们称为入栈,当方法执行结束后,栈帧就会被销毁,我们称为出栈。在一个栈帧里,用于存储局部变量表、操作数栈、动态链接、方法出口和一些额的附加信息。也许你会跟我一样,栈帧里的这些东东是什么鬼?不要捉急,下面我们将详细介绍运行时栈帧的结构。
栈帧是虚拟机在方法调用执行时存储在虚拟机栈的数据结构,也可以称为栈元素,一个方法对应一个栈帧,一个栈帧概念结构如图所示。

 

本地方法栈;

本地方法栈(Native Method Stack) 与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机机行Java方法(字节码)服务,而本地方法栈则为虚拟机便用到的Native方法服务。

在虚拟机规范中对本地方法栈中方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机(Sun Hotspot)直接把本地方法栈和虚拟机栈合二为- - 。与虚拟机栈- -样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异 常。
 

Java堆;

Java堆(Java Heap) 是Java虛拟机所管理的内存中最大的一块。Java堆是被所有线程和共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一- 目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。

这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致--些微妙的变化发生,所有的对象都分配在堆上也渐渐变得不是那么“绝对”了。
 

方法区;

方法区(Method Area)与Java堆一 样, 是所有线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。Java虛拟机规范把方法区描述为堆的一个逻辑部分,但方法区有一个别名叫做非堆(Non-Heap),目的是与Java堆区分开来。
 

Java程序中堆和堆栈内存结构示例

  • 一旦我们运行这个程序,它就会将所有的运行时类加载到堆空间中。在第1行找到main()方法时,Java运行时将创建供main()方法线程使用的堆栈内存。

 

  • 我们正在第2行创建原始本地变量,因此它被创建并存储在main ()方法的堆栈内存中。

 

  • 因为我们正在第3行中创建.一个对象,所以它是在堆内存中创建的,堆栈内存包含对它的引用。在第4行创建内存对象时也会发生类似的过程。

 

  • 现在,当我们在第5行调用foo()方法时,将创建堆栈顶部的一个块, 用于foo()方法。由于Java是通过值传递的,所以在第6行的foo()堆栈块中创建了一个新的对象引用。

 

  • 第7行创建了一个字符串,它进入堆空间中的字符串池,并在foo ()堆栈空间中为它创建一-个引用。

 

  • foo()方法在第8行终止,此时堆栈中为foo ()分配的内存块变为空闲。

 

  • 在第9行中,main() 方法终止,并销毁为main()方法创建的堆栈内存。程序在这一行结束,因此Java运行时释放所有内存并结束程序的执行。

 

Java程序中堆和堆栈内存结构示例
 

Java堆内部结构

1、Young (年轻代)大多数情况下JAVA程序中创建的对象是从新生代分配内存,新生代有两部分组成: Eden Space和两块大小相等的Survivor Space (S0和S1)。可以通过参数-Xmn来指定新生代的大小,通过XX: SurivorRatio来指定Eden Space和
Survivor Space的大小。


2、Tenured (年老代)年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。


3、Perm (持久代)用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等, 在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过XX :MaxPermSize=进行设置。
 

●新生区
●新生区是类的诞生、成长、消亡的区域,-一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分:伊甸区(Eden space) 和幸存者区(Survivor pace),所有的类都是在伊甸区被new出来的。幸存区有两个: 0区(Survivor 0 space) 和1区(Survivor 1 space) 。当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园进行垃圾回收(MinorGC),将伊甸园中的剩余对象移动到幸存0区。若幸存0区也满了,再对该区进行垃圾回收,然后移动到1区。那如果1去也满了呢?再移动到养老区。若养老区也满了,那么这个时候将产生Major GC(Fu11GC),进行养老区的内存清理。若养老区执行Ful1GC之后发现依然无法进行对象的保存,就会产生00M异常“OutOfMemoryError”。


●如果出现java. lang. OutOfMemoryError: Java heap space异常,说明Java虛拟机的堆内存不够。
原因有二:
a. Java虚 拟机的堆内存设置不够,可以通过参数Xms、Xmx来 调整。
b.代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。

 

●养老区
养老区用于保存从新生区筛选出来的JAVA对象,--般池对象都在这个区域活跃。


●永久区
永久存储区是一个常驻内存区域,用于存放JDK自身所携带的Class, Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占用的内存。如果出现java. lang. OutOfMemoryError: PermGen space, 说明是Java虛拟机对永久代Perm内存设置不够。
原因有二:
a.程序启动需要加载大量的第三方jar包。例如:在一-个Tomcat下部署了太多的应用。
b.大量动态反射生成的类不断被加载,最终导致Perm区被占满。
说明: 
Jdk1. 6及之前:常量池分配在永久代。
Jdk1. 7:有,但已经逐步“去永久代”。
Jdk1.8及之后:无(java. lang. OutOfMemoryError: PermGen space, 这种错误将不会出现在JDK1.8中)。
 

永久代(PermGen) 和元空间的区别(Metaspace )
类的元数据,字符串池,类的静态变量将会从永久代移除,放入Java heap或者native memory。 其中建议JVM的实现中将类的元数据放入native memory, 将字符串池和类的静态变量放入Java堆中。这样可以加载多少类的元数据就不在由MaxPermSize控制,而由系统的实际可用空间来控制。为什么这么做,呢?减少00M只 是表因,更深层的原因还是要合并HotSpot和JRockit的代码,JRockit从来没有 一个叫永久代的东西,但是运行良好,也不需要开发运维人员设置这么一个永久代的大小。
 

小结;

高级程序员了解虚拟机运行时数据区是必备技能,在现代程序复杂度、重量级、效率化的需求下,程序不单单是要求能运行,运行性能、效率的需求尤为重要。
程序员和高级程序员的区别?
●程序员可以按需求实现功能
●高级程序员不光要实现功能,更要考虑程序的性能、健壮、可扩展
JVM运行时数据区的五大模块:
●程序计数器
●虚拟机栈
●本地虚拟机栈
●方法区
●堆

 

三、类加载器;

 类加载器的分类
Java提供以下三种系统类加载器:
1、启动类加载器( Bootstrap ClassLoader引导类加载器)
2、扩展类加载器( Extension ClassLoader )
3、应用程序类加载器(Application ClassLoader)也称为系统类加载器

1) 启动类加载器( Bootstrap ClassLoader引导类加载器),这个类负责将放在<JAVA_ HOME>\lib目录下, 并且是虚拟机识别的(仅仅按照文件名识别,名字不符合的类库即使在lib目录下也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用,如果要把加载请求委派给启动类加载器,那就直接用null代替即可。
2) 扩展类加载器( Extension ClassLoader)负责加载<JAVA_ HOME>\lib\ext目 录下的类库
3) 应用程序类加载器(Application ClassLoader)也称为系统类加载器,负责加载用户类路径上所指定的类库,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。通俗的来讲: - -般情况下,我们自己写的类是由这个加载器加载。
 

JVM类加载工作原理:就是把类的class文件加载到内存中,并对数据进行校验、转换解析和初始化,最终形成被虛拟机使用的java类型。
类加载的生命周期包括以下几个部分:加载(Loading) 、验证(Verification) 、准备(Preparation) 、解析( Resolution) 、初始化(Initialization) 、使用(Using) 、卸载(Unloading) ,其中验证、准备、解析三个部分统称链接。
 

 

 

 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java丨JVM虚拟机与类加载器 的相关文章

  • 如何降低圈复杂度?

    我正在开发一个将 RequestDTO 发送到 Web 服务的类 我需要在发送请求之前验证该请求 请求可以从 3 个不同的地方发送 并且每个 请求类型 有不同的验证规则 例如请求1必须有姓名和电话号码 请求2必须有地址等 我有一个 DTO
  • 在 Tomcat 上部署 Java Web 项目,无需 WAR 或 EAR

    我有一个 Java Web 项目 Struts Spring 在我的本地主机上完美运行 我必须将其部署在我的网站上 但虚拟主机提供的 Tomcat Manager 界面显示 由于安全原因 它无法上传 WAR 文件 当联系技术支持时 我被告知
  • 如何在数据库中对 (Java) 枚举进行建模(使用 SQL92)

    您好 我正在使用名为 性别 的列对实体进行建模 在应用程序代码中 性别应该是一个 Java 枚举类型 有 2 个值 男性和女性 知道作为数据类型的枚举不是通用 SQL 语言 92 的一部分 您将如何建模它 数据模型必须是可移植的 以便由多个
  • WebLogic 10 中的临时目录

    每当 WL 停止时 它都不会删除其临时目录 即 domains mydomain servers myserver tmp WL TEMP APP DOWNLOADS domains mydomain servers myserver tm
  • 代码编译期间遇到警告消息“使用或覆盖已弃用的 API”

    我编译了我的程序并收到以下错误 我该如何解决呢 Note ClientThreadClients java uses or overrides a deprecated API Note Recompile with Xlint depre
  • 动画图像视图

    目前我正在开发一款游戏 这是我的游戏的详细信息 用户应选择正确的图像对象 我希望图像从左到右加速 当他们到达终点时 他们应该再次出现在活动中 这是我正在处理的屏幕截图 我有 5 个图像视图 它们应该会加速 您有此类动画的示例代码吗 非常感谢
  • FFmpeg 不适用于 android 10,直接进入 onFailure(String message) 并显示空消息

    我在我的一个项目中使用 FFmpeg 进行视频压缩 在 Android 10 Google Pixel 3a 上 对于发送执行的任何命令 它会直接进入 onFailure String message 并显示空消息 所以我在我的应用程序 g
  • JavaFx 中装饰且不可移动的舞台

    我想在 JavaFx 中创建一个装饰舞台 它也将不可移动 我正在从另一个控制器类创建这个阶段 我能够创造和展示舞台 但它是自由移动的 我怎样才能创建这个 非常感谢帮助和建议 我把打开新关卡的方法贴出来 private void addRec
  • 如何获取 Android 中临时文件的文件大小?

    如果我使用 openFileOutput 创建并写入临时文件 写入完成后如何获取文件大小 我希望这可以帮助你 File file new File selectedPath int file size Integer parseInt St
  • XSLT:我们可以使用abs值吗?

    我想知道在 XSLT 中我们是否可以使用 math abs 我在某处看到过这个 但它不起作用 我有类似的东西
  • Java 类:匿名类、嵌套类、私有类

    有人能解释一下Java中匿名类 嵌套类和私有类之间的区别吗 我想知道与每个相关的运行时成本以及每个编译器的方法 这样我就可以掌握哪个最适合用于例如性能 编译器优化的潜力 内存使用以及其他 Java 编码人员的普遍可接受性 我所说的匿名类是指
  • NoSuchMethodError:将 Firebase 与应用程序引擎应用程序集成时

    我试图将 firebase 实时数据库与谷歌应用程序引擎应用程序集成 我在调用时收到此错误 gt DatabaseReference ref FirebaseDatabase gt getInstance gt getReference t
  • 删除 ArrayList 对象问题

    我在处理作业时遇到从 ArrayList 中删除对象的问题 如果我使用 正常 for 循环 它的工作原理如下 public void returnBook String isbn for int i 0 i lt booksBorrowed
  • 如何列出所有可用的 LookAndFeel 主题?

    如何列出所有可用的 LookAndFeel 主题 我想在 JComboBox 中显示以供用户选择 这真的很简单 public static UIManager LookAndFeelInfo getInstalledLookAndFeels
  • 在 netBeans 中运行程序时,字体看起来非常奇怪

    我在我的新 MacBook M1 上设置了 netBeans 和 SceneBuilder 除了运行程序时的字体外 一切正常 它看起来像这样 我不知道为什么 按钮应显示 Click me 标签应显示 Hello 我收到的错误消息是 M rz
  • 无法仅在控制台中启动 androidstudio

    你好 我的问题是下一个 我下载了Android Studio如果我去 路径 android studio bin 我执行studio sh 我收到以下错误 No JDK found Please validate either STUDIO
  • 如何使用 SAX Java 解析器读取注释文本

    我只想使用 Java 中的 SAX 解析器读取 XML 文件中对象标记的注释 这是我的文件的摘要
  • 无法在 BlackBerry Playbook 上设置音量

    我在更改黑莓游戏书的音量时遇到问题 首先 我将 Android 应用程序重新打包到 Palybook 应用程序 我需要使用搜索栏更改黑莓剧本的音量 并在搜索监听器中设置音频管理器音量 这是代码 audioManager AudioManag
  • java数据结构模拟数据树

    我需要帮助定义使用什么方法 我有一个 SOAP 响应 给我一个 xml 文件 我需要在屏幕上显示 3 个相关列表 当您在第一个列表中选择一个项目时 相应的选择将出现在第二个列表中 依此类推 我只对从 xml 流中提取数据后如何有效地组织数据
  • java中的回调是什么[重复]

    这个问题在这里已经有答案了 可能的重复 什么是回调函数 https stackoverflow com questions 824234 what is a callback function 我已经阅读了回调的维基百科定义 但我仍然没有明

随机推荐

  • SSL的“四次握手”

    第一次握手 客户端向服务端发送Client Hello报文 该报文中包含了支持的版本信息 加密组件等 加密组建包括加密算法 秘钥长度等内容 第二次握手 这个阶段服务器会向客户端发送三个报文 服务端收到请求后 如果支持SSL通信 会首先以Se
  • SQL Server数据备份

    SQL Server数据库 自动 手动 备份 sql 数据库自动备份 一 为备份文件建一个独立文件夹 sql data autobakup 方便区分 Win R 输入services msc进入服务管理界面查找sqlserver服务 复制此
  • pulseaudio使用过程中遇到的问题

    W pulseaudio main c This program is not intended to be run as root unless system is specified E pulseaudio core util c H
  • Self-study Python Fish-C Note-5 P20-P26 (part2)

    python 中的列表 Part 2 本文主要讲解了python中列表的使用 本文为自学B站上鱼C的python课程随手做的笔记 如有问题 欢迎大家批评指正 原视频链接 https www bilibili com video BV1c44
  • LeetCode算法心得——和可被 K 整除的子数组(前缀和+HashMap)

    大家好 我是晴天学长 同余定理的应用 需要的小伙伴可以关注支持一下哦 后续会继续更新的 1 和可被 K 整除的子数组 题目描述 给定一个整数数组 A 返回其中元素之和可被 K 整除的 连续 非空 子数组的数目 示例 输入 A 4 5 0 2
  • 【极简数据结构】快速了解并实现顺序表,速通玩家的最爱

    顺序表目录 前言 一 线性表 二 顺序表 1 顺序表的概念 2 接口函数 顺序表 初始化 顺序表 尾插 顺序表 打印 顺序表 销毁 顺序表 尾删 顺序表 头插 和 顺序表 扩容 优化顺序表 尾删 顺序表 头删 顺序表 查找 顺序表 任意po
  • Android如何安全的关闭线程

    正常情况下 当线程中的run方法执行完毕后 线程是会自动关闭 不需要我们手动去关闭的 如 new Thread new Runnable Override public void run 执行操作 start 该线程在run方法中的操作执行
  • C语言经典100例题(22)--两个乒乓球队进行比赛,各出三人。甲队为a, b, c三人,乙队为x, y, z三人。已抽签决定//比赛名单,有人向队员打听比赛的名单.a说他不和x比,c说他不和x, z

    目录 题目 问题分析 代码 运行结果 题目 两个乒乓球队进行比赛 各出三人 甲队为a b c三人 乙队为x y z三人 已抽签决定比赛名单 有人向队员打听比赛的名单 a说他不和x比 c说他不和x z比 请编程序找出三队赛手的名单 问题分析
  • linux屏蔽海外流量的两种方法

    方法一 使用大神的开源脚本 屏蔽指定国家地区的IP访问 wget https raw githubusercontent com iiiiiii1 Block IPs from countries master block ips sh s
  • RSA的C++语言描述简单实现

    文章目录 前言 代码仓库 代码特点 大 素 数讨论 部分资料 作者理解 代码 rsa h rsa cpp main cpp 结果 总结 参考资料 作者的话 前言 网络安全中RSA的C 语言描述简单实现 代码仓库 yezhening Prog
  • excel 生成sql

    参考文章 https blog csdn net m0 67695717 article details 127406830 新增语句 INSERT INTO table name column1 column2 VALUES A2 D2
  • 判断一个文件是否为CSV文件的Python代码

    在Python中 我们可以使用os模块的path splitext 函数来获取文件扩展名 然后判断这个扩展名是否为 csv 以下是一个示例代码 import os def is csv file file path file extensi
  • WSL2和Docker for Windows

    文章目录 一 Docker和WSL2概述 二 WSL安装使用 三 基于Docker导入任意WSL分发 参考资料 一 Docker和WSL2概述 Docker 是一个开源的应用容器引擎 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中
  • git中出现“interactive rebase in progress; onto 11dde1e”错误分析与解决方案

    出错原因分析 进行提交前 需提前拉取远程仓库的代码 拉取之后 需要重新add commit 避免仓库的数据被修改 但是再次提交之后会出现上图的错误 原因 是因为你现在正在编辑的提交将要覆盖在 11ddele commited 之前使用过gi
  • 472-I/O阻塞和非阻塞,同步和异步

    阻塞 非阻塞 同步 异步 典型的一次I O的两个阶段是什么 数据准备 和 数据读写 我们作为服务器 接收客户端的请求 得先监听客户端有没有数据过来 这是一个状态 还有就是数据过来了该怎么去读写 这又是一个状态 实际上 阻塞 非阻塞 同步 异
  • 基于51单片机的羽毛球计分器proteus仿真程序设计

    硬件设计 末尾附文件 方案 在像羽毛球这样的竞技比赛中 计分器占着很大的作用 如果我们就只在心里记着双方的比分 显然是不实际的 而且在现在的乒乓球比赛中采用的都是21分制 因此我们不能再用传统的计分方式了 本次课题采用单片机设计了一个羽毛球
  • JetBrains IDE Support 调试工具(页面自动刷新)

    1 谷歌浏览器安装JetBrains IDE Support 插件 2 更改端口 webstorm 和 JetBrains IDE Support 端口不对插件图标会黑 3 debug 4 同步
  • 求定制闲鱼爬虫获取最新发布商品

    闲鱼采集及监控下单软件开发 1 点击宝贝右键打开网页 2 点击宝贝右键拉黑卖家 3 点击宝贝右键清空列表 4 点击宝贝左键显示二维码和主图 5 软件页面显示宝贝二维码 6 软件页面显示宝贝主图 7 软件页面显示检测搜索词及下单宝贝 8 每次
  • 介绍计算机方队,方阵

    f ng zh n 方阵 语音 编辑 锁定 讨论 上传视频 方阵是古代军队作战时采用的一种队形 是把军队在野外开阔地上排列成方形阵式 远古方阵由前军 中军和后军相互嵌套排列而成 方阵平面呈现 回 字形状 反映出远古观念中的一种政治地理结构
  • Java丨JVM虚拟机与类加载器

    一丶JVM 虚拟机介绍 Sun HotSpot VM 这个目前看起来 血统纯正 的虚拟机在最初并非由Sun公司开发 而是由一家名为 Longview Technologies 的小公 司设计的 甚至这个虚拟机最初并非是为Java语言而开发的