kotlinx.coroutines
kotlinx.coroutines copied to clipboard
Guard against OutOfMemoryError in coroutine internals
trafficstars
We got a report of coroutines failing to finish when an OOM happens. The internal link is https://youtrack.jetbrains.com/issue/IJPL-172305, and here is the relevant part of the stacktrace:
kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[Dispatchers.EDT, Continuation at com.
at kotlinx.coroutines.DispatchedTask.handleFatalException$kotlinx_coroutines_core(DispatchedTask.kt:142)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:113)
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.base/jdk.internal.org.objectweb.asm.SymbolTable.<init>(SymbolTable.java:156)
at java.base/jdk.internal.org.objectweb.asm.ClassWriter.<init>(ClassWriter.java:297)
at java.base/jdk.internal.org.objectweb.asm.ClassWriter.<init>(ClassWriter.java:267)
at java.base/java.lang.invoke.InvokerBytecodeGenerator.classFilePrologue(InvokerBytecodeGenerator.java:270)
at java.base/java.lang.invoke.InvokerBytecodeGenerator.generateCustomizedCodeBytes(InvokerBytecodeGenerator.java:753)
at java.base/java.lang.invoke.InvokerBytecodeGenerator.generateCustomizedCode(InvokerBytecodeGenerator.java:712)
at java.base/java.lang.invoke.LambdaForm.compileToBytecode(LambdaForm.java:849)
at java.base/java.lang.invoke.LambdaForm.prepare(LambdaForm.java:807)
at java.base/java.lang.invoke.MethodHandle.<init>(MethodHandle.java:482)
at java.base/java.lang.invoke.BoundMethodHandle.<init>(BoundMethodHandle.java:52)
at java.base/java.lang.invoke.BoundMethodHandle$Species_L.<init>(BoundMethodHandle.java:210)
at java.base/java.lang.invoke.BoundMethodHandle$Species_L.make(BoundMethodHandle.java:225)
at java.base/java.lang.invoke.BoundMethodHandle.makeReinvoker(BoundMethodHandle.java:114)
at java.base/java.lang.invoke.DirectMethodHandle.rebind(DirectMethodHandle.java:148)
at java.base/java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandleImpl.java:289)
at java.base/java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:265)
at java.base/java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:382)
at java.base/java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:905)
at java.base/java.lang.invoke.MethodHandle.asType(MethodHandle.java:870)
at java.base/jdk.internal.reflect.MethodHandleIntegerFieldAccessorImpl.fieldAccessor(MethodHandleIntegerFieldAccessorImpl.java:44)
at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.newFieldAccessor(MethodHandleAccessorFactory.java:156)
at java.base/jdk.internal.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:145)
at java.base/java.lang.reflect.Field.acquireOverrideFieldAccessor(Field.java:1200)
at java.base/java.lang.reflect.Field.getOverrideFieldAccessor(Field.java:1169)
at java.base/java.lang.reflect.Field.get(Field.java:444)
at kotlin.coroutines.jvm.internal.DebugMetadataKt.getLabel(DebugMetadata.kt:96)
at kotlin.coroutines.jvm.internal.DebugMetadataKt.getStackTraceElement(DebugMetadata.kt:44)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.getStackTraceElement(ContinuationImpl.kt:76)
at kotlinx.coroutines.debug.internal.DebugProbesImpl.realCaller(DebugProbesImpl.kt:462)
at kotlinx.coroutines.debug.internal.DebugProbesImpl.updateRunningState(DebugProbesImpl.kt:451)
at kotlinx.coroutines.debug.internal.DebugProbesImpl.updateState(DebugProbesImpl.kt:428)
at kotlinx.coroutines.debug.internal.DebugProbesImpl.probeCoroutineResumed$kotlinx_coroutines_core(DebugProbesImpl.kt:419)
The only thing we can do in a scenario when any allocation can fail is to avoid allocating in the parts of the library responsible for liveness.