前言在之前我写过一篇专门讲解JVM的文章大家看完这篇可以专门去看一下那篇这篇主要是讲框架以及全面的看待JDK、JRE、JVM之间的关系尽管我们在使用Java但是最最最基础的知识还不太了解这篇就主要从Java核心特点、优劣势、JDK/JRE/JVM三者的定义与关系、Java完整执行流程、半编译半解释特性这五个核心维度来讲解一、Java核心特点大家一定听说过Java的设计理念就是“Write Once, Run Anywhere”一次编写到处运行其核心特点围绕这一理念展开每个特点都有底层逻辑支撑而非单纯的表面描述1.跨平台性核心特点这是Java最具辨识度的特点核心原理是「JVM的中间层隔离」——Java程序不直接编译成操作系统可执行的机器码而是编译成中间态的字节码.class文件再由不同操作系统对应的JVMWindows版JVM、Linux版JVM、macOS版JVM将字节码解释为本地机器码执行。关键点跨平台的不是Java代码而是「字节码」JVM是跨平台的核心载体不同系统的JVM实现不同但都能识别统一的字节码这也是“一次编译到处运行”的本质。2. 面向对象OOPJava是纯面向对象语言除基本数据类型外所有元素都是对象核心三大特性封装、继承、多态同时支持抽象类、接口从设计上引导开发者进行模块化、可复用的代码编写。补充Java不支持多重继承避免菱形继承冲突而是通过接口实现多继承的效果这是Java面向对象设计的一个重要取舍。3. 安全性高Java从设计之初就注重安全性核心保障有三点① 字节码校验机制JVM加载.class文件时会校验字节码的合法性防止恶意代码注入② 沙箱机制限制程序的访问权限比如Applet程序不能访问本地文件系统③ 垃圾自动回收避免手动管理内存导致的内存泄漏、野指针等安全问题对新手很友好。4. 平台无关性延伸特性除了跨平台Java的平台无关性还体现在API接口统一不同系统的Java核心类库接口一致、数据类型大小固定比如int在任何系统都是32位而C/C中int大小随系统变化避免了因平台差异导致的代码适配问题。5. 垃圾自动回收GCJava不需要开发者手动分配、释放内存对比C/C的malloc/free而是由JVM内置的垃圾回收器GC自动识别并回收不再使用的对象内存降低了内存管理的复杂度减少了内存泄漏风险。补充GC并非实时回收而是在内存达到一定阈值或程序空闲时触发开发者可以通过System.gc()建议JVM执行GC但无法强制触发。6. 多线程支持Java内置多线程机制通过Thread类、Runnable接口、Callable接口等轻松实现多线程编程且JVM提供了线程调度、同步锁synchronized这个在之前的文章里面也详细的讲解过大家有兴趣可以去看看、volatile关键字等工具简化了多线程开发的复杂度但也需要注意线程安全问题。二、Java优劣势结合Java的特点优劣性非常鲜明尤其在企业级开发场景中优势更为突出劣势也多与具体应用场景相关而非语言本身的缺陷。1. 优势跨平台性突出一次编译多平台运行大幅降低跨系统开发、部署的成本尤其适合企业级应用需部署在不同服务器系统。生态完善经过近30年的发展Java拥有庞大的生态体系无论是框架Spring、SpringBoot、MyBatis、中间件Redis、Kafka、Dubbo还是工具类Apache Commons、Guava都非常成熟能覆盖绝大多数开发场景。安全性高字节码校验、沙箱机制、GC等特性让Java程序在运行过程中更稳定、更安全适合开发金融、电商等对安全性要求高的系统。可扩展性强面向对象的设计、模块化开发以及丰富的框架支持让Java程序能够轻松应对业务迭代便于后期维护和扩展。人才储备充足Java是全球使用最广泛的编程语言之一开发者基数大招聘、学习、问题排查都更便捷。2. 劣势运行效率低于编译型语言由于Java是半编译半解释语言存在字节码解释为机器码的过程运行效率略低于C/C等纯编译型语言但现代JVM的JIT即时编译已大幅弥补这一差距。内存占用较高Java程序运行时JVM会占用一定的内存用于运行时数据区、GC等相比Python、Go等语言内存消耗相对较大。语法相对繁琐对比Python、JavaScript等语言Java的语法更严谨、繁琐比如必须定义类、main方法才能运行入门门槛略高。移动端生态弱化随着Flutter、React Native等跨平台框架的兴起Java在移动端Android的主导地位有所下降虽然Android开发仍以Java/Kotlin为主但生态热度不及以往。三、JVM 、JRE、JDK很多开发者分不清JVM、JRE、JDK的区别甚至认为三者是一回事其实它们是层层包含、各司其职的关系核心逻辑是“开发→运行→底层执行”的分工下面逐一拆解定义、组成及关系。1. JVMJava Virtual MachineJava虚拟机—— 底层执行核心1定义JVM是一个抽象的、软件层面的“虚拟计算机”是Java程序运行的底层核心载体本质上是一段运行在操作系统上的程序负责将Java字节码解释或编译为本地机器码并执行。2核心组成类加载器ClassLoader负责加载.class字节码文件到JVM内存中验证字节码合法性是JVM执行的第一步注意类加载器属于JVM而非JRE。运行时数据区JVM的内存空间分为方法区、堆、虚拟机栈、本地方法栈、程序计数器5个部分用于存储程序运行时的变量、对象、方法等数据后续可单独拆解内存模型。执行引擎核心模块负责将字节码翻译成本地机器码并执行分为解释器逐行解释字节码和JIT即时编译器将热点代码编译成机器码缓存提升效率。本地方法接口JNI用于调用本地操作系统的方法比如访问本地文件、硬件弥补Java无法直接操作底层硬件的不足。垃圾回收器GC负责回收运行时数据区中不再使用的对象内存避免内存泄漏核心算法有标记-清除、复制、标记-整理等。3关键注意点JVM不能单独安装和使用必须依赖JRE或JDK因为JVM本身只负责执行字节码而字节码运行需要Java核心类库的支持比如String、List等类JVM无法单独提供这些类库。2. JREJava Runtime EnvironmentJava运行环境—— 运行Java程序的最小环境1定义JRE是运行Java程序所必需的环境集合面向的是“普通用户”或“部署环境”只负责运行已编译好的Java程序不提供任何开发相关的工具。2核心组成JRE JVM Java核心类库rt.jar等 本地方法库JVM提供字节码的执行能力是JRE的核心。Java核心类库包含Java基础API比如java.lang、java.util、java.io等包是Java程序运行的基础比如String类、集合类、IO流等都来自核心类库。本地方法库配合JNI提供Java程序调用本地系统方法的支持。3使用场景如果只需要运行别人写好的Java程序比如jar包、Java桌面程序安装JRE即可不需要安装JDK比如服务器部署Java项目只需要JRE。3. JDKJava Development KitJava开发工具包—— 开发Java程序的完整工具包1定义JDK是Java开发必备的完整工具包面向的是“Java开发者”不仅包含了运行Java程序的JRE还提供了编译、调试、监控等开发所需的工具既能开发Java程序也能运行Java程序。2核心组成JDK JRE 开发工具集常用开发工具javacJava编译器负责将.java源代码编译成.class字节码文件核心开发工具。javaJava运行命令负责启动JVM加载字节码并执行程序。jar打包工具将多个.class文件、资源文件打包成jar包便于部署和分发。jpsJVM进程查看工具用于查看当前运行的Java进程。jmap、jconsole、jvisualvmJVM监控和调试工具用于排查内存泄漏、性能瓶颈等问题。3使用场景开发Java项目无论是后端、桌面还是Android必须安装JDK因为需要使用javac编译源代码使用调试工具排查问题。4. 三者核心关系层级包含关系从大到小JDK ⊃ JRE ⊃ JVMJDK包含JREJDK自带一套完整的JRE所以安装了JDK后不需要再单独安装JREJDK的jre目录就是内置的JRE。JRE包含JVMJRE将JVM作为核心组件同时提供核心类库和本地方法库让JVM能够正常执行字节码。JVM是最小核心JVM只负责执行字节码没有JRE提供的核心类库JVM无法运行任何完整的Java程序比如没有String类就无法处理字符串。图片来源于网络通俗比喻便于记忆JVM 汽车发动机只负责运转没有其他零件无法行驶JRE 完整汽车发动机车身、轮胎、方向盘等基础零件能正常行驶JDK 汽车4S店完整汽车既能开车还能修车、改装、生产新车对应开发、调试、编译。四、Java执行流程编写.java源代码 → JDK的javac编译 → .class字节码 → 启动JVM → 类加载器加载字节码 → 执行引擎将字节码翻译成机器码 → CPU执行 → 程序结束 → JVM释放资源。五、Java是半编译半解释语言Java结合了编译型语言和解释型语言的优势既保证了跨平台性又兼顾了运行效率1.编译语言、解释语言1编译型语言如C/C在程序执行前源代码一次性全部编译成操作系统可执行的机器码运行时直接执行机器码运行效率高但无法跨平台Windows编译的机器码不能在Linux上运行。2解释型语言如Python、JavaScript源代码不提前编译运行时逐行解释成机器码并执行跨平台性好但运行效率低逐行解释需要反复翻译。2.Java的半编译半解释原理Java的执行过程分为“编译阶段”和“解释阶段”两者结合形成了半编译半解释的特点1编译阶段提前做只做一次通过JDK的 javac 工具将.java源代码编译成.class字节码文件这个过程是“一次性编译”——只要源代码不变就不需要重复编译编译后的字节码是跨平台的与操作系统无关。注意这里的“编译”不是直接翻译成机器码而是翻译成中间态的字节码这是Java与纯编译型语言的核心区别。2解释阶段运行时做按需执行程序运行时JVM的执行引擎会将.class字节码逐行解释成当前操作系统的机器码然后交给CPU执行这个过程是“实时解释”——每执行一行字节码就解释一行机器码。注意解释阶段是与操作系统相关的不同系统的JVM解释出的机器码不同这也是Java跨平台的关键。