| ## Threading considerations | |
| Unlike method channels, JNIgen uses FFI calls. This means that the calls happen | |
| on the calling thread. | |
| Dart callbacks are executed on the isolate where they were created. This means | |
| the Dart isolate remains active until the associated Java objects are garbage | |
| collected by the JVM. | |
| Java calls Dart callbacks directly when both are on the same thread. If they are | |
| on different threads, Java sends a message to the Dart isolate and waits for a | |
| response. However, you can | |
| [configure void-returning callbacks to avoid waiting](<(../interface_implementation.md#implement-as-a-listener)>), | |
| as they don't produce a return value. | |
| ### Deadlocks | |
| When implementing Java/Kotlin interfaces in Dart, it is possible to create | |
| deadlocks. Suppose we have created an object that implements `Runnable` in Dart | |
| in the main isolate. This means that the code will always be run on the platform | |
| thread. | |
| ```dart | |
| // Dart | |
| final runnableFromDart = Runnable.implement( | |
| $Runnable(run: () => print('hello')) | |
| ); | |
| ``` | |
| If Java creates a second thread from the platform thread and calls | |
| `runnableFromDart.run()` from that thread and then attempts to join or | |
| synchronize with the main thread, it will cause a deadlock. | |
| This is because the body of the `runnableFromDart` needs to be run on the | |
| platform thread, so JNIgen waits until platform thread is available. However in | |
| this setting the platform thread will not be available until | |
| `runnableFromDart.run` is executed. | |
| If the callback does not need to be blocking, | |
| [making it a listener](../interface_implementation.md#implement-as-a-listener) | |
| solves this issue: | |
| ```dart | |
| // Dart | |
| final runnableFromDart = Runnable.implement($Runnable( | |
| run: () => print('hello'), | |
| run$async: true, | |
| )); | |
| ``` | |
| Of course, only void-returning methods can be non-blocking. | |
| ### Calling thread restricted APIs | |
| When developing for Flutter Android, certain APIs can be thread-restricted to | |
| the platform thread which is currently different than the Flutter's UI thread. | |
| These two threads will be merged in | |
| [the near future](https://github.com/flutter/flutter/issues/150525). | |
| Until then you can wrap your calls with `runOnPlatformThread` which is available | |
| in `dart:ui`. | |
| ### Dart-standalone | |
| On Dart-standalone, call `Jni.setDylibsDir` in each new isolate, since each | |
| isolate loads the dynamic libararies separately. |