Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force garbage collection of JavaScriptCore virtual machine on iOS

Is there any way to force iOS (or Mac OS) JavaScriptCore VM garbage collector to run? I need it only to test for memory leaks, so private API would be fine.

like image 261
silyevsk Avatar asked Feb 28 '16 23:02

silyevsk


People also ask

How to force Java garbage collection?

Java Mission Control and JConsole both have visual tools that allow you to force Java GC. While a developer can never actually force Java garbage collection, there are ways to make the JVM prioritize memory management functions. In review, five ways to try and force Java garbage collection are: Call the System.gc () command.

How does garbage collector work in JavaScript?

Detailed examples to follow. There’s a background process in the JavaScript engine that is called garbage collector. It monitors all objects and removes those that have become unreachable. Here the arrow depicts an object reference. The global variable "user" references the object {name: "John"} (we’ll call it John for brevity).

Where can I find more information about V8’s garbage collector?

If you are familiar with low-level programming, more detailed information about V8’s garbage collector is in the article A tour of V8: Garbage Collection. The V8 blog also publishes articles about changes in memory management from time to time.

How to prioritize garbage collection in JVM?

Developers can call System.gc () anywhere in their code to instruct the JVM to prioritize garbage collection. When a developer calls this method -- and there isn't an extreme load on the JVM -- a Java GC cycle will happen within seconds. 2. Call Runtime.getRuntime ().gc () Another option is to use the Runtime.getRuntime ().gc () call.


1 Answers

Use following function from JSBase.h:

/*!
@function JSGarbageCollect
@abstract Performs a JavaScript garbage collection.
@param ctx The execution context to use.
@discussion JavaScript values that are on the machine stack, in a register,
 protected by JSValueProtect, set as the global object of an execution context,
 or reachable from any such value will not be collected.

 During JavaScript execution, you are not required to call this function; the
 JavaScript engine will garbage collect as needed. JavaScript values created
 within a context group are automatically destroyed when the last reference
 to the context group is released.
*/
JS_EXPORT void JSGarbageCollect(JSContextRef ctx);

You can obtain JSContextRef from your JSContext, using JSGlobalContextRef readonly property.

Update

I've found next change in WebKit - bugs.webkit.org/show_bug.cgi?id=84476:

JSGarbageCollect should not synchronously call collectAllGarbage(). Instead, it should notify the GCActivityCallback that it has abandoned an object graph, which will set the timer to run at some point in the future that JSC can decide according to its own policies.

This explains why previous solution doesn't work as expected.

Digging deeper into WebKit sources, I found another interesting approach. Please, try following code:

JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx);

@interface JSContext (GarbageCollection)

-(void)garbageCollect {
    JSSynchronousGarbageCollectForDebugging(self.JSGlobalContextRef);
}

@end

Simply call garbageCollect method on your JSContext instance after that. I've tried it locally on iOS and it seems to work.

like image 200
Borys Verebskyi Avatar answered Sep 27 '22 18:09

Borys Verebskyi