blob: cdd6113af8a7acf29b98cab36c8235c9e8898232 [file]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:ffi';
import 'dart:io';
import 'package:jni/_internal.dart';
import 'package:jni/jni.dart';
// Can't reliably force GC on Android.
final canRunJavaGC = !Platform.isAndroid;
void runJavaGC() {
final managementFactory = JClass.forName(
'java/lang/management/ManagementFactory',
);
final bean = managementFactory
.staticMethodId(
'getRuntimeMXBean',
'()Ljava/lang/management/RuntimeMXBean;',
)
.call(managementFactory, JObject.type, []);
final pid =
bean.jClass.instanceMethodId('getPid', '()J').call(bean, jlong.type, []);
ProcessResult result;
do {
result = Process.runSync('jcmd', [pid.toString(), 'GC.run']);
sleep(const Duration(milliseconds: 100));
} while (result.exitCode != 0);
}
/// A wrapper around Java's `java.lang.ref.WeakReference` for testing GC
/// collection.
class JWeakReference {
static final _class = JClass.forName('java/lang/ref/WeakReference');
static final _ctor = _class.constructorId('(Ljava/lang/Object;)V');
static final _getMethod =
_class.instanceMethodId('get', '()Ljava/lang/Object;');
final JObject _weakRef;
JWeakReference(JObject object) : _weakRef = _ctor.call(_class, [object]);
/// Returns `true` if the target object has been collected by the Java GC.
bool get isCollected {
final res = _getMethod.callNullable(_weakRef, JObject.type, []);
// ignore: invalid_use_of_internal_member
return res == null || res.reference.pointer == nullptr;
}
void release() {
_weakRef.release();
}
}