Java类初始化阶段静态初始化不抛出异常

在重构一个项目时,发现一个Java类在静态初始化阶段没有抛出预期的ClassNotFound异常。通过逐步排查,发现在静态初始化块中的代码在单独执行时会抛出异常,但当它作为类加载的一部分时,异常被忽略了。原因可能是Java类加载时静态初始化的异常处理机制,构造函数和静态初始化都不能直接抛出异常。解决方法是将静态初始化的代码移至构造函数外的单独方法中,确保异常能被正确处理。此外,项目A与项目B的依赖配置差异导致了类找不到的问题,项目A包含了所有必需的Hadoop jar包,而项目B只添加了部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近接手实习生写的一个项目A,主要是往HDFS里写文件,因为项目比较急所以代码写的很乱,我就顺便新建个项目B重构一下。

其中把对HDFS的操作封装成了一个类:

public class HDFS {
	private static final String HDFS_ADDR = Config.HDFS_PATH;
	private static FileSystem fs;
	static {
		Configuration configuration = new Configuration();
		configuration.set("dfs.replication", Config.REPLICATION);
		configuration.set("fs.defaultFS", HDFS_ADDR);
		try {
			fs = FileSystem.get(URI.create(HDFS_ADDR), configuration);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	private Path path;
	private FSDataOutputStream out;

	public HDFS(String file) {
		if (file != null && file.length() > 0) {
			init(file);
		}
	}
        .....
}

供其他模块调用,我在重构时候基本就照搬了这一块,后来发现我的程序每次执行

new HDFS(string);
的时候就停止了,也没报错。

Debug的话在构造函数第一行打印语句都不执行,那么说明不是构造函数本身的问题,回想起之前看的类的生命周期,在构造函数之前那就是初始化阶段了,也就是类加载时候自动执行的。

于是我就把目光集中在静态初始化阶段,依旧是靠打印语句,在

Configuration configuration = new Configuration();
之前是可以打印的,后面的就不行,可这么简单一句能有什么问题呢?而且明明他的程序是可以运行的,也就是客户端代码应该是没问题。

为了验证这一点,我又新建了一个空项目C,然后把静态初始化这段代码放到main里面执行,然后马上就抛出ClassNotFound异常了:

显示是在new Configuration的时候抛出的,我看了一眼依赖的库,确实是没有的,但是之前我的工程B也没有抛出异常啊,这两个工程BC导入的库是一样的。

唯一一种可能就是:原来的工程B本应该报错却没报,这也太不正常了,找不到类是Java常见的异常之一啊,怎么可能忽视呢?

这时候我想起了之前看effective系列的时候一条经验,说是不要在构造函数里面做太多事,而是单独写一个init()来做初始化的工作,因为构造函数中不能抛异常。

莫非是因为这个问题,连构造函数都不能抛异常,更别说有更高优先级的静态初始化了,于是我把静态初始化这段改成了这样:

static {
		try {
			Configuration configuration = new Configuration();
			configuration.set("dfs.replication", Config.REPLICATION);
			configuration.set("fs.defaultFS", HDFS_ADDR);
			fs = FileSystem.get(URI.create(HDFS_ADDR), configuration);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

马上就抛出异常了,至此证明确实是之前就有错。

然后说一下为什么新建的B工程缺少类而A工程不缺,新建工程的过程中有一个步骤就是导入依赖的jar包,之前的项目A是吧hadoop/share目录下所有的jar全添加进来了,我为了图省事,只加了几个common和core的jar:



所以自然就报错了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值