Re: PilBox & Java object lifecycle

2023-08-27 Thread Alexander Burger
On Sat, Aug 26, 2023 at 11:56:42AM -0400, Todd Coram wrote:
> Of course, tracking every object instantiation that gets stuffed into the
> HashArray isn't trivial,

The opposite (i.e. which objects are still referenced from Lisp) is easy though:

   (filter
  '((Obj) (== 32769 (car (id Obj T
  (all 0) )

This returns a List of all accessible Java objects.


> It seems that any object returned by a Java method call is subject to be 
> placed
> there so calls like (java (java someobject 'getResultingObject) 'doSomething))
> will place the inner object in the HashArray, correct?

Yes. The call inserts the result of (java someobject ...) into the hashmap, and
perhaps also the result of the outer 'java' call if it is an object.

For example,

   : (java "java.io.File" T "name")
   -> {H@@@10327432}

inserts *one* new object.

If that object's internals are accessed, for example by

   : (show @)
   {H@@@10327432} ({H@@@751603011} . "java.io.File")
  filePath NIL
  path "name"
  prefixLength 0
  status NIL
  fs {H@@@1172500016}
  pathSeparator ":"
  pathSeparatorChar 58
  separator "/"
  separatorChar 47
  serialVersionUID 301077366599181567
   -> {H@@@10327432}

then also all objects referred by it (i.e. {H@@@751603011} and {H@@@1172500016}
will be inserted.

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: PilBox & Java object lifecycle

2023-08-26 Thread Todd Coram
On Fri, Aug 25, 2023, at 3:52 AM, Alexander Burger wrote:

> and did some test. Works fine, and gives - as expected - a null pointer
> exception if the object is accessed from Lisp again.

Great! I've got same results here.  Of course, tracking every object 
instantiation that gets stuffed into the HashArray isn't trivial, but for my 
purposes it's essential.  It seems that any object returned by a Java method 
call is subject to be placed there so calls like (java (java someobject 
'getResultingObject) 'doSomething)) will place the inner object in the 
HashArray, correct?
I've taken to not doing nested (java) calls to manage this.  And I've also 
wrapped a catch around my releases (java NIL obj) in case it has been release 
already from the HashArray...  Some good idioms will need to go with the use of 
(java NIL...) 

> I cannot make a release to PlayStore now, as PilBox is in the process of some
> changes to prepare for Android 14. So I made a temporary release available at:
>
>https://picolisp.com/pub/pilBox.apk
>https://picolisp.com/pub/PilBox.tgz

Thanks! I'll grab it soon.

> Thanks a lot for the good idea! :)

Thanks for validating it.  My app has now been running over 24 hours 
(collecting BLE scans) without running out of memory (up from the 1-2 hour runs 
before).

/todd

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: PilBox & Java object lifecycle

2023-08-25 Thread Alexander Burger
Hi Todd,

> Perhaps something like:
> (java NIL 'obj) for removing it from the hashtable? The "complex management" 
> of this could then be handled in pure Picolisp...

Very good idea! This fits nicely into the 'java' syntax, and has no harmful
effects if used wisely ;)


