Preventing SPTerm Memory Leaks

Some uses of SPTerm will leak memory on the Prolog side. This happens if a new SPTerm object is allocate, but Java neither returns to Prolog nor backtracks (using the method close, cut or nextSolution) into a query opened before the allocation of the SPTerm object.

As of SICStus 3.8.5, it is possible to explicitly delete a SPTerm object using the SPTerm.delete() method. The delete() method invalidates the SPTerm object and makes the associated SP_term_ref available for re-use.

Another way to ensure that all SP_term_refs are deallocated is to open a dummy query only for this purpose. The following code demonstrates this:

     // Always synchronize over creation and closing of SPQuery objects
     synchronized (sp) {
         // Create a dummy query that invokes true/0
         SPQuery context = sp.openQuery("user","true",new SPTerm[]{});
         // All SP_term_refs created after this point will be reclaimed by
         // Prolog when doing context.close() (or context.cut())
     
         try {           // ensure context is always closed
             SPTerm tmp = new SPTerm(sp); // created after context
             int i = 0;
     
             while (i++ < 5) {
                 // re-used instead of doing tmp = new SPTerm(sp,"...");
                 tmp.putString("Iteration #" + i + "\n");
                 // e.g. user:write('Iteration #1\n')
                 sp.queryCutFail("user", "write", new SPTerm[]{tmp});
             }
         }
         finally {
             // This will invalidate tmp and make Prolog
             // reclaim the corresponding SP_term_ref
             context.close(); // or context.cut() to retain variable bindings.
         }
     }