RLK.JNDI
如果资源经过分配,但使用后未得到妥当处置,将报告 RLK(资源泄漏)问题。未能正确处置资源可能导致如下的问题:
- 打开太多文件
- 应用程序无法在需要时访问临时文件
RLK.JNDI 警告表明 JNDI 上下文未在退出时关闭。
漏洞与风险
流、连接以及图形对象之类的资源必须明确关闭。关闭操作可以取消对事务的拦截,或将文件更改刷新到文件系统中。虽然资源最终会被垃圾回收器关闭,但可能在启动垃圾回收之前就已经耗尽资源。根据资源的不同性质,如果对分配其他资源的尝试失败,将引发各种不同的异常,例如 java.io.FileNotFoundException:打开的文件过多,或数据库连接过多。
缓解与预防
明确关闭所有具有关闭方法的资源,即使您认为不重要的资源亦应如此。这样将避免未来更改代码时出现这类错误。
示例 1
复制
public NamingEnumeration<SearchResult> search(final String providerURL,
final String name,
final String filter,
final SearchControls cons) {
try {
Hashtable environment = new Hashtable();
environment.put(INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
environment.put(Context.PROVIDER_URL, providerURL);
environment.put(Context.SECURITY_AUTHENTICATION, SECURITY_AUTHENTICATION);
InitialLdapContext context = new InitialLdapContext(environment, null);
NamingEnumeration<SearchResult> result = context.search(name, filter, cons); // Resource allocated
return result;
} catch (NamingException e) {
System.err.println("LDAP search failed: " + e.getMessage());
}
return null;
}
针对第 34 行的代码段报告 RLK.JNDI:JNDI 上下文“context”未在退出时关闭。
示例 2
复制
public NamingEnumeration<SearchResult> search(final String providerURL,
final String name,
final String filter,
final SearchControls cons) {
try {
Hashtable environment = new Hashtable();
environment.put(INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
environment.put(Context.PROVIDER_URL, providerURL);
environment.put(Context.SECURITY_AUTHENTICATION, SECURITY_AUTHENTICATION);
InitialLdapContext context = new InitialLdapContext(environment, null); // Resource allocated
try {
NamingEnumeration<SearchResult> result = context.search(name, filter, cons);
return result;
} finally {
context.close(); // Resource released
}
} catch (NamingException e) {
System.err.println("LDAP search failed: " + e.getMessage());
}
return null;
}
来自之前部分的代码段经过了修复;在此不会报告 RLK.JNDI。
扩展
此检查器可通过 Klocwork 知识库进行扩展。有关详情,请参阅调整 Java 分析。