news 2026/7/6 2:56:32

Java语言JVM

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java语言JVM

一、Java介绍

编译型语言(源代码需要通过编译器编译):(面向过程)C;(面向过程&面向对象)C++;(面向对象)Java,Go,C#
解释型语言:JavaScript
  1. Java的一些特性
  • Java是纯面向对象语言,所有代码必须定义在类中,不容许单独的过程与函数存在,方法必须隶属于类或对象。
  • 成员通过类名(静态方法)或对象(实例方法)调用。
  • 非静态方法属于实例成员(对象),而静态方法才属于类成员。
  • 类的成员= 类里面定义的所有东西(包括静态和非静态的字段、方法、嵌套类等)
  • 实例成员= 必须通过对象.xxxoff-heap访问的非静态部分(属于具体对象)
  1. Java的组成
  • JDK:Java Delelopment Kit Java开发工具包
  • JRE:Java Runtime Environment Java运行时环境
  • JVM: Java Vertual Machine Java虚拟机

二、JVM虚拟机

类加载器、垃圾回收器、JIT编译器和解释器 均为JVM的组件。
  1. Java的跨平台开发:
javac 是 Java 编译器。它的作用是将你写的 Java 源代码(.java 文件)编译成字节码(.class 文件,JVM 可识别的格式一个Java源程序文件中定义几个类和接口,则编译该文件后生成几个以.class为后缀的字节码文件。
java 是解释器/运行器。负责启动 JVM 并将指定的 .class 文件加载进入JVM并执行,生成可执行的二进制机器码。
  1. JVM中的内存结构
线程共享:
  • 直接内存:直接向操作系统申请内存,不受 JVM 堆内存大小限制。
  • 方法区(Method Area)/元空间(Metaspace):是 JVM 中用来存储类的结构信息、常量、静态变量、JIT 编译代码等的内存区域。
  • 运行时常量池(JVM常量池):属于方法区的一部分,存放编译期生成的各种字面量和符号引用。可以动态添加常量(如 String.intern())。
  • Java 堆(Heap):是垃圾收集器管理的主要区域,因此也被称作GC 堆(Garbage Collected Heap)。是 JVM 中最大的一块内存区域,存储着所有通过 new 关键字创建的对象实例和数组以及这些对象的实例变量(字段)等。是垃圾回收器(GC)主要管理的区域。如果没有内存可用且 GC 无法回收,会抛出 OutOfMemoryError。
线程私有(独立拥有):
  • 程序计数器:当前线程所执行字节码的行号指示器。
  • 本地方法栈:执行 native 本地方法,运行 C/C++ 等 native 代码,如 JNI
  • 虚拟机栈(JVM Stack)栈区是 JVM 为每个线程分配的运行内存区域存储每个方法调用时的栈帧,栈帧是栈区的最小单位。
    • 栈帧:方法调用时在栈区里开辟的一小块内存单元,存储方法执行过程中所需要的信息局部变量-存储了基本数据类型的值、对象的引用变量、操作数、中间结果和方法出口等)。
    • 压栈出栈:方法调用 → 入栈;方法结束 → 出栈。
    • 异常情况:StackOverflowError:栈深度过大。OutOfMemoryError:无法申请足够内存创建新的栈。

3、池Pool

其实是一个非常重要的性能优化思想,Java 大量使用“池”,贯穿了JVM 底层、标准库、开发框架与应用开发各个层次。是“资源复用”机制,避免频繁创建与销毁相同类型的对象或资源,降低性能开销与内存浪费。
层次
池的名称
位置
说明
外存层面
Class 文件常量池(Constant Pool Table)
存储在磁盘上的 .class 文件内部
属于 Class 文件格式规范,同时为JVM 加载和执行类文件提供必要的符号信息支持
JVM内存层面
运行时常量池
方法区(元空间)
运行时常量池是Class 文件常量池被JVM加载在内存中的映射
字符串常量池
堆(JDK1.7+)
字面量字符串共享
包装类对象缓存池
Integer、Byte、Boolean 缓存
标准库层面
线程池(ThreadPoolExecutor)
复用线程资源
对象池(Object Pool)
Apache Commons Pool 等
NIO ByteBuffer 池
堆/堆外
复用缓冲区(Netty)
应用层面
数据库连接池
DBCP、HikariCP、Druid 等
缓存池(对象缓存)
业务自定义缓存池

4、JVM 的垃圾回收机制(GC garbage collection)

