UF.JNDI

UF (Use Freed) 指摘は、リソースが解放された後にリソースを使用する試みがある場合に報告されます。警告 UF.JNDI は、JNDI コンテキストが閉じられた後にこのコンテキストの使用を試みていることを示します。

例 1

コピー
     public void scan(Name name, String... filters) {
         try {
             DirContext ctx = initContext();
             try {
                 for (final String filter : filters) {
                     search(name, filter, ctx);
                 }
             } finally {
                 ctx.close();
             }
         } catch (NamingException e) {
             e.printStackTrace();
         }
     }
 
     private DirContext initContext() throws NamingException {
         Hashtable env = new Hashtable(11);
         env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
         env.put(Context.PROVIDER_URL, "ldap:///o=JndiSample,dc=example,dc=com");
 
         DirContext ctx = new InitialDirContext(env);
         return ctx;
     }
 
     private void search(Name name, String filter, DirContext ctx) throws NamingException {
         try {
             final SearchControls searchControls = new SearchControls();
             searchControls.setReturningAttributes(necessaryItemAttributes);
             searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
             final NamingEnumeration<SearchResult> resultNamingEnumeration = ctx.search(name, filter, searchControls);
         } catch (NamingException e) {
             ctx.close();
         }
     }

UF.JNDI が 30 行目のスニペットについて報告されています。JNDI コンテキスト 'ctx' がメソッド 'scan' の for サイクルでアクセスされています (54 行目を参照)。ところが、56 行目のメソッド 'search' で例外が発生した場合、繰り返しのいずれかで 'ctx' が先に閉じられる可能性があります。

例 2

コピー
     public void scan(Name name, String... filters) {
         try {
             DirContext ctx = initContext();
             try {
                 for (final String filter : filters) {
                     search(name, filter, ctx);
                 }
             } finally {
                 ctx.close();
             }
         } catch (NamingException e) {
             e.printStackTrace();
         }
     }
 
     private DirContext initContext() throws NamingException {
         Hashtable env = new Hashtable(11);
         env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
         env.put(Context.PROVIDER_URL, "ldap:///o=JndiSample,dc=example,dc=com");
 
         DirContext ctx = new InitialDirContext(env);
         return ctx;
     }
 
     private void search(Name name, String filter, DirContext ctx) throws NamingException {
         final SearchControls searchControls = new SearchControls();
         searchControls.setReturningAttributes(necessaryItemAttributes);
         searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
         final NamingEnumeration<SearchResult> resultNamingEnumeration = ctx.search(name, filter, searchControls);
     }

前節のスニペットが修正されています。メソッド 'search' ではストリームを閉じないようになっています。'scan' メソッドで閉じられるようになりました。このメソッドは、このストリームを開いたメソッドです。一般に、リソースを最初に割り当てたメソッドと同じメソッドでリソースを解放するのが好ましいコーディング手法です。