public void release ( Collection < MemorySegment > segments ) { if ( segments == null ) { return ; } // -------------------- BEGIN CRITICAL SECTION ------------------- synchronized ( lock ) { if ( isShutDown ) { throw new IllegalStateException ( "Memory manager has been shut down." ) ; } // since concurrent modifications to the collection // can disturb the release, we need to try potentially multiple times boolean successfullyReleased = false ; do { final Iterator < MemorySegment > segmentsIterator = segments . iterator ( ) ; Object lastOwner = null ; Set < MemorySegment > segsForOwner = null ; try { // go over all segments while ( segmentsIterator . hasNext ( ) ) { final MemorySegment seg = segmentsIterator . next ( ) ; if ( seg == null || seg . isFreed ( ) ) { continue ; } final Object owner = seg . getOwner ( ) ; try { // get the list of segments by this owner only if it is a different owner than for // the previous one (or it is the first segment) if ( lastOwner != owner ) { lastOwner = owner ; segsForOwner = this . allocatedSegments . get ( owner ) ; } // remove the segment from the list if ( segsForOwner != null ) { segsForOwner . remove ( seg ) ; if ( segsForOwner . isEmpty ( ) ) { this . allocatedSegments . remove ( owner ) ; } } if ( isPreAllocated ) { memoryPool . returnSegmentToPool ( seg ) ; } else { seg . free ( ) ; numNonAllocatedPages ++ ; } } catch ( Throwable t ) { throw new RuntimeException ( "Error removing book-keeping reference to allocated memory segment." , t ) ; } } segments . clear ( ) ; // the only way to exit the loop successfullyReleased = true ; } catch ( ConcurrentModificationException | NoSuchElementException e ) { // this may happen in the case where an asynchronous // call releases the memory. fall through the loop and try again } } while ( ! successfullyReleased ) ; } // -------------------- END CRITICAL SECTION ------------------- }
Tries to release many memory segments together .