JVM和异常

Java 虚拟机(Java Virtual Machine,简称 JVM)

概述

JVM 是运行 Java 字节码的虚拟计算机,它是 Java 程序能够实现 “一次编写,到处运行(Write Once, Run Anywhere)” 特性的关键所在。Java 程序首先被编译成字节码(.class 文件),然后由 JVM 在不同的操作系统和硬件平台上执行这些字节码,屏蔽了底层操作系统和硬件的差异。

体系结构

  • 类加载子系统(Class Loader Subsystem):负责加载字节码文件到 JVM 中。它包括启动类加载器(Bootstrap Class Loader),主要加载 Java 的核心类库,像 java.lang 包下的类等;扩展类加载器(Extension Class Loader),负责加载 Java 扩展库;应用程序类加载器(Application Class Loader),加载用户编写的类路径下的类等。例如,当运行一个简单的 HelloWorld 程序时,应用程序类加载器会把对应的 HelloWorld.class 文件加载进来。
  • 运行时数据区(Runtime Data Areas)
    • 方法区(Method Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。在 HotSpot JVM 中,方法区也常被称为永久代(Permanent Generation,不过在 Java 8 之后,元空间(Metaspace)取代了永久代)。
    • 堆(Heap):这是 JVM 内存管理中最大的一块区域,主要用于存放对象实例。所有的对象实例以及数组都要在堆上分配内存,例如通过 new 关键字创建的对象都会存放在堆中。
    • 虚拟机栈(Java Virtual Machine Stacks):每个线程都有一个私有的虚拟机栈,它描述的是 Java 方法执行的内存模型。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。栈帧中存储了局部变量表、操作数栈、动态连接、方法返回地址等信息。
    • 本地方法栈(Native Method Stacks):和虚拟机栈类似,不过它是为执行本地方法(Native Method,一般是用其他语言编写的与底层系统交互的方法,比如 C 或 C++ 编写的方法)服务的。
    • 程序计数器(Program Counter Register):可以看作是当前线程所执行的字节码的行号指示器。因为在多线程环境下,线程会频繁地切换,而程序计数器能保证每个线程切换回来后能准确地知道下一条要执行的字节码指令。
  • 执行引擎(Execution Engine):负责执行字节码指令。执行引擎会把字节码指令解释执行或者编译成机器码后再执行,像 HotSpot JVM 就采用了即时编译(Just-In-Time Compilation,JIT)技术,对于热点代码(频繁执行的代码)会将其编译成机器码以提高执行效率。

垃圾回收(Garbage Collection,GC)

JVM 自动管理内存,其中很重要的一部分就是垃圾回收机制。它会自动识别并回收那些不再被使用的对象所占用的内存空间。例如,当一个对象没有任何引用指向它时,经过一定的垃圾回收算法(如标记 - 清除算法、复制算法、标记 - 整理算法等)的判断和处理,其占用的内存就会被释放掉,让内存能够得到有效的利用,减少内存泄漏等问题的发生。

重要性及应用场景

JVM 的存在让 Java 开发人员无需过多关注底层硬件和操作系统的差异,专注于业务逻辑开发。在企业级应用开发、安卓应用开发(安卓系统中也有基于 JVM 改造的 Dalvik 虚拟机、ART 虚拟机等)、大数据处理框架(很多大数据框架基于 Java 开发,运行在 JVM 上)等众多场景中广泛应用,保障了 Java 程序稳定、高效地运行。

总之,JVM 是 Java 生态中极为重要的基础支撑,深入理解它对于优化 Java 程序性能、排查内存相关问题等都有着重要的意义。

异常类概述

在 Java 中,异常类(Exception Classes)用于表示程序执行过程中出现的异常情况,它是 Throwable 类的子类。当程序运行过程中发生一些不符合预期的状况,比如试图访问不存在的文件、数组越界、除数为零等,就会抛出对应的异常对象,如果不进行处理,程序通常会终止执行。通过合理地使用异常类,可以更好地控制程序流程,增强程序的健壮性和容错能力。

异常类的层次结构

  • Throwable 类:它是所有异常和错误的超类,位于异常类层次结构的顶层。Throwable 有两个重要的子类,分别是 Exception 和 Error
  • Exception 类:表示程序本身可以处理的异常情况,又可以细分为两类。
    • 受检异常(Checked Exceptions):这类异常是编译器要求必须进行处理的异常,通常是一些在程序运行时可能会出现的可预期的异常情况,比如 IOException(涉及输入输出操作,像文件读取写入时可能出现问题)、SQLException(进行数据库操作时可能产生的异常)等。在方法中如果可能抛出受检异常,要么使用 try-catch 语句块捕获并处理它,要么在方法声明处通过 throws 关键字声明抛出该异常,让调用者去处理。例如:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;public class CheckedExceptionExample {public static void main(String[] args) {try {File file = new File("test.txt");FileInputStream fis = new FileInputStream(file);// 这里如果文件不存在等情况就会抛出IOException,后续代码进行处理} catch (IOException e) {e.printStackTrace();}}
}
  • 非受检异常(Unchecked Exceptions):也叫运行时异常(Runtime Exceptions),这类异常通常是由于程序员编写代码时的逻辑错误导致的,比如 NullPointerException(对空指针进行操作)、ArrayIndexOutOfBoundsException(数组越界)、ArithmeticException(算术运算异常,像除数为零)等。编译器不会强制要求处理这类异常,但如果发生了也会导致程序异常终止,除非在代码中进行合适的处理。例如:
public class UncheckedExceptionExample {public static void main(String[] args) {int[] arr = new int[5];// 下面这行代码会抛出ArrayIndexOutOfBoundsExceptionSystem.out.println(arr[10]); }
}
  • Error 类:表示严重的、不应该被程序捕获处理的错误情况,一般是 JVM 内部错误或者资源耗尽等非常严重的问题,比如 OutOfMemoryError(内存溢出)、StackOverflowError(栈溢出)等。当出现这类错误时,通常很难通过程序本身去恢复,往往意味着程序需要重新启动或者进行系统层面的调整。例如:
public class ErrorExample {public static void main(String[] args) {// 下面的递归调用如果没有终止条件,会导致栈空间不断被占用,最终抛出StackOverflowErrorrecursiveMethod(); }public static void recursiveMethod() {recursiveMethod();}
}

自定义异常类

除了使用 Java 内置的异常类,开发人员还可以根据具体的业务需求自定义异常类。自定义异常类通常需要继承自 Exception 类(如果是受检异常)或者 RuntimeException 类(如果是非受检异常)。例如,假设在一个电商系统中,当库存不足时想要抛出特定的异常,可以这样定义:

// 自定义受检异常类
public class InsufficientStockException extends Exception {public InsufficientStockException(String message) {super(message);}
}

然后在相关业务逻辑代码中使用:

public class Product {private int stock;public Product(int stock) {this.stock = stock;}public void sell(int quantity) throws InsufficientStockException {if (quantity > stock) {throw new InsufficientStockException("库存不足,无法销售这么多商品");}stock -= quantity;}
}

总之,合理运用异常类并对各种可能出现的异常情况进行妥善处理,对于编写高质量、稳定可靠的 Java 程序是至关重要的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/65650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis 为什么不需要给Mapper接口写实现类,为什么要使用代理而不是硬编码?

文章目录 核心机制概述源码分析1. 获取 Mapper 实例2. 创建 Mapper 代理对象3. 拦截方法调用 MapperProxy4. 关联 SQL 并执行 为什么 MyBatis 采用了代理机制,而不是简单地面向流程化的方式?1. 解耦和灵活性2. 方法拦截和事务管理3. 动态代理支持方法级别的 SQL 定…

DevOps流程CICD之Jenkins使用操作

一、jenkins的docker-compose安装部署 请参考 jenkins的docker安装部署配置全网最详细教程-CSDN博客 二、创建repository 三、创建ssh 四、创建视图 五、创建任务 六、配置gitlab钩子 七、自动构建部署CI/CD验证

Solidworks打开无法获得许可,提示(-15,10,10061)错误解决办法

参考文章: https://blog.csdn.net/2301_81263647/article/details/140904773

四、AI知识(其他算法)

四、AI知识(其他算法) 1.其他算法 终身学习 元学习 2.建模预处理与评估 数据清洗 数据规约 空缺值 噪声数据 数据变换 数据规范化(如正则化、归一化) 数据压缩 数据规约 数值数据离散化/分类数据概念分层 模型评估 …

【云原生】Docker Compose 从入门到实战使用详解

目录 一、前言 二、Docker Compose 介绍 2.1 Docker Compose概述 2.2 Docker Compose特点 2.3 Docker Compose使用场景 三、Docker Compose 安装 3.1 安装docker环境 3.2 Docker Compose安装方式一 3.2.1 下载最新版 3.2.2 设置权限 3.2.3 设置软链接 3.2.4 查看版本…

wangEditor/editor自定义粘贴后续

背景 按照上一篇文章处理自定义粘贴之后,发现复制表格之后,会出现表格样式失效问题,原因是自定义粘贴没有处理表格数据,导致按照文本格式粘贴了 处理方式 自定义表格(如果业务有需求需要更新表格样式的,…

【OTA】论文笔记--《智能网联汽车整车OTA功能设计研究》智能网联汽车OTA系统设计分析报告

智能网联汽车OTA系统设计分析报告 引言 随着汽车智能化、网联化水平不断提升,现代汽车中电子控制单元(ECU)的数量和复杂度持续增加。据统计,高级轿车上电子电气元件的成本已占整车开发成本的60%~70%。为了实现对这些电控单元的软件开发调试、数据标定、文件更新和故障修复,…

【电路理论四】正弦电流电路

正弦电流 正弦量是随时间按正弦规律变动的电路变量。 随时间按正弦规律变动的电流称为正弦电流。 正弦电流的瞬时值表达式: 称为正弦电流的三要素。 分别为振幅/幅值,角频率,初相。 幅值为正弦电流的最大值,恒为正。 为正弦电…

解决Windows无法同时使用有线网和无线网WIFI的问题

参考资料 电脑无线网wifi和有线网同时使用(内网外网同时使用)用route命令解决Wifi和网卡不能同时上内外网问题 解决方法 对于Windows系统同时连接有线网和无线网Wifi时,只会有一个网关生效,因此我们需要手动通过route命令设置网…

FOC控制原理-ADC采样时机

0、文章推荐 SimpleFOC移植STM32(五)—— 电流采样及其变换_极对数对电流采样的影响-CSDN博客 FOC 电流采样方案对比(单电阻/双电阻/三电阻) - 知乎 (zhihu.com) FOC中的三种电流采样方式,你真的会选择吗?…

uniapp:编译微信、h5都正常的,编译钉钉小程序无法找到页面

我们在做uniapp的开发的时候遇到很多莫名其妙的问题,其中就有个很奇葩的问题,我们开发的过程中使用微信小程序/h5调试都是正常编译正常跳转,然后在要上架的时候,编译钉钉小程序成功,但是访问页面无法访问, …

zentao ubuntu上安装

#下载ZenTaoPMS-21.2-zbox_amd64.tar.gz(https://www.zentao.net/downloads.html) https://dl.zentao.net/zentao/21.2/ZenTaoPMS-21.2-zbox_amd64.tar.gzcd /opt tar -zxvf ZenTaoPMS-21.2-zbox_amd64.tar.gz#启动 /opt/zbox/zbox start /opt/zbox/zbox…

REDIS2.0

string list hash set 无序集合 声明一个key,键里面的值是元素,元素的类型是string 元素的值是唯一的,不能重复 多个集合类型之间可以进行并集,交集,集查的运算 sadd test1 a b c c d :添加5个元素&am…

【论文阅读】DebSDF:深入研究神经室内场景重建的细节和偏差

【论文阅读】DebSDF:深入研究神经室内场景重建的细节和偏差 Abstract3.METHOD3.1 Preliminaries3.2 Uncertainty Guided Prior Filtering3.3 Uncertainty-Guided Ray Sampling3.4 Uncertainty-Guided Smooth Regularization3.5 Bias-aware SDF to Density Transform…

golang,多个proxy拉包的处理逻辑

在Go语言中,当你设置了多个代理(GOPROXY)时,Go工具链会按照你设置的顺序尝试每个代理。如果第一个代理失败,它会尝试下一个代理,直到成功获取到模块或者所有代理都尝试失败。最后,如果所有代理都…

微服务SpringCloud分布式事务之Seata

视频教程:https://www.bilibili.com/video/BV16P63Y3ESq 效果演示 准备的微服务项目调用的链路如下: 文字描述: gateway模块接收到请求,并发送到order订单模块order订单模块接收到请求,新增一个订单数据后发送一个…

Pyhton知识分享-利用KNN算法实现手写数字识别

利用KNN算法实现手写数字识别 MNIST手写数字识别 是计算机视觉领域中 "hello world"级别的数据集 1999年发布,成为分类算法基准测试的基础随着新的机器学习技术的出现,MNIST仍然是研究人员和学习者的可靠资源。 本次案例中,我们的…

多点通信、流式域套接字

一、广播 1.1广播的发送端模型&#xff1a; #include<myhead.h>#define BEN_IP "192.168.191.129" #define BEN_PORT 8888#define PORT 6666int main(int argc, const char *argv[]) {int oldfd socket(AF_INET,SOCK_DGRAM,0);if(oldfd -1){perror("soc…

AMBA-APB

目录 1.APB 协议 2.APB信号列表 3.数据传输 3.1写传输&#xff08;2种&#xff09; 3.1.1 无等待状态的写传输 3.1.2有等待状态的写传输 3.2写选通信号 (PSTRB) 字节通道映射 3.3读传输&#xff08;2种&#xff09; 3.3.1 无等待状态的读传输 3.3.2有等待状态的读传…

linux自动化一键批量检查主机端口

1、准备 我们可以使用下面命令关闭一个端口 sudo iptables -A INPUT -p tcp --dport 端口号 -j DROP我关闭的是22端口&#xff0c;各位可以关其它的或者打开其它端口测试&#xff0c;谨慎关闭22端口&#xff01;不然就会像我下面一样握手超时&#x1f62d;&#x1f62d;&…