Java后端 - 常见BUG及其处理策略(持续更新)

编译时错误

Maven包dependency报红

  • 依赖中有付费包 => 叫同事发你一份,复制到repository包的指定目录结构的相应位置
  • 依赖中有私包 => 叫同事发你一份settting.xml文件,并修改maven的settting文件包路径

还有就是假报错,如果项目能运行启动就不用管它是否爆红。

编译项目时显示out of memory,但是电脑的内存是足够 或者 Error:java: Compilation failed: internal java compiler error

原因是idea默认给的build project的heap内存不够大,修改下图箭头位置的数值即可。 具体修改位置为: File => setting => Build,Execution,Deployment => Compiler => Shared build process heap size(Mbytes):

Error:java: Compilation failed: internal java compiler error

可能的原因是: 上面的堆内存分配不足 或者 IDE配置的项目JVM版本与JDK版本不一致 修改的地方有:

  • File => Project Structure => Module 检查每个模块是否合理,一般都是使用1.8的,如果出现1.5或者11等,则修改回来即可

  • File => Settings => Build,Execution,Deployment => Compiler => Java Compiler,这里也是检查一下每个模块是否合理

运行时异常

NPE - 空指针异常(Null pointer Exception)

一个优秀的攻城狮必须要避免空指针异常导致的程序不能运行的问题,对于该if进行判断的一定要进行判断。

有现成的工具类就用现成的,自己写很可能漏掉判断逻辑。

  • 对象判空:使用ObjectUitls来判断对象是否为空。
  • 数组判空:使用CollectionUtils来判断是否为空。
  • 字符串判空:使用StringUtils来判断是否为空或者字符串是否为空字符串。
  • 字符串和魔法值比较:比较"rainxxbow"和values,不要写成values.equals("rainxxbow"),如果你没有对values进行判空,则会出现NPE问题,好的习惯是写成"rainxxbow".equals(values)(其实这里也有问题,不要直接魔法值,而是写成一个静态常量或者枚举更好)

NFE - 字符串转换为数字异常(Java.lang.NumberFormatException)

场景

当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常.如现在讲字符型的数据"123456"转换为数值型数据时,是允许的。但是如果字符型数据中包含了非数字型的字符,如123#56,此时转换为数值型时就会出现异常。系统就会捕捉到这个异常,并进行处理。

解决方案

  • 限制好前端的输入 或者 数据字段的格式
  • 对String类型的数据进行判断是否存在非数值的内容,否则不进行处理(try ... catch ...)

CCE - 类型转换异常(ClassCastException)

FNFE - 文件未找到异常(Java.lang.FileNotFoundException)

场景: 当程序试图打开一个不存在的文件进行读写时将会引发该异常。该异常由FileInputStream,FileOutputStream,RandomAccessFile的构造器声明抛出,即使被操作的文件存在,但是由于某些原因不可访问,比如打开一个只读文件进行写入,这些构造方法仍然会引发异常。

解决: 手动查看文件是否存在 或者 查看文件是否符合文件读写要求

AOE - 访问越界异常(ArrayIndexOutOfBoundException)

场景

  • 访问不存在的索引:当你尝试访问数组中一个不存在的索引时,比如数组长度为5,却尝试访问索引6或更大数据时,就会抛出这个异常。数组的合法索引范围是0到数组长度减1。
  • 循环条件错误:在遍历数组的循环中,如果循环条件设置不当,可能导致索引超出数组边界。例如,使用<=而不是<作为终止条件。
  • 动态数组操作不当:在动态改变数组内容时(如添加或删除元素),如果没有正确调整后续的索引访问,可能会导致越界。
  • 初始化错误:数组没有正确初始化,或者初始化时的大小设置不正确,然后尝试访问其中的元素。

解决方案

解决ArrayIndexOutOfBoundsException的方法包括:

  • 检查索引边界:在访问数组元素前,总是检查索引是否在有效范围内。可以使用条件语句确保索引index >= 0 && index < array.length。
  • 使用循环时小心边界:确保循环迭代时不会超过数组的最后一个元素。例如,使用for(int i = 0; i < array.length; i++)而不是i <= array.length。
  • 初始化数组时指定正确大小:确保数组在创建时就给予合适的大小,如果数组大小可能变化,考虑使用动态数据结构如ArrayList。
  • 异常处理:使用try-catch语句块捕获ArrayIndexOutOfBoundsException,并在catch块中处理异常情况,比如提供错误提示或进行安全的回退操作。
  • 代码审查和测试:在代码审查阶段注意检查所有数组访问的边界条件,同时编写单元测试,特别是边界条件测试,确保数组操作的安全性。
  • 使用工具辅助:利用IDE的静态代码分析功能,可以帮助提前发现可能的数组越界问题。

