What does

write $SYSTEM.Util.GetEnviron("JAVA_HOME")

return in the same process as JavaGateway?

If not /usr/java/jdk1.8.0_65 you might need to restart the InterSystems IRIS instance.

Your OS user can be determined by running:

write $system.Process.UserName()

again it's important to run this code in the same process as Java Gateway.

After you determined effective OS username you can check folder/executable permissions.

Finally, SELinux if enabled might require additional configuration.

If records are never deleted and you're okay with a few misses, use ExtentSizeFast, if you need the fastest precise runtime implementation use ExtentSize, in you need better compile speed and don't care about runtime speed use GetExtentSize.

/// w ##class(Utils.Persistent).GetGlobal("Utils.Persistent")
ClassMethod GetDataGlobal(Class As %Dictionary.CacheClassname) As %String
{
    Quit:'$$$comClassDefined(Class) ""
    Set Strategy = $$$comClassKeyGet(Class, $$$cCLASSstoragestrategy)
    Quit $$$defMemberKeyGet(Class, $$$cCLASSstorage, Strategy, $$$cSDEFdatalocation)
}

/// w ##class(Utils.Persistent).ExtentSizeFast("Utils.Persistent")
ClassMethod ExtentSizeFast(Class As %Dictionary.CacheClassname) As %String [ CodeMode = expression ]
{
$Get(@..GetDataGlobal(Class), 0)
}


/// w ##class(Utils.Persistent).GetExtentSize("Utils.Persistent")
ClassMethod GetExtentSize(Class As %String) As %Integer
{
    Set Global = ..GetDataGlobal(Class)
    Quit:Global="" 0
   
    Set Id = $Order(@Global@(""))
    Set Count = 0
    While Id '= "" {
        Set Id = $Order(@Global@(Id))
        Set Count = Count + 1
    }
    Quit Count
}

ClassMethod ExtentSize() As %Integer [ CodeMode = objectgenerator ]
{
    set Strategy = $$$comClassKeyGet(%classname, $$$cCLASSstoragestrategy)
    set Global = $$$defMemberKeyGet(%classname, $$$cCLASSstorage, Strategy, $$$cSDEFdatalocation)
    Do %code.WriteLine(" Set Id = $Order(" _ Global _ "(""""))")
    Do %code.WriteLine(" Set Count = 0")
    Do %code.WriteLine(" While Id '= """" {")
    Do %code.WriteLine("     Set Id = $Order(" _ Global _ "(Id))")
    Do %code.WriteLine("     Set Count = Count + 1")
    Do %code.WriteLine(" }")
    Do %code.WriteLine(" Quit Count")
    Quit $$$OK
}

$STORAGE is a special variable which contains the number of bytes available for a current process. After it hits zero you get STORE error. You can profile your code to see which part leaks memory. Small example:

write $STORAGE
>268326112
set i=1
write $STORAGE
>268326104
kill i
write $STORAGE
>268326112

Check that:

  • $storage before and after EvaluateClone call is the same
  • $storage on each loop cycle is the same

Another approach is throwing/catching and logging an exception and checking what's available in each frame.

do clone.Children.RemoveAt(key) // update clone

RemoveAt returns oref, maybe you need to kill it.

I'm wondering if IS has a java-like garbage collector (as in "the object is automatically destroyed"), and if so, is this keeping up with the clone construction and killing, over a 200k+ loop? Is it an immediate thing, or is there a garbage collector crawling around looking for un-referenced objects?

InterSystems products have automatic garbage collector. I'm not sure on the specifics. Calling @Dan Pasco.