David
10/16/2018, 8:32 AMDavid
10/16/2018, 8:32 AMclass KotlinNativeFramework {
    var listener: KotlinNativeFrameworkListener? = null
    fun giveMeDoubles() {
        while (true) {
            val myList = DoubleArray(100) { 1.0 }.toList()
            listener?.listenToDoubles(myList) // If this line is commented, the leak stops.
        }
    }
}
interface KotlinNativeFrameworkListener {
    fun listenToDoubles(list: List<Double>)
}
LeakingClass.m:
#import "LeakingClass.h"
@interface LeakingClass()
@property (nonatomic, strong) KNFKotlinNativeFramework *knf;
@end
@implementation LeakingClass
-(void)start
{
    _knf = [KNFKotlinNativeFramework new];
    self.knf.listener = self;
    [self.knf giveMeDoubles];
}
- (void)listenToDoublesList:(NSArray<KNFDouble *> *)list {}
@endsvyatoslav.scherbina
10/16/2018, 8:37 AMIsn’t it a retain cycle?self.knf.listener = self
David
10/16/2018, 8:39 AMDavid
10/16/2018, 8:43 AMsvyatoslav.scherbina
10/16/2018, 8:44 AMlistenToDoubles. When calling from Kotlin to Objective-C, Kotlin runtime creates temp Objective-C NSArray wrapper for Kotlin List.svyatoslav.scherbina
10/16/2018, 8:45 AMfun giveMeDoubles() {
        while (true) {
            val myList = DoubleArray(100) { 1.0 }.toList()
            autoreleasepool {
                listener?.listenToDoubles(myList) // If this line is commented, the leak stops.
            }
        }
    }David
10/16/2018, 8:54 AMsvyatoslav.scherbina
10/16/2018, 8:57 AMDavid
10/16/2018, 8:59 AMsvyatoslav.scherbina
10/16/2018, 9:00 AMDavid
10/16/2018, 11:33 AMpool = objc_autoreleasePoolPush() and then I periodically call objc_autoreleasePoolPop(pool). Is this best practice or is there another way?olonho
10/16/2018, 11:35 AMsvyatoslav.scherbina
10/16/2018, 11:36 AMDavid
10/16/2018, 11:36 AMsvyatoslav.scherbina
10/16/2018, 11:37 AMsvyatoslav.scherbina
10/16/2018, 11:38 AMDavid
10/16/2018, 11:41 AMsvyatoslav.scherbina
10/16/2018, 11:42 AMobjc_autoreleasePoolPop(pool)
pool = objc_autoreleasePoolPush()David
10/16/2018, 11:44 AMsvyatoslav.scherbina
10/16/2018, 11:44 AMSo, the best way perhaps is to avoid sending lists to objective-c? If the conversion between lists and NSArrays is the problem…No. Normal Objective-C code uses autorelease pools too. So the necessity to release the pool periodically doesn’t seem to be specific for Kotlin/Native
David
10/16/2018, 11:46 AMsvyatoslav.scherbina
10/16/2018, 11:50 AMautoreleasepool {} without falling back to its implementation details `objc_autoreleasePoolPop`/`objc_autoreleasePoolPush` with something like this:
while (true) {
            autoreleasepool {
                repeat(autoreleaseFrequency) {
                    val myList = DoubleArray(100) { 1.0 }.toList()
                    listener?.listenToDoubles(myList)
                }
            }
        }David
10/16/2018, 11:55 AMWorker.execute to perform work and do the callback. It is then not possible to wrap several event-cycles in one lambda.