通过以上措施,可以有效预防和解决ArrayIndexOutOfBoundsException问题,提升代码的健壮性和可靠性。

CNFE - 类未找到异常(ClassNotFoundException)

场景

ClassNotFoundException(类未找到异常)**在Java中出现的情况主要是当Java虚拟机(JVM)尝试加载一个特定的类,但是找不到对应的.class文件时。**这意味着类没有被包含在类路径(class path)中,或者类加载器无法访问到这个类。这类异常通常发生在以下几种情境:

  • 类名拼写错误:确保在代码中引用的类名与实际的类名完全一致,包括大小写。
  • 类路径问题:检查项目的类路径设置,确保所有需要的类文件和JAR包都被包含进来。可以通过调整IDE的配置,或者在命令行使用java -cp来指定正确的类路径。
  • 依赖管理不当:如果你的项目依赖于外部库,确保所有必要的依赖都已经被正确安装并且版本兼容。使用构建工具如Maven或Gradle可以帮助自动管理这些依赖。
  • 类文件不存在:确认相关的.class文件或JAR包实际上存在于预期的位置。
  • 类加载器问题:在某些复杂的环境中,如使用了自定义类加载器,确保类加载机制正确无误。
  • 访问权限问题:确保JVM有足够的权限访问类文件,特别是在类文件位于受保护的目录或网络资源上时。

解决方案

  • 核对类名拼写:仔细检查并修正类名拼写。
  • 检查类路径:确保类路径设置正确,必要时重新配置。
  • 验证依赖:使用构建工具确保所有依赖都已正确下载和链接。
  • 确认类文件存在:通过文件浏览器或命令行确认类文件的实际位置和存在性。
  • 检查类加载器逻辑:如果使用了自定义类加载器,检查其实现逻辑。

Mybatis-plus框架的count优化问题

场景

时间:2024-06-27 需求:添加一个Excel导入功能,可以批量添加数据 需求很简单,很快做完,但是查询出问题了。(心里ps:wtf,我搞个导入和批量插入,关查询什么问题,什么bug突然扣我头上了?)

本来是一对多的数据,但是总数只显示总表的数据个数

日志如下: 很明显,count的SQL并没有联表的部分,导致只查询总表的数据个数,进而导致分页出现问题。

一番摸索后,查看源码,发现count方法会对比联表的表字段有没有在where后面用到,如果没有就会被优化掉,进而出现这个总数不对的问题。

解决方案

  1. 禁用count优化
java 复制代码
Page<Xxxx> xxx= new Page<>(pageQuery.getPage(), pageQuery.getSize());
// 禁用count优化
pdmProcessRecordVoPage.setOptimizeCountSql(false);
Page<Yyyy> yyyy= ZzzMapper.getData(xxx);
  1. 禁用Mybatis-plus的count方法,使用自己写的count方法
java 复制代码
Page<Xxxx> xxx= new Page<>(pageQuery.getPage(), pageQuery.getSize());
pdmProcessRecordVoPage.setOptimizeCountSql(false);
pdmProcessRecordVoPage.setSearchCount(false);
Page<Yyyy> yyyy= ZzzMapper.getData(xxx);

方案对比

直接禁用count优化更好一点

  • 不用再去查询一次SQL获取TOTAL值
  • 不用在写/复制SQL导致SQL冗余问题

综上: 选择禁用count优化

如何快速定位问题并解决?

整体步骤

  1. 先根据出现的问题或者反馈的bug,大致区分是前端问题还是后端问题
  2. 然后按照是哪个具体步骤可能的问题进行深入分析 或者 根据经验和业务,边界定位法

辅助:

  1. debug
  2. 打日志,在关键节点打日志或者在catch里面
相关推荐
Victor35612 分钟前
MongoDB(87)如何使用GridFS?
后端
Victor35615 分钟前
MongoDB(88)如何进行数据迁移?
后端
小红的布丁32 分钟前
单线程 Redis 的高性能之道
redis·后端
GetcharZp37 分钟前
Go 语言只能写后端?这款 2D 游戏引擎刷新你的认知!
后端
宁瑶琴2 小时前
COBOL语言的云计算
开发语言·后端·golang
普通网友2 小时前
阿里云国际版服务器,真的是学生党的性价比之选吗?
后端·python·阿里云·flask·云计算
IT_陈寒3 小时前
Vue的这个响应式问题,坑了我整整两小时
前端·人工智能·后端
Soofjan4 小时前
Go 内存回收-GC 源码1-触发与阶段
后端
shining4 小时前
[Golang]Eino探索之旅-初窥门径
后端
掘金者阿豪4 小时前
Mac 程序员效率神器:6 个我每天都在用的 Mac 工具推荐(Alfred / Paste / PixPin / HexHub / iTerm2 /)
后端