> Would it be as simple as something like (in Reflector.java  reflect()):
>if (y == InOut.Nil) {   // Release 
> reference to Object
>  Object o = lst[1];  // object to 
> release
>  int idx  = o.hashCode();
>  InOut.Obj.remove(idx);
>  Io.Out.write(InOut.NIX);
>  Io.Out.write(InOut.NIX);
>  x = null;
>   
> Or am I heading in the wrong direction?

No, this is basically correct. The write's are not needed, as they happen at the
end of reflect() anyway.

So I inseted:

   1c1
   < // 31jul23abu
   ---
   > // 25aug23abu
   58a59
   >// (java NIL 'obj) -> NIL   Release reference to object
   120c121,125
   if (y == InOut.Nil) { // Release 
reference to object
   >   InOut.Obj.remove(lst[1].hashCode());
   >   x = null;
   >}
   >else if (y == InOut.T) {  // Define 
interface

and did some test. Works fine, and gives - as expected - a null pointer
exception if the object is accessed from Lisp again.


I cannot make a release to PlayStore now, as PilBox is in the process of some
changes to prepare for Android 14. So I made a temporary release available at:

   https://picolisp.com/pub/pilBox.apk
   https://picolisp.com/pub/PilBox.tgz

Thanks a lot for the good idea! :)

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: PilBox & Java object lifecycle

2023-08-24 Thread Todd Coram
Hi Alex,
Fantastic language (Picolisp) and very, very useful port to Android.

On Thu, Aug 24, 2023, at 2:15 PM, Alexander Burger wrote:

> Is this is really the cause of the problem? Most java calls do not make a new
> object each time, and stored in the hash map are not all involved objects, but
> only those which are reflected back to Lisp (and not all created internally).

TBH,  most of my troubles came from using the Android JSON library (which 
requires me to explicitly create the Java objects to add) and I do plan to move 
to a pure Picolisp implementation.  But it did get me thinking about everywhere 
I instantiate a Java object via  (java "classname" T).  

> The objects in the hash map are indeed never removed. This would be difficult 
> to
> implement, because the Java side has no information about which objects are
> still in use on the Lisp side.

I'm pushing PilBox to the limits of (probably) what you intended: I want to run 
a minimal UI background service that scans BLE.  It works well, but I'd like to 
keep track of the Java objects, even if done explicitly.  With that said, there 
are occasionally instantiated objects I'd like to keep track of and don't mind 
house cleaning.  I could even imagine instrumenting something handled in catch 
clauses or loop/function exit situations.

I just need access to that hashtable.  

> Perhaps we can come up with ideas how to improve the situation.
>

Perhaps something like:
(java NIL 'obj) for removing it from the hashtable? The "complex management" of 
this could then be handled in pure Picolisp...

Would it be as simple as something like (in Reflector.java  reflect()):
   if (y == InOut.Nil) {   // Release reference 
to Object
   Object o = lst[1];  // object to 
release
   int idx  = o.hashCode();
   InOut.Obj.remove(idx);
   Io.Out.write(InOut.NIX);
   Io.Out.write(InOut.NIX);
   x = null;
  
Or am I heading in the wrong direction?

/todd


-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: PilBox & Java object lifecycle

2023-08-24 Thread Alexander Burger
Hi Todd,

> I have a long running PilBox Android app that tends to just "crash" (with a
> "Webpage not Available... net:ERR_CONNECTION_REFUSED") after running for a few
> hours. At this point, the REPL is unresponsive at this point and nothing is in
> the PilBox log file.

I need PilBox open all day for various reasons, and monitor it constantly. So I
notice quickly if something goes wrong. In fact it crashes sometimes, but it is
usually longer than a few hours (more like about once or twice a week).

Typical crashes are usually not PilBox's fault. Android is a nasty host system,
it kills apps whenever it feels it needs memory (kills with -9, not -15 !!!).
Other situations are when Android updates system components in the background
(most notably the System WebView), then PilBox is also killed.

But: In most of the above cases, there is no connection error, but PilBox
"resets", i.e. it goes to the home screen and lost its context. Technically,
this means a new instance of the internal PicoLisp process was started.

If you see the above connection errors, it seems that the PicoLisp process
is gone and not restarted. Not sure.

Also you probably know that you can force a full stop of PilBox and PicoLisp by
swiping it off. This stopping did not work reliable in older PilBoxes and was
improved a few months ago.

BTW, do you use a current version of PilBox?
Latest official release was 23.7.13 (183)


> My app makes heavy use of Java calls (dozens every 5 seconds) and this got me
> wondering about how PilBox treats the Java object life-cycle.

A valid question.

> I don't see clearly how the Java objects themselves are referenced so as not 
> to
> be collected by the Java GC. I do see a static HashMap in InOut.java. Are Java
> objects "put" there to save them from the GC?

Yes, this is exactly the reason.

> If so, when are they removed from the HashMap? I don't see any "remove" in
> InOut.java or other PilBox Java sources.
> 
> If objects are referenced there Is it possible that these objects are never
> freed?
> ... 2nd mail
> I should be a little clearer: I "instantiate" dozens Java object every 5 
> seconds
> and wonder how Pilbox affects their life-cycle

I understand the question well. And was aware of the trade offs from early on.

The objects in the hash map are indeed never removed. This would be difficult to
implement, because the Java side has no information about which objects are
still in use on the Lisp side.

Is this is really the cause of the problem? Most java calls do not make a new
object each time, and stored in the hash map are not all involved objects, but
only those which are reflected back to Lisp (and not all created internally).

And: The objects in the hash map are truly minimal. They have no local data,
they are just stubs. They seem big when looked at with (show Obj), but all these
data are generated on the fly via reflection and not part of the objects
themselves.

Still, you are right that this mechanism will use more and more memory.

Have you checked it? I did occasionally, using something like this code in the
REPL:

   (let R (java "java.lang.Runtime" 'getRuntime)
  (java R 'gc)
  (let
 (Fmt (-7 9)
Mem (java R 'totalMemory)
Free (java R 'freeMemory) )
 (tab Fmt "Total" (format Mem 3 "." ","))
 (tab Fmt "Free" (format Free 3 "." ","))
 (tab Fmt "Used" (format (- Mem Free) 3 "." ",")) )
  R )

Perhaps we can come up with ideas how to improve the situation.

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: PilBox & Java object lifecycle

2023-08-24 Thread Todd Coram
I should be a little clearer: I "instantiate" dozens Java object every 5 
seconds and wonder how Pilbox affects their life-cycle

/todd

On Thu, Aug 24, 2023, at 12:42 PM, Todd Coram wrote:
> Hi,
> I have a long running PilBox Android app that tends to just "crash" 
> (with a "Webpage not Available... net:ERR_CONNECTION_REFUSED") after 
> running for a few hours. At this point, the REPL is unresponsive at 
> this point and nothing is in the PilBox log file.
>
>  My app makes heavy use of Java calls (dozens every 5 seconds)  and 
> this got me wondering about how PilBox treats the Java object 
> life-cycle. 
>
> I don't see clearly how the Java objects themselves are referenced so 
> as not to be collected by the Java GC.  I do see a static HashMap in 
> InOut.java.  Are Java objects "put" there to save them from the GC?  If 
> so, when are they removed from the HashMap?  I don't see any "remove" 
> in InOut.java or other PilBox Java sources.
>
> If objects are referenced there Is it possible that these objects are 
> never freed?
>
> /todd
>
> -- 
> UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe