On 30.04.2017 12:53, Rick McGuire wrote:
> I want to verify something first. In this scenario, Rexx code makes a call to 
> a Java method (i.e.,
> the parser) which then makes a lot of callbacks all on the same thread?
Yes.

> If so, then I think I might see where the problem could be. The code that 
> handles nested thread
> attaches (that is, attaching to a thread that already exists) appears to hold 
> on to any allocated
> objects until it returns to the original exit point (in your case, the 
> initial call to the parser). 
>
> This may take a little while to figure out the details of a fix, but I at 
> least know where to
> start. You might want to open a bug indicating there appears to be an
> AttachThread()/DetachThread() memory leak.
Opened a bug: <https://sourceforge.net/p/oorexx/bugs/1445/>.

---rony

>
> On Sun, Apr 30, 2017 at 6:38 AM, Rony G. Flatscher <rony.flatsc...@wu.ac.at
> <mailto:rony.flatsc...@wu.ac.at>> wrote:
>
>     Having slept I went over the debug statements, just to learn that I 
> concluded wrongly
>     yesterday: the reference decreases did not come from the Rexx objects 
> with uninits, but from
>     the Java side! :(
>
>     With new debug statements on the Rexx side (in the destructores) it is 
> clear that no proxy
>     Rexx object turns into garbage before the program gets interrupted with a 
> syntax error.
>
>     Will start over analyzing the codepaths, creating debug programs and 
> report back, once I am
>     done, which might take a day or two.
>
>     ---rony
>
>
>     On 29.04.2017 21:53, Rick McGuire wrote:
>>
>>
>>     On Sat, Apr 29, 2017 at 3:43 PM, Rony G. Flatscher 
>> <rony.flatsc...@wu.ac.at
>>     <mailto:rony.flatsc...@wu.ac.at>> wrote:
>>
>>         The class object (for the BSF class and also its subclasses) is 
>> (get) created in the
>>         BSF.CLS package, which gets required. So it (and its subclasses) 
>> should get created only
>>         once in this test case.
>>
>>         The ooRexx peer objects are instances of the .BSF class, which 
>> defines an uninit method.
>>
>>         Ad interpreter safepoints:
>>
>>           * in this case there is a pending external Rexx function call that 
>> kicks of the SAX
>>             parser's parsing and only will return after the SAX parser 
>> concluded its work,
>>           * in the meantime each callback from the SAX parser will cause a 
>> call via JNI to Rexx,
>>             where each such callback will do an AttachThread() in native 
>> code and before
>>             returning a DetachThread().
>>
>>         The uninits run, so these interpreter safepoints should be reached.
>>
>>     The return from the ooRexx code at the end of the event call is one 
>> safepoint, but the
>>     arguments you passed will still be protected at this point. However, 
>> these objects will not
>>     be processed until the next time a garbage collection is required and 
>> then not until the next
>>     uninit point is hit. 
>>
>>      
>>
>>         ---
>>
>>         Maybe one more thing: the ooRexx peer objects that get created in 
>> native code are stored
>>         in a RexxArray object as they server as arguments for the 
>> SendMessage() function. So I
>>         assume (pure speculation!) that first the RexxArray object needs to 
>> get destroyed in
>>         order for its contained objects to become eligible for destruction. 
>> Maybe that explains
>>         why the Rexx peer objects currently do not get their uninits run at 
>> a much faster pace.
>>
>>
>>     I doubt this causes much of the delay, since these objects don't get 
>> moved to the uninit
>>     queue until the next time it is necessary to run the garbage collector. 
>> It is highly unlikely
>>     that more than a few objects would be affected  by this, but you might 
>> give it a try and see
>>     what happens. 
>>
>>     Rick
>>      
>>
>>         ---rony
>>
>>
>>
>>         On 29.04.2017 21:32, Rick McGuire wrote:
>>>         Running the garbage collector will not force the uninit methods to 
>>> be run. When the
>>>         garbage collector runs, any newly dead objects with uninit methods 
>>> are marked as being
>>>         ready to have the uninit method run. At some later time, when the 
>>> interpreter is at a
>>>         safe point, then the objects with pending uninit methods will be 
>>> processed. These are
>>>         major boundaries such as return from a method or call or thread 
>>> termination. 
>>>
>>>         Since you are creating class objects, things can get delayed even 
>>> further since the
>>>         class object will not become "dead" until all of its instances are 
>>> first "dead". It then
>>>         gets moved to the uninit queue for processing. 
>>>
>>>         Rick
>>>
>>>         On Sat, Apr 29, 2017 at 3:11 PM, Rony G. Flatscher 
>>> <rony.flatsc...@wu.ac.at
>>>         <mailto:rony.flatsc...@wu.ac.at>> wrote:
>>>
>>>             Today, I have started to analyze the code-paths through 
>>> BSF4ooRexx (Java, c++,
>>>             ooRexx-package BSF.CLS).
>>>
>>>             As I have not found any "obvious" cause for the observed 
>>> behaviour yet, I have
>>>             started to analyse the changes in the Java registry (that I 
>>> have full control of).
>>>
>>>             Maybe first a sketch, how Java objects get proxied by ooRexx 
>>> objects:
>>>
>>>               * a Java object that is to be sent to ooRexx as a return or 
>>> argument value will
>>>                 get stored together with a reference counter in a Java 
>>> registry (using a
>>>                 ConcurrentHashMap), the index is a string which will get 
>>> passed on to Rexx
>>>                 instead of the Java object,
>>>               * the Rexx side will create an instance of the class .BSF (or 
>>> a subclass of it)
>>>                 supplying the Java object's index string which is used as 
>>> the objecname for the
>>>                 ooRexx peer object
>>>                   o The BSF class has a destructor method (uninit) which 
>>> will cause a call to
>>>                     the Java side to reduce the Java object's reference 
>>> counter; if the Java
>>>                     reference counter drops to 0 the Java object will be 
>>> removed from the Java
>>>                     registry
>>>
>>>             Running the SAX-example serving as the test case until 250 
>>> startElement
>>>             SAX-callbacks (each callback from Java to Rexx will cause an 
>>> AttachThread(),
>>>             creating the ooRexx peer objects for the arguments, sending the 
>>> Rexx message, upon
>>>             return doing a DetachThread()) have been carried out (in 
>>> addition there are plenty
>>>             of other SAX-callbacks) and using debug statements for adding 
>>> and removing entries
>>>             to/from the Java registry, this is what I can observe:
>>>
>>>               * the ooRexx destructors run,
>>>               * *however* the rate of new ooRexx peer objects that get 
>>> created (by Java objects
>>>                 that are sent to Rexx) is much higher than the rate of 
>>> ooRexx peer objects that
>>>                 get garbage collected by ooRexx, which causes a continuous 
>>> increase in Rexx
>>>                 objects over time
>>>                   o indeed, the ooRexx peer objects get destroyed 
>>> eventually, causing the Java
>>>                     refcounters to be decreased
>>>                       + it seems that not all ooRexx peer objects that have 
>>> turned into garbage
>>>                         get destroyed in the garbage collection runs
>>>                   o still (hence), the amount of ooRexx peer objects 
>>> increases quickly at
>>>                     runtime as the flux of callbacks from Java continues
>>>               * at the end of the program (in this case forcing an error to 
>>> stop it by issuing a
>>>                 'say 1/0') all uninits run the reference counters on the 
>>> Java objects in the
>>>                 Java registry drop to 0!
>>>
>>>             Is there a way in ooRexx to have the garbage collector be run 
>>> (like in Java's
>>>             System.gc() or Runtime.getRuntime.gc())?
>>>
>>>             Such a possibility might help to debug/tame this "run-away" 
>>> scenario.
>>>
>>>             ---rony
>>>
>>>
>>>
>>>             On 27.04.2017 16:56, Rony G. Flatscher wrote:
>>>>
>>>>             Thank you! Will report back, once I concluded the analysis, 
>>>> which may take a while.
>>>>
>>>>             ---rony
>>>>
>>>>
>>>>             On 27.04.2017 16:53, Rick McGuire wrote:
>>>>>             The memory manager will force any pending uninits to be run 
>>>>> before it gives up and
>>>>>             issues the out of resources error messages. I really suspect 
>>>>> something in the way
>>>>>             your code is creating the proxies and tracking them is 
>>>>> preventing the objects from
>>>>>             being identified as dead objects, so these objects will just 
>>>>> keep accumulating.
>>>>>             The more live objects locked in memory, the longer a GC cycle 
>>>>> will take because
>>>>>             there is a larger live set to mark. 
>>>>>
>>>>>             Rick
>>>>>
>>>>>             On Thu, Apr 27, 2017 at 10:34 AM, Rony G. Flatscher 
>>>>> <rony.flatsc...@wu.ac.at
>>>>>             <mailto:rony.flatsc...@wu.ac.at>> wrote:
>>>>>
>>>>>                 Further information, using the initial e-mail to keep all 
>>>>> relevant information
>>>>>                 in one e-mail.
>>>>>
>>>>>                 Today I uninstalled the 32-bit ooRexx 5.0beta and 
>>>>> installed the 64-bit ooRexx
>>>>>                 5.0beta (both from SourceForge, downloaded February 4th 
>>>>> 2017).
>>>>>
>>>>>                 This time the program ran successfully to the end:
>>>>>
>>>>>                   * there were more than 247,000 XML elements processed
>>>>>                       o as already mentioned this may translate into 
>>>>> million(s) call backs
>>>>>                         from Java to Rexx as all SAX events will cause 
>>>>> callbacks to Rexx
>>>>>                           + some of these callbacks carry Java objects as 
>>>>> arguments which will
>>>>>                             get wrapped as a peer ooRexx object 
>>>>> (ultimately an instance of the
>>>>>                             class .BSF that has an uninit method 
>>>>> defined), namely the Java
>>>>>                             types: "char[]", "Attributes", "Local" from 
>>>>> the callbacks 
>>>>>                             
>>>>> <https://docs.oracle.com/javase/7/docs/api/org/xml/sax/ContentHandler.html
>>>>>                             
>>>>> <https://docs.oracle.com/javase/7/docs/api/org/xml/sax/ContentHandler.html>>
>>>>>                           + there are no return values (all callbacks are 
>>>>> defined to be void)
>>>>>
>>>>>                   * it took a total of 2:37 hours to SAX-parse a 10MB XML 
>>>>> file,
>>>>>                       o the SAX-parsing was over after 1:45 hours
>>>>>                           + the program constantly slowed down and in 
>>>>> between paused for a
>>>>>                             while (which got longer and longer over time)
>>>>>                       o after the SAX-parseing was over the Rexx program 
>>>>> needed another  0:52
>>>>>                         hours to complete
>>>>>                           + speculating/assuming that in this time all 
>>>>> the uninits got
>>>>>                             executed (which is fine)
>>>>>
>>>>>                   * it consumed 8.7GB of memory
>>>>>                       o ProcessExplorer reports a
>>>>>                           + Physical Memory "PeekWorking Set" of 
>>>>> 8.795.796 K
>>>>>                           + Virtual Memory "Virtual Size" of 13.404.424 K 
>>>>> with "Peak Private
>>>>>                             Bytes" of 9.138.664 K
>>>>>
>>>>>                   * it used 24% of the CPU over all 2:37 hours
>>>>>                       o ProcessExplorer reports a
>>>>>                           + "Kernel Time" of 0:01:10.184
>>>>>                           + "User Time" of 2.32.57.960
>>>>>                           + "Total Time" of  2:34:08.144
>>>>>                           + "Cycles": 23.898.290.997.693
>>>>>
>>>>>                 Will check the BSF4ooRexx call and code paths.
>>>>>
>>>>>                 ---rony
>>>>>
>>>>>
>>>>>
>>>>>                 On 26.04.2017 20:28, Rony G. Flatscher wrote:
>>>>>>
>>>>>>                 A student is using BSF4ooRexx to parse a huge XML file 
>>>>>> using Java's SAX parser.
>>>>>>
>>>>>>                 The SAX (simple API for XML) works with a callback 
>>>>>> concept. In order to be
>>>>>>                 eligible for these SAX callbacks the ContentHandler 
>>>>>> interface
>>>>>>                 
>>>>>> <https://docs.oracle.com/javase/7/docs/api/org/xml/sax/ContentHandler.html>
>>>>>>                 
>>>>>> <https://docs.oracle.com/javase/7/docs/api/org/xml/sax/ContentHandler.html>
>>>>>>                 must be implemented, which the Rexx program does with 
>>>>>> the help of BSF4ooRexx.
>>>>>>
>>>>>>                 As a result each single SAX event will cause an 
>>>>>> appropriate Rexx message to
>>>>>>                 be generated and dispatched.  The Rexx message is named 
>>>>>> after the
>>>>>>                 ContentHandler method name and will receive all 
>>>>>> arguments documented there.
>>>>>>                 All arguments are processed in native code, a Rexx array 
>>>>>> object will get
>>>>>>                 created from the Java arguments.
>>>>>>
>>>>>>                 This works and was presented on one of the International 
>>>>>> Rexx symposiums and
>>>>>>                 has become part of my lecture using Java camouflaged as 
>>>>>> ooRexx with the help
>>>>>>                 of BSF4ooRexx. Here is a link to the symposium which 
>>>>>> contains links to the
>>>>>>                 slides: <http://rexxla.org/events/2013/schedule.html>
>>>>>>                 <http://rexxla.org/events/2013/schedule.html>.
>>>>>>
>>>>>>                 Now, a student is in the need to parse a rather huge XML 
>>>>>> file (10 MB) and
>>>>>>                 uses the SAX parser. She always hits the Rexx "Error 5: 
>>>>>> System resources
>>>>>>                 exhausted"! I asked her to come up with a very small 
>>>>>> program to demonstrate
>>>>>>                 the error and I am able to reproduce it reliably!
>>>>>>
>>>>>>                 Here is the rather short Rexx program:
>>>>>>                 --- #!/usr/bin/rexx parse arg xmlFile if xmlFile="" then
>>>>>>                 XMLFile="..\LB-HB.onlb" if sysFileExists(xmlFile)=.false 
>>>>>> then do say "File"
>>>>>>                 pp(xmlFile) "does not exist, aborting." exit -1 end
>>>>>>                 rexxObject=.saxHandler~new();
>>>>>>                 
>>>>>> javaProxy=BSFCreateRexxProxy(rexxObject,,"org.xml.sax.ContentHandler")
>>>>>>                 
>>>>>> parser=bsf.loadClass("org.xml.sax.helpers.XMLReaderFactory")~createXMLReader
>>>>>>                 parser~setContentHandler(javaProxy) eh=.errorHandler~new
>>>>>>                 javaEH=BsfCreateRexxProxy(eh,,"org.xml.sax.ErrorHandler")
>>>>>>                 parser~setErrorHandler(javaEH) signal on syntax 
>>>>>> start=.dateTime~new say
>>>>>>                 pp(start)": start of parsing" parser~parse(XMLFile) 
>>>>>> end=.dateTime~new say
>>>>>>                 pp(end)": end of parsing" say "done, needed:" 
>>>>>> pp(end-start) exit syntax: say
>>>>>>                 "error at" rexxObject~nrOfElements "element" 
>>>>>> co=condition('o') say
>>>>>>                 ppCondition2(co) ::requires "BSF.CLS" /* get the Java 
>>>>>> support */ ::requires
>>>>>>                 "rgf_util2.rex" ::CLASS "SaxHandler" -- a Rexx content 
>>>>>> handler
>>>>>>                 ("org.xml.sax.ContentHandler") ::attribute nrOfElements 
>>>>>> ::METHOD init
>>>>>>                 --ooRexx constructor expose nrOfElements nrOfElements=0 
>>>>>> ::METHOD startElement
>>>>>>                 expose nrOfElements USE ARG uri, localName, qName, 
>>>>>> attributes nrOfElements+=1
>>>>>>                 if nrOfElements//1000=0 then say nrOfElements "elements 
>>>>>> so far ..." ::METHOD
>>>>>>                 characters -- the callback method for characters (text) 
>>>>>> USE ARG charArray,
>>>>>>                 start, length ::METHOD endElement USE ARG uri, 
>>>>>> localName, qName, attributes
>>>>>>                 ::method unknown ::class ErrorHandler ::method unknown 
>>>>>> use arg methName,
>>>>>>                 argArray exception=argArray[1]s .error~say(methName": "
>>>>>>                 "line="exception~getLineNumber 
>>>>>> ",col="exception~getColumnNumber": "
>>>>>>                 pp(exception~getMessage)) ---
>>>>>>                 As you might see, there is nothing "special" going on 
>>>>>> here, other than being
>>>>>>                 able to supply a Rexx object as the callback object for 
>>>>>> the Java implemented
>>>>>>                 SAX parser! It seems that running all these callback 
>>>>>> from Java to Rexx will
>>>>>>                 cause eventually that ooRexx gets exhausted of system 
>>>>>> resources. While
>>>>>>                 running the program it can be observed that from time to 
>>>>>> time there are
>>>>>>                 little lags as if some garbage collecting takes place. 
>>>>>> Eventually the error 5
>>>>>>                 is thrown, while executing in native code:
>>>>>>
>>>>>>                     result_obj=rtc->SendMessage(ro, c_msg, ra); // with 
>>>>>> arguments
>>>>>>
>>>>>>                 Please note that the following error message only gives 
>>>>>> the numbers of XML
>>>>>>                 elements that the SAX parser reported. In reality, *all* 
>>>>>> callbacks are
>>>>>>                 carried out from Java to Rexx, the unprocessed ones will 
>>>>>> be intercepted by
>>>>>>                 the Rexx UNKNOWN method. So there is a flurry of context 
>>>>>> switches and
>>>>>>                 creation of Rexx array objects for the arguments and the 
>>>>>> like. Here is the
>>>>>>                 error message on my system.
>>>>>>                 --- 83000 elements so far ... 84000 elements so far ... 
>>>>>> error at 84926
>>>>>>                 element [ADDITIONAL] =[an Array (2 items) 
>>>>>> id#_-1457160369]
>>>>>>                 ["BSF4ooRexx/routine/BSF(), error 3: Java exception 
>>>>>> occurred:
>>>>>>                 [org.rexxla.bsf.engines.rexx.RexxException:
>>>>>>                 BSF4ooRexx/routine/jniRexxSendMessageToRexxObject(), 
>>>>>> error 4:" || "0A"x || "
>>>>>>                 *-* Compiled method ""OBJECTNAME="" with scope 
>>>>>> ""Object""." || "0A"x ||
>>>>>>                 "Error 5 running C:\Program Files 
>>>>>> (x86)\BSF4ooRexx\BSF.CLS line 2644: System
>>>>>>                 resources exhausted." || "0A"x || "Error 5.0: message 
>>>>>> n/a]"]
>>>>>>                 [org.rexxla.bsf.engines.rexx.RexxException@182d820 
>>>>>> id#_-1478994985] [CODE]
>>>>>>                 =[40.900] [CONDITION] =[SYNTAX] [DESCRIPTION]=[] 
>>>>>> [ERRORTEXT] =[Incorrect call
>>>>>>                 to routine.] [INSTRUCTION]=[SIGNAL] [MESSAGE] 
>>>>>> =["BSF4ooRexx/routine/BSF(),
>>>>>>                 error 3: Java exception occurred: 
>>>>>> [org.rexxla.bsf.engines.rexx.RexxException:
>>>>>>                 BSF4ooRexx/routine/jniRexxSendMessageToRexxObject(), 
>>>>>> error 4:" || "0A"x || "
>>>>>>                 *-* Compiled method ""OBJECTNAME="" with scope 
>>>>>> ""Object""." || "0A"x ||
>>>>>>                 "Error 5 running C:\Program Files 
>>>>>> (x86)\BSF4ooRexx\BSF.CLS line 2644: System
>>>>>>                 resources exhausted." || "0A"x || "Error 5.0: message 
>>>>>> n/a]."] [PACKAGE] =[a
>>>>>>                 Package id#_-2109388833] [POSITION] =[25] [PROGRAM]
>>>>>>                 =[F:\tmp\orx\kirisits\20170425\SAX_noAlerts.rxj] 
>>>>>> [PROPAGATED] =[1] [RC] =[40]
>>>>>>                 [STACKFRAMES]=[a List (4 items) id#_-1467321073] [ *-* 
>>>>>> Compiled routine
>>>>>>                 "BSF". id#_-1939043649] [ 1811 *-* res=BSF( "invoke",
>>>>>>                 "com.sun.org.apache.xerces.int
>>>>>>                 
>>>>>> <http://com.sun.org.apache.xerces.int>ernal.parsers.SAXParser@117ae12",
>>>>>>                 "PARSE" , a.1 ) id#_-1938526417] [ 1813 *-* interpret 
>>>>>> code ")" -- execute
>>>>>>                 this dynamically created Rexx string id#_-1937397361] [ 
>>>>>> 25 *-*
>>>>>>                 parser~parse(XMLFile) id#_-1936143753] [TRACEBACK] =[a 
>>>>>> List (4 items)
>>>>>>                 id#_-1458379065] [ *-* Compiled routine "BSF".] [ 1811 
>>>>>> *-* res=BSF( "invoke",
>>>>>>                 "com.sun.org.apache.xerces.int
>>>>>>                 
>>>>>> <http://com.sun.org.apache.xerces.int>ernal.parsers.SAXParser@117ae12",
>>>>>>                 "PARSE" , a.1 )] [ 1813 *-* interpret code ")" -- 
>>>>>> execute this dynamically
>>>>>>                 created Rexx string] [ 25 *-* parser~parse(XMLFile)] ---
>>>>>>                 The traceback points to the invocation of the SAX parser 
>>>>>> from Rexx which only
>>>>>>                 returns upon completion of the Java parse method, or in 
>>>>>> this case when an
>>>>>>                 error interrupts the program. --- So now my 
>>>>>> question/request: how to debug
>>>>>>                 this problem/error? How can I get more information from 
>>>>>> the ooRexx
>>>>>>                 interpreter? How can one determine what kind of "system 
>>>>>> resources" got
>>>>>>                 exhausted and what the cause would be? Can one e.g. 
>>>>>> determine how many Rexx
>>>>>>                 objects there are and how many are dead, in the need of 
>>>>>> getting garbage
>>>>>>                 collected? In this case whenever (on each SAX callback) 
>>>>>> the Java side invokes
>>>>>>                 the native code which then sends the message to the Rexx 
>>>>>> object there will be
>>>>>>                 an AttachThread() followed by a DetachThread(). Please 
>>>>>> advise! ---rony 
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to