Minor GC:主要回收的是年轻代(Young Generation)的内存。年轻代主要包括Eden 区和两个Survivor 区(S0 和 S1)。
Full GC:Full GC 会回收整个堆内存,包括年轻代老年代(Old Generation)
当JVM发现某些对象不再被引用时,就会将其标记并在合适的时机进行回收,这个过程是动态的、持续的。GC不仅管理堆内存,还涉及方法区(元空间)。Java 中的垃圾回收算法有四种分别是标记清除法、标记整理法、复制算法、分代收集算法;
堆内存采用分代结构,分为新生代和老年代JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了),取而代之是元空间,元空间使用的是直接内存。新创建的对象总是在新生代的Eden区进行分配,Java GC是可以手动触发的,比如通过System.gc()方法,尽管这只是建议JVM进行垃圾回收,但并不保证一定会执行。JVM可以自主决定何时触发GC。
大部分情况,对象都会首先在 Eden 区域分配。当 eden 区没有足够空间进行分配时,虚拟机将发起一次 Minor GC。经过第一次 Minor GC 后仍然能够存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为 1.对象在 Survivor 中每熬过一次 MinorGC,年龄就增加 1 岁,当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。在Minor GC(YGC)时,若存活对象无法全部放入To Survivor区,超出的部分会直接晋升到老年代。对象晋升到老年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设置。老年代无法容纳新晋升的对象时,会触发 Full GC(仅限一些垃圾回收器比如Serial / Parallel Scavenge)。
JAVA进程的JVM参数配置如下:-Xms1G -Xmx2G -Xmn500M -XX:MaxPermSize=64M -XX:+UseConcMarkSweepGC -XX:SurvivorRatio=3,
  • -Xms1G → 初始堆大小 =1GB
  • -Xmx2G → 最大堆大小 =2GB
  • -Xmn500M → 新生代大小 =500MB
  • -XX:MaxPermSize=64M → 永久代最大值 =64MB(仅适用于 JDK 8 之前)
  • -XX:SurvivorRatio=N → Eden : Survivor = N : 1 : 1(即 Eden 占新生代的 3/5,两个 Survivor 区各占 1/5)
垃圾回收算法:
1.1.标记-清除算法该算法分为“标记”和“清除”阶段:首先标记出所有不需要回收的对象,在标记完成后统一回收掉所有没有被标记的对象。它是最基础的收集算法,后续的算法都是对其不足进行改进得到的。
特点:
  • 1. 效率不行,标记和清除的效率都不高
  • 2. 标记和清除后会产生大量的不连续的空间分片,可能会导致之后程序运行的时候需分配大对象而找不到连续分片而不得不触发一次GC;
1.2. 复制算法为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。
特点:1. 不会产生空间碎片2. 内存使用率极低
1.3. 标记-整理算法根据老年代的特点提出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。
特点:1. 适用于存活对象多,垃圾少的情况2. 需要整理的过程,无空间碎片产生
1.4.分代收集算法当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将 java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。==为了提高GC效率,所以 HotSpot 要分为新生代和老年代。

三、Kotlin介绍

几乎可以说 Kotlin 是在Java 的地基上盖的新房子。Kotlin 是一种现代化的、与 Java 100% 互操作的 JVM 语言,它可以直接使用 Java 的所有资源,但在语法、空指针安全和开发体验上更先进。
1.运行平台相同
  • Java 程序编译成字节码(.class 文件),运行在JVM(Java Virtual Machine)上。
  • Kotlin 也是编译成字节码,运行在同一个 JVM 上。
  • 所以 Kotlin 和 Java 的 .class 文件可以在同一个项目中无缝混用。
2.语法兼容
  • Kotlin 可以直接调用 Java 的类、方法、库,没有任何额外转换。
  • Java 也能调用 Kotlin 写的代码(虽然 Kotlin 的一些特性在 Java 调用时可能不那么优雅)。
  • Kotlin 中声明变量不必指定变量的类型,Kotlin 会隐式指定类型。
  • Kotlin 中声明变量,可以使用 var 或 val 关键字
  • Kotlin 中,val 变量赋值后,无法更改使用 val 关键字声明的变量
  • Kotlin 中的 println() 函数调用了 System.out.println() 函数
3.语言设计目标
Kotlin 由JetBrains(IntelliJ IDEA 的公司)开发,设计目标是:
  • 更简洁(减少 Java 的模板代码)
  • 更安全(尤其是空指针安全)
  • 更现代(支持协程、扩展函数、数据类等特性)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 2:56:11

管理Linux软件包和进程

Linux软件包管理:从源码编译到YUM仓库,再到进程管理 —— 原理与实战 前言 在Linux系统中,软件包管理是运维人员最常打交道的操作之一。无论是安装Web服务器,还是部署数据库环境,都离不开它。但你有没想过:…

作者头像 李华
网站建设 2026/7/6 2:55:35

GraphRAG 实战:工程实践里的常见坑

《GraphRAG 实战:工程实践里的常见坑》看起来是个大话题,但真落到项目里,常常就是几个具体选择。下面我尽量按实际开发时会遇到的问题来讲。摘要这篇面向需要构建企业知识库和复杂问答系统的开发者,但不会把“GraphRAG 实战&#…

作者头像 李华
网站建设 2026/7/6 2:55:09

大部分管理信息系统(MIS)都少不了员工

当为员工创建帐号并分配相应的权限后,该帐号即可登录系统并进行相应的操作。当员工与系统进行交互操作时,系统会把员工Id、操作时间、操作IP、操作内容等信息记录到操作日志中,以便随时审计。   这样,从Domain的角度讲&#xff…

作者头像 李华