diff --git a/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JniScope.kt b/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JniScope.kt
index c4deff9a4906b470c834ebc6ec7ab6b1e7018ded..16598d1fb207f6549124b5c3d435673bd2b05ba0 100644
--- a/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JniScope.kt
+++ b/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JniScope.kt
@@ -29,9 +29,6 @@ import kotlinx.cinterop.CVariable
 import kotlinx.cinterop.ExperimentalForeignApi
 
 value class JniScope(val env: JniEnvironment) {
-    inline val runtime: JvmRuntime?
-        get() = JvmRuntime.get(env)
-
     fun jstring.toKString(): String = toKString(env)
     fun String.toJString(): jstring = toJString(env)
 
@@ -110,6 +107,11 @@ value class JniScope(val env: JniEnvironment) {
     val JvmField.instance: JvmObject
         get() = getInstance(env)
 
+    fun JvmMethod.callVoid(
+        instance: JvmObject = JvmObject.NULL,
+        closure: ArgumentScope.() -> Unit = {}
+    ) = callVoid(env, instance, closure)
+
     fun JvmMethod.callByte(
         instance: JvmObject = JvmObject.NULL,
         closure: ArgumentScope.() -> Unit = {}
@@ -430,6 +432,18 @@ value class JniScope(val env: JniEnvironment) {
         get() = getIterator(env)
     inline val JvmObjectArray.view: JvmObjectArrayView
         get() = getView(env)
+
+    inline val runtime: JvmRuntime
+        get() = JvmRuntime.get(env)
+    inline val JvmRuntime.availableProcessors: Int
+        get() = getAvailableProcessors(env)
+    inline val JvmRuntime.totalMemory: Int
+        get() = getTotalMemory(env)
+    inline val JvmRuntime.maxMemory: Int
+        get() = getMaxMemory(env)
+
+    fun JvmRuntime.freeMemory() = freeMemory(env)
+    fun JvmRuntime.gc() = gc(env)
 }
 
 @OptIn(UnsafeJniApi::class)
diff --git a/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JvmMethod.kt b/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JvmMethod.kt
index 328a17bb2e72740577b0c0b699d6bc16ff1cad69..27619f2ceda1b81608fc2cfa5599483642fe830b 100644
--- a/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JvmMethod.kt
+++ b/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JvmMethod.kt
@@ -186,25 +186,42 @@ class JvmMethod(
         )
     }
 
+    @OptIn(UnsafeJniApi::class, InternalJniApi::class)
+    inline fun callVoid(
+        env: JniEnvironment,
+        instance: JvmObject = JvmObject.NULL,
+        args: ArgumentScope.() -> Unit = {}
+    ) = memScoped {
+        when (descriptor.callType) { // @formatter:off
+            CallType.STATIC -> env.pointed?.CallStaticVoidMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallVoidMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualVoidMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        } ?: 0 // @formatter:on
+    }
+
     @OptIn(UnsafeJniApi::class, InternalJniApi::class)
     inline fun callByte(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         args: ArgumentScope.() -> Unit = {}
-    ): Byte {
-        return memScoped {
-            when (descriptor.callType) { // @formatter:off
-                CallType.STATIC -> env.pointed?.CallStaticByteMethodA?.invoke(
-                    env.ptr, enclosingClass.handle, id, allocArgs(args)
-                )
-                CallType.VIRTUAL -> env.pointed?.CallByteMethodA?.invoke(
-                    env.ptr, instance.handle, id, allocArgs(args)
-                )
-                CallType.DIRECT -> env.pointed?.CallNonvirtualByteMethodA?.invoke(
-                    env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
-                )
-            } ?: 0 // @formatter:on
-        }
+    ): Byte = memScoped {
+        when (descriptor.callType) { // @formatter:off
+            CallType.STATIC -> env.pointed?.CallStaticByteMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallByteMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualByteMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        } ?: 0 // @formatter:on
     }
 
     @OptIn(UnsafeJniApi::class, InternalJniApi::class)
@@ -212,20 +229,18 @@ class JvmMethod(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         args: ArgumentScope.() -> Unit = {}
-    ): Short {
-        return memScoped {
-            when (descriptor.callType) { // @formatter:off
-                CallType.STATIC -> env.pointed?.CallStaticShortMethodA?.invoke(
-                    env.ptr, enclosingClass.handle, id, allocArgs(args)
-                )
-                CallType.VIRTUAL -> env.pointed?.CallShortMethodA?.invoke(
-                    env.ptr, instance.handle, id, allocArgs(args)
-                )
-                CallType.DIRECT -> env.pointed?.CallNonvirtualShortMethodA?.invoke(
-                    env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
-                )
-            } ?: 0 // @formatter:on
-        }
+    ): Short = memScoped {
+        when (descriptor.callType) { // @formatter:off
+            CallType.STATIC -> env.pointed?.CallStaticShortMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallShortMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualShortMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        } ?: 0 // @formatter:on
     }
 
     @OptIn(InternalJniApi::class, UnsafeJniApi::class)
@@ -233,20 +248,18 @@ class JvmMethod(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         args: ArgumentScope.() -> Unit = {}
-    ): Int {
-        return memScoped {
-            when (descriptor.callType) { // @formatter:off
-                CallType.STATIC -> env.pointed?.CallStaticIntMethodA?.invoke(
-                    env.ptr, enclosingClass.handle, id, allocArgs(args)
-                )
-                CallType.VIRTUAL -> env.pointed?.CallIntMethodA?.invoke(
-                    env.ptr, instance.handle, id, allocArgs(args)
-                )
-                CallType.DIRECT -> env.pointed?.CallNonvirtualIntMethodA?.invoke(
-                    env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
-                )
-            } ?: 0 // @formatter:on
-        }
+    ): Int = memScoped {
+        when (descriptor.callType) { // @formatter:off
+            CallType.STATIC -> env.pointed?.CallStaticIntMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallIntMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualIntMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        } ?: 0 // @formatter:on
     }
 
     @OptIn(UnsafeJniApi::class, InternalJniApi::class)
@@ -254,20 +267,18 @@ class JvmMethod(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         args: ArgumentScope.() -> Unit = {}
-    ): Long {
-        return memScoped {
-            when (descriptor.callType) { // @formatter:off
-                CallType.STATIC -> env.pointed?.CallStaticLongMethodA?.invoke(
-                    env.ptr, enclosingClass.handle, id, allocArgs(args)
-                )
-                CallType.VIRTUAL -> env.pointed?.CallLongMethodA?.invoke(
-                    env.ptr, instance.handle, id, allocArgs(args)
-                )
-                CallType.DIRECT -> env.pointed?.CallNonvirtualLongMethodA?.invoke(
-                    env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
-                )
-            } ?: 0 // @formatter:on
-        }
+    ): Long = memScoped {
+        when (descriptor.callType) { // @formatter:off
+            CallType.STATIC -> env.pointed?.CallStaticLongMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallLongMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualLongMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        } ?: 0 // @formatter:on
     }
 
     @OptIn(UnsafeJniApi::class, InternalJniApi::class)
@@ -275,20 +286,18 @@ class JvmMethod(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         args: ArgumentScope.() -> Unit = {}
-    ): Float {
-        return memScoped {
-            when (descriptor.callType) { // @formatter:off
-                CallType.STATIC -> env.pointed?.CallStaticFloatMethodA?.invoke(
-                    env.ptr, enclosingClass.handle, id, allocArgs(args)
-                )
-                CallType.VIRTUAL -> env.pointed?.CallFloatMethodA?.invoke(
-                    env.ptr, instance.handle, id, allocArgs(args)
-                )
-                CallType.DIRECT -> env.pointed?.CallNonvirtualFloatMethodA?.invoke(
-                    env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
-                )
-            } ?: 0F // @formatter:on
-        }
+    ): Float = memScoped {
+        when (descriptor.callType) { // @formatter:off
+            CallType.STATIC -> env.pointed?.CallStaticFloatMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallFloatMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualFloatMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        } ?: 0F // @formatter:on
     }
 
     @OptIn(InternalJniApi::class, UnsafeJniApi::class)
@@ -296,20 +305,18 @@ class JvmMethod(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         args: ArgumentScope.() -> Unit = {}
-    ): Double {
-        return memScoped {
-            when (descriptor.callType) { // @formatter:off
-                CallType.STATIC -> env.pointed?.CallStaticDoubleMethodA?.invoke(
-                    env.ptr, enclosingClass.handle, id, allocArgs(args)
-                )
-                CallType.VIRTUAL -> env.pointed?.CallDoubleMethodA?.invoke(
-                    env.ptr, instance.handle, id, allocArgs(args)
-                )
-                CallType.DIRECT -> env.pointed?.CallNonvirtualDoubleMethodA?.invoke(
-                    env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
-                )
-            } ?: 0.0 // @formatter:on
-        }
+    ): Double = memScoped {
+        when (descriptor.callType) { // @formatter:off
+            CallType.STATIC -> env.pointed?.CallStaticDoubleMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallDoubleMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualDoubleMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        } ?: 0.0 // @formatter:on
     }
 
     @OptIn(UnsafeJniApi::class, InternalJniApi::class)
@@ -317,20 +324,18 @@ class JvmMethod(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         args: ArgumentScope.() -> Unit = {}
-    ): Boolean {
-        return memScoped {
-            when (descriptor.callType) { // @formatter:off
-                CallType.STATIC -> env.pointed?.CallStaticBooleanMethodA?.invoke(
-                    env.ptr, enclosingClass.handle, id, allocArgs(args)
-                )
-                CallType.VIRTUAL -> env.pointed?.CallBooleanMethodA?.invoke(
-                    env.ptr, instance.handle, id, allocArgs(args)
-                )
-                CallType.DIRECT -> env.pointed?.CallNonvirtualBooleanMethodA?.invoke(
-                    env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
-                )
-            }?.toKBoolean() ?: false // @formatter:on
-        }
+    ): Boolean = memScoped {
+        when (descriptor.callType) { // @formatter:off
+            CallType.STATIC -> env.pointed?.CallStaticBooleanMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallBooleanMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualBooleanMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        }?.toKBoolean() ?: false // @formatter:on
     }
 
     @OptIn(ExperimentalNativeApi::class, UnsafeJniApi::class, InternalJniApi::class)
@@ -338,22 +343,20 @@ class JvmMethod(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         args: ArgumentScope.() -> Unit = {}
-    ): Char {
-        return memScoped {
-            // @formatter:off
-            Char.toChars(when (descriptor.callType) {
-                CallType.STATIC -> env.pointed?.CallStaticCharMethodA?.invoke(
-                    env.ptr, enclosingClass.handle, id, allocArgs(args)
-                )
-                CallType.VIRTUAL -> env.pointed?.CallCharMethodA?.invoke(
-                    env.ptr, instance.handle, id, allocArgs(args)
-                )
-                CallType.DIRECT -> env.pointed?.CallNonvirtualCharMethodA?.invoke(
-                    env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
-                )
-            }?.toInt() ?: 0)[0]
-            // @formatter:on
-        }
+    ): Char = memScoped {
+        // @formatter:off
+        Char.toChars(when (descriptor.callType) {
+            CallType.STATIC -> env.pointed?.CallStaticCharMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallCharMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualCharMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        }?.toInt() ?: 0)[0]
+        // @formatter:on
     }
 
     @OptIn(UnsafeJniApi::class, InternalJniApi::class)
@@ -361,21 +364,20 @@ class JvmMethod(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         args: ArgumentScope.() -> Unit = {}
-    ): JvmObject {
-        return memScoped {
-            JvmObject.fromHandle(when (descriptor.callType) { // @formatter:off
-                CallType.STATIC -> env.pointed?.CallStaticObjectMethodA?.invoke(
-                    env.ptr, enclosingClass.handle, id, allocArgs(args)
-                )
-                CallType.VIRTUAL -> env.pointed?.CallObjectMethodA?.invoke(
-                    env.ptr, instance.handle, id, allocArgs(args)
-                )
-                CallType.DIRECT -> env.pointed?.CallNonvirtualObjectMethodA?.invoke(
-                    env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
-                )
-            }
-            ) // @formatter:on
-        }
+    ): JvmObject = memScoped {
+        // @formatter:off
+        JvmObject.fromHandle(when (descriptor.callType) {
+            CallType.STATIC -> env.pointed?.CallStaticObjectMethodA?.invoke(
+                env.ptr, enclosingClass.handle, id, allocArgs(args)
+            )
+            CallType.VIRTUAL -> env.pointed?.CallObjectMethodA?.invoke(
+                env.ptr, instance.handle, id, allocArgs(args)
+            )
+            CallType.DIRECT -> env.pointed?.CallNonvirtualObjectMethodA?.invoke(
+                env.ptr, instance.handle, enclosingClass.handle, id, allocArgs(args)
+            )
+        })
+        // @formatter:on
     }
 
     @OptIn(UnsafeJniApi::class)
@@ -386,13 +388,13 @@ class JvmMethod(
     ): R = callObject(env, instance, args).uncheckedCast<R>()
 
     @OptIn(UnsafeJniApi::class)
-    @Suppress("IMPLICIT_CAST_TO_ANY")
     inline fun <reified R> call(
         env: JniEnvironment,
         instance: JvmObject = JvmObject.NULL,
         closure: ArgumentScope.() -> Unit = {}
     ): R {
         return when (R::class) {
+            Unit::class -> callVoid(env, instance, closure)
             Byte::class -> callByte(env, instance, closure)
             Short::class -> callShort(env, instance, closure)
             Int::class -> callInt(env, instance, closure)
diff --git a/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JvmRuntime.kt b/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JvmRuntime.kt
index 68e9824e72867552a06480cca7528c93a3a40d04..a02d8ed221e9740704f84173f9ad48fe393524c0 100644
--- a/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JvmRuntime.kt
+++ b/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/JvmRuntime.kt
@@ -25,12 +25,50 @@ value class JvmRuntime @UnsafeJniApi private constructor(
 ) : JvmObject {
     companion object {
         @OptIn(UnsafeJniApi::class)
-        fun get(env: JniEnvironment): JvmRuntime? = jniScoped(env) {
+        fun get(env: JniEnvironment): JvmRuntime = jniScoped(env) {
             JvmClass.find(Type.get("java.lang.Runtime")).findMethod {
                 name = "getRuntime"
                 returnType = Type.get("java.lang.Runtime")
                 callType = CallType.STATIC
-            }.callObject().handle?.let(::JvmRuntime)
+            }.callObject().handle.let { JvmRuntime(requireNotNull(it)) }
         }
     }
+
+    fun getAvailableProcessors(env: JniEnvironment): Int = jniScoped(env) {
+        JvmClass.find(Type.get("java.lang.Runtime")).findMethod {
+            name = "availableProcessors"
+            returnType = PrimitiveType.INT
+            callType = CallType.DIRECT
+        }.callInt(this@JvmRuntime)
+    }
+
+    fun getTotalMemory(env: JniEnvironment): Int = jniScoped {
+        JvmClass.find(Type.get("java.lang.Runtime")).findMethod {
+            name = "totalMemory"
+            returnType = PrimitiveType.INT
+            callType = CallType.DIRECT
+        }.callInt(this@JvmRuntime)
+    }
+
+    fun getMaxMemory(env: JniEnvironment): Int = jniScoped {
+        JvmClass.find(Type.get("java.lang.Runtime")).findMethod {
+            name = "maxMemory"
+            returnType = PrimitiveType.INT
+            callType = CallType.DIRECT
+        }.callInt(this@JvmRuntime)
+    }
+
+    fun freeMemory(env: JniEnvironment) = jniScoped(env) {
+        JvmClass.find(Type.get("java.lang.Runtime")).findMethod {
+            this.name = "freeMemory"
+            callType = CallType.DIRECT
+        }.callVoid(this@JvmRuntime)
+    }
+
+    fun gc(env: JniEnvironment) = jniScoped(env) {
+        JvmClass.find(Type.get("java.lang.Runtime")).findMethod {
+            this.name = "gc"
+            callType = CallType.DIRECT
+        }.callVoid(this@JvmRuntime)
+    }
 }
\ No newline at end of file
diff --git a/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/VirtualMachine.kt b/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/VirtualMachine.kt
index 614cd32f2c71c4de119b2ccfa727dd4b97bc12c2..6429c2db449730cc82cd42605b2fcccfd4e7962e 100644
--- a/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/VirtualMachine.kt
+++ b/multiplatform-jni/src/nativeMain/kotlin/io/karma/jni/VirtualMachine.kt
@@ -101,13 +101,15 @@ value class VirtualMachine private constructor(
     }
 
     @OptIn(UnsafeJniApi::class)
-    inline val environment: JniEnvironment?
+    inline val environment: JniEnvironment
         get() = memScoped {
             val address = allocPointerTo<JniEnvironment>()
             handle?.pointed?.GetEnv?.invoke(handle.ptr, interpretCPointer(address.rawPtr), 0)
-            address.pointed
+            requireNotNull(address.pointed) { "Could not retrieve environment" }
         }
 
+    inline fun <reified R> use(closure: JniScope.() -> R): R = jniScoped(environment, closure)
+
     @OptIn(UnsafeJniApi::class)
     fun destroy() {
         handle?.pointed?.DestroyJavaVM?.invoke(handle.ptr)