Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[kotlin][debugger] Don't throw when exception occurred in the completable future #2871

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

nikita-nazarov
Copy link
Contributor

Sometimes when computing classes with inlined code, an ObjectCollectedException could be thrown in on of the futures. This resulted in failure of CompleatableFuture.allOf(*futures). Because of this, smart stepping and breakpoints in inline functions sometimes didn't work, which was easy to observe when debugging on Android.

@zuevmaxim

@zuevmaxim
Copy link
Contributor

zuevmaxim commented Nov 13, 2024

@nikita-nazarov Could you please attach the error with ObjectCollectedException? I would like to dig deeper into the problem cause

@nikita-nazarov
Copy link
Contributor Author

@zuevmaxim
The exception:

java.util.concurrent.CompletionException: com.sun.jdi.ObjectCollectedException
	at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315)
	at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320)
	at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:649)
	at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:482)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: com.sun.jdi.ObjectCollectedException
	at com.jetbrains.jdi.JDWPException.toJDIException(JDWPException.java:71)
	at com.jetbrains.jdi.PacketStream.processReply(PacketStream.java:135)
	at com.jetbrains.jdi.PacketStream.lambda$readReply$1(PacketStream.java:125)
	at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:646)
	... 4 more

How to reproduce it:
Run IDEA with Android and add recreate the following example:

inline fun iFoo() {
    println()
}

fun foo(f: () -> Unit) {
    f()
}

fun main() {
    foo(::iFoo) // Breakpoint
}

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        main()
        super.onCreate(savedInstanceState)
    }
}

Run the debugger and stop on the breakpoint. Then place a breakpoint inside iFoo and resume the debugger. The breakpoint in iFoo will be skipped and the exception will be thrown.

@zuevmaxim
Copy link
Contributor

@nikita-nazarov Thank you! I can reproduce the issue, but I cannot understand which object is causing it. I see that the exception is thrown during the processing of some android.* classes. Maybe we can handle the exception in some explicit way at the place where it is thrown?
Anyway, could you please specify that we expect ObjectCollectedException? smth like this

                .exceptionally { e ->
                    val exception = DebuggerUtilsAsync.unwrap(e)
                    if (exception is ObjectCollectedException) null else throw e
                }

Sometimes when computing classes with inlined code, an ObjectCollectedException could be thrown in on of the futures. This resulted in failure of `CompleatableFuture.allOf(*futures)`. Because of this, smart stepping and breakpoints in inline functions sometimes didn't work, which was easy to observe when debugging on Android.
@nikita-nazarov nikita-nazarov force-pushed the nazarov/art-smart-step-inline-method-ref branch from 5d8008a to 1cfda72 Compare November 19, 2024 15:24
@nikita-nazarov
Copy link
Contributor Author

@zuevmaxim Hi Maksim!
I've applied the requested change.
Speaking of handling the exception explicitly where it is thrown, the com.sun.jdi.ReferenceType documentation says:

Any method on ReferenceType or which directly or indirectly takes ReferenceType as parameter may throw ObjectCollectedException if the mirrored type has been unloaded.

It means that the exception can be thrown anywhere, for example in com.jetbrains.jdi. I think it is totally fine to handle this exception in one place, namely KotlinPositionManager.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants