以下用我之前代码中的一个bug作为说明,解释如何实现代码在运行期的问题检查。
首先,我们先定义一下待检查的问题。故障代码如下:
// Invocator...
try {
channel = new TcpChannel(SocketChannel.open(), new InetSocketAddress("127.0.0.1", 5656));
} catch (Exception ex) {
if (channel != null) {// **
channel.cleanup(); // Error prone?
}
throw ex;
}
// TcpChannel.java
public TcpChannel(SelectableChannel channel, SocketAddress addr) throws IOException
{
boolean done = false;
Selector selector = null;
try {
selector = Selector.open();
key = channel.register(selector, op);
// ...
done = true;
} finally {
if (!done) {
cleanup(); // Close all resources
}
}
connect(addr); // * IOException ?
}
void cleanup()
{
try {
key.selector().close();
key.channel().close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void connect(SocketAddress addr) throws IOException
// ...
这个问题是在使用SocketChannel的时候,没有正确地关闭,导致系统资源(文件句柄)泄漏。具体是由于connect(addr);*操作可能产生IOException错误,所以channel可能会构造失败,从而不能执行Exception子句**中的资源回收,造成的句柄外泄。但由于代码里明确写明了SocketChannel的打开和关闭,所以仅从静态的代码审查角度来看,很难发现这个错误。所以我们可以在这里采用对运行中的代码调用指定检查逻辑的方法以发现这种问题。
首先,还是要建立我们的判断逻辑。
public final class SelectorOp
{
private SelectorOp() {}
public static Selector open() throws IOException
{
Selector selector = Selector.open();
System.out.println(selector + "\topened!");
return selector;
}
public static void close(Selector selector) throws IOException
{
System.out.println(selector + "\tclosed!");
selector.close();
}
}
这里,如果要新建一个Selector,则调用SelectorOp.open()代理方法,完成对原有Selector.open()方法的调用,并记录被创建的Selector;如果要关闭Selector,也需要调用SelectorOp.close(selector)代理方法,完成对selector对象自身close()方法的调用,并记录。
这个例子只是一个问题检查的简化说明,只具有实验意义。对于真正的应用来说,可以考虑把这些事件记录在类似于Map这样的容器中,并收集事件发生的时间和代码行,以便做进一步的对比和分析。
接下来,我们要实现自己的ClassLoader。具体的代码见附件,这里仅拣要点说明。
public FileClassLoader(String[] classPaths) {
for (String path : classPaths) {
File file = new File(path);
if (file.exists() && file.canRead()) {
if (file.isFile() && file.getName().endsWith(".jar")) {
loadJar(file);
} else if (file.isDirectory()) {
loadPath(file, "");
}
}
}
}
FileClassLoader可以处理单个文件,也可以处理jar包。不论对于哪种方式,都是添加类名->实际存放位置的映射关系。之后,在需要的时候获取类的二进制字节数组,转换为Class。
最后,我们要实现类结构的访问和修改工具,见下:
public void visitMethodInsn(int opcode, String owner, String name, String desc)
{
final String OWNER = "java/nio/channels/Selector";
final String MOCK = "mock/SelectorOp";
final String DESC1 = "()Ljava/nio/channels/Selector;";
final String DESC2 = "(Ljava/nio/channels/Selector;)V";
if (opcode == INVOKESTATIC && OWNER.equals(owner) && "open".equals(name) && DESC1.equals(desc)) {
super.visitMethodInsn(opcode, MOCK, name, desc);
} else
if (opcode == INVOKEVIRTUAL && OWNER.equals(owner) && "close".equals(name) && "()V".equals(desc)) {
super.visitMethodInsn(Opcodes.INVOKESTATIC, MOCK, name, DESC2);
} else {
super.visitMethodInsn(opcode, owner, name, desc);
}
}
如果发现了对Selector的open静态方法调用,则转为调用SelectorOp的open静态方法;如果发现了对Selector对象的close调用,则转为调用SelectorOp的close静态方法,入参为Selector对象。
执行结果如下:
图中可以很容易发现,Selector只有开放,没有关闭。
但修改过代码之后,再次执行则结果如下:
每个Selector对象都正确地开放和关闭了。
- 大小: 15.8 KB
- 大小: 14.7 KB
分享到:
相关推荐
通过分析和运行这些代码,您可以深入理解风速数据的处理流程,并掌握如何将这些方法应用于其他气象参数。 总之,"【气象水文】以最大风速为例进行风速均一化订正(附代码+数据).zip"为气象学者和研究人员提供了一...
根据标题“基于国产BMC 的服务器安全启动技术研究与实现.pdf”和描述中提及的“法律法规”,可以推断本文研究的内容涉及服务器安全领域,特别是国产基础管理控制器(Baseboard Management Controller,简称BMC)在...
淘淘商城项目是一个模仿淘宝商城开发的电子商务平台,它的第17期源代码包含了该项目在这一阶段的完整开发内容。这个压缩包中的“czbk”可能是项目团队或某个功能模块的代号,暗示了该版本可能针对特定的功能或优化...
3. 动静结合测试方法:动态测试(Dynamic Testing)是指在运行时检查程序的行为,而静态分析(Static Analysis)则是在不运行代码的情况下检查代码结构。结合这两种方法可以更加全面地分析和测试程序,从而提高测试...
1. 面向切面编程(AOP)的核心概念与实现机制:AOP通过在编译期或运行期动态地织入切面来实现对业务逻辑的增强,其核心元素包括切点(Pointcut)、通知(Advice)、连接点(Join point)、方面(Aspect)等。...
10. **枚举与注解**:枚举类型提供了一种安全的方式来表示固定的常量集合,注解则为编译器和JVM提供了元数据,用于自定义编译期和运行期的行为。 11. **反射与动态代理**:反射允许程序在运行时检查和操作类、接口...
静态分析是指在不运行代码的情况下检查代码,寻找潜在的安全威胁。常用的方法包括: - **代码审计**:对源代码进行审查,查找不安全的编码实践和潜在的安全漏洞。 - **自动化扫描工具**:使用静态代码分析工具,如...
自动化程序调试是软件开发过程中的一个重要环节,它涉及使用计算机程序自动检查、定位并修复程序代码中的错误或缺陷。随着软件工程的发展,自动化调试技术不断进步,它能够提高开发效率,减少人工调试的繁琐性和时间...
静态存储分配是在编译时进行的,它为全局变量和static变量分配内存,这块内存的生命周期贯穿整个程序运行期。栈分配则在函数执行时进行,函数内部的局部变量和参数的存储单元在栈上创建,函数运行结束时这些存储单元...
通过运行提供的Matlab代码,用户可以观察算法在不同测试函数上的表现,了解罚函数法和PSO的结合如何改善优化结果。此外,用户还可以根据具体需求调整算法参数,如罚函数的参数、粒子群的规模、学习因子等,以适应...
在处理心电信号时,这样的脚本会加载数据、应用去噪方法、运行R波检测,并可能进行一些可视化操作,以便用户检查结果的准确性。它可能包含了预处理步骤,如使用滤波器(如 Butterworth 或 Chebyshev 滤波器)去除...
通过深入研究Windows平台上的泛型反利用技术,我们不仅了解了当前可用的防御措施,还预见了未来发展的潜力。然而,正如论文所指出的,任何单一的技术都不可能完全解决所有安全问题。因此,构建一个全面、多层次的...
4. **异常处理机制:** 设计合理的错误捕获与处理逻辑,确保系统在遇到问题时能够稳定运行。 #### 五、论文与开题报告要点 - **研究背景与意义:** 阐述药品库房管理的重要性及其对药品质量和企业经济效益的影响。 ...
- **运行期动态代理模式**:如Spring AOP和JBoss AOP,通过动态创建代理对象来实现在运行时拦截方法调用并插入横切逻辑。 #### 四、Spring与Hibernate **Spring提供容器的声明性事务管理**:Spring框架允许开发者...
《ASP体育城场地预约系统的设计与实现》是一个基于ASP技术的在线预约平台,旨在解决体育设施利用率低、预约不便的问题。该系统集成了用户管理、场地展示、预约操作、时间管理等多个功能模块,为体育爱好者提供了便捷...
在计算机安全领域,"壳子程序"(Shellcode)通常指的是注入到目标进程内存中的小段代码,用于执行特定的任务,如绕过权限检查或执行恶意操作。然而,这里的"壳子程序"是指一种对可执行文件进行保护的技术,尤其是...
WebForm+SSO源代码项目是一个基于ASP.NET WebForm技术实现的单点登录(Single Sign-On,简称SSO)解决方案。这个项目包含了Server端和Client端的所有必要组件,旨在简化用户在多应用系统间的登录流程,提高用户体验...