class文件替换要注意,java.lang.noSuchMethodError

有时候我们替换.class文件时只会把我们改过的文件替换了,如果我们替换的文件有其他调用的文件编码也发生了变化而我们没有替换的话程序往往会报错,java.lang.noSuchMethodError就是最容易被我们忽视的错误,像是后台跑批任务时如果有TimerTask作为监控时时跑批时,在实现类方法体发生变化时我们单独更新class文件而不是全部更新的时候,继承的TimerTask类对应的run方法类也要相应更新,不然就会报错。

举例说明:

mainserver.java

public class MainServer {

public static void main(String[] args) {

ApplicationContext context = ApplicationContextUtils.getContext();

ExecuteServerService executeServerService = (ExecuteServerService) context.getBean("executeServerServiceImpl");

executeServerService.startExecuteServer();

}

}

ExecuteServerService.java

public void startExecuteServer() {

this.init();

long scanTimespace = getInstanScanTimespace();

timer.schedule(new TimerTask() {

@Override

public void run() {

try {

count = 0;

//执行任务方法

executeJob();

} catch (Exception e) {

logger.error("执行失败!", e);

e.printStackTrace();

}

}

}, new Date(), scanTimespace);

}

在这里是用TimerTask来监控的。

如果我因为要区别执行任务想要给任务一个分类的话,我会这么改:

mainserver.java

public class MainServer {

public static void main(String[] args) {

ApplicationContext context = ApplicationContextUtils.getContext();

ExecuteServerService executeServerService = (ExecuteServerService) context.getBean("executeServerServiceImpl");

executeServerService.startExecuteServer("XXX");

}

}

ExecuteServerService.java

public void startExecuteServer(final String id) {

this.init();

long scanTimespace = getInstanScanTimespace();

timer.schedule(new TimerTask() {

@Override

public void run() {

try {

count = 0;

//执行任务方法

executeJob(id);

} catch (Exception e) {

logger.error("执行失败!", e);

e.printStackTrace();

}

}

}, new Date(), scanTimespace);

}

这里虽然是同一个方法,但是参数发生了变化,在编译为class文件时字节码就会发生变化,因为TimerTask是监控该任务的它会相应的生成一个继承类里面包含run方法来定时的执行这个实现类,所以相应的TimerTask这个继承类的字节码也发生了变化,也要进行替换,否则就会报java.lang.noSuchMethoderror.