Repository navigation
[android] Add opt-in standard JNI for ExecuTorchRuntime and Tensor - #22959
ricardoasouz wants to merge 3 commits into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/22959
Note: Links to docs will display an error until the docs builds have been completed. ✅ You can merge normally! (1 Unrelated Failure)As of commit 8aae748 with merge base a84676e ( BROKEN TRUNK - The following job failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
@pytorchbot label "release notes: none" |
c955beb to
71e717d
Compare
|
Hi @ricardoasouz could you update the branch and give a ping when ready for review? |
71e717d to
2dc8035
Compare
|
@claude review |
|
Claude finished @kirklandsign's task in 1m 54s —— View job The direction looks right, and I found no correctness bugs; the remaining items are a style mismatch in Detailed reviewPR Review: #22959SummaryThe PR moves
Code Quality
Testing
RecommendationApprove once the instrumentation tests pass on a device. Nothing above blocks the change; the helper restructuring is a small style fix. |
2dc8035 to
fd1943b
Compare
|
@nil-is-all @kirklandsign Updated the branch again after main moved; it is mergeable now and ready for review. I reran the Android validation locally:
The test fix remains separate in #23480. The shared The branch is now stable at Could you re-sync the internal Diff with this head and approve the pending workflows here and on #23480 so CI can run? |
|
@psiddh has imported this pull request. If you are a Meta employee, you can view this in D123563084. |
fd1943b to
ceb88a9
Compare
psiddh
left a comment
There was a problem hiding this comment.
Thanks @ricardoasouz for the contribution. Moving this into "Request changes" state as we need to validate this against internal Apps surface and make sure it passes internal review and CI. Thanks again and I will get back on this PR with clear next steps.
|
@ricardoasouz Can we introduce a --disable-jni flag or some such (default value is off), If this flag is off, we continue to rely on fbjni , if enabled, rely standard JNI. that way , with the flag disabled, there is no change to existing functionality with minimum to no risk of regression. ? |
ceb88a9 to
8de9880
Compare
@psiddh Done — I added an opt-in The default is The flag is wired through both CMake and Buck. For the public Android build script, Validation after rebasing onto current
The new head is |
145bdfa to
ab5fefa
Compare
@psiddh @nil-is-all The requested opt-in The current head is Thanks! |
ab5fefa to
cd2a8a0
Compare
|
Hi @psiddh @nil-is-all @kirklandsign, The latest head ( The CI has completed with 202 successful checks, including the Android build and emulator tests. There are two remaining blockers:
No further code changes are planned unless internal validation or review identifies an issue. Thanks for your help! |
Thanks for the ping, @ricardoasouz. Could you update the out-of-date branch? I'll run CI and re-import the latest commit internally to do a final check. |
cd2a8a0 to
998514e
Compare
|
@nil-is-all Thanks! I've updated the branch by rebasing onto the latest The new HEAD is Thanks for your help! |
jni_layer.cpp and jni_layer_training.cpp each declared TensorHybrid and JEValue, and the two definitions differed, which violates the ODR. The training translation unit also relied on the inline member definitions in jni_layer.cpp being emitted there. Move the declarations to jni_layer_types.h and define the members out of line in jni_layer.cpp. TensorHybrid becomes JTensor, matching JEValue. The conversion logic is unchanged. Part of pytorch#10444 Signed-off-by: Ricardo Alves de Souza <ricardoasouz@hotmail.com>
Add an opt-in build option, OFF by default, that switches bindings to standard JNI as they are migrated off fbjni. It is available as a CMake option, as the executorch.use_generic_jni Buck config read by every target that compiles the JNI sources (selective_jni_target included), and as an environment variable for scripts/build_android_library.sh. With the option ON, ExecuTorchRuntime's natives are exported as Java_* symbols, which version_script.txt already keeps global, instead of being registered through fbjni. With it OFF, the existing fbjni code is compiled unchanged. Part of pytorch#10444 Signed-off-by: Ricardo Alves de Souza <ricardoasouz@hotmail.com>
The C++ side of JTensor holds no state: the HybridClass constructor discards its argument, and the HybridData attached to each Java Tensor created from native is never read back. With EXECUTORCH_USE_GENERIC_JNI ON, JTensor becomes a plain JavaClass and native code creates tensors through a nativeNewTensor overload without the HybridData parameter, so no C++ object is allocated for each tensor returned to Java. With the option OFF, JTensor and the existing nativeNewTensor call are compiled unchanged; that overload now delegates to the new one before attaching the HybridData. Part of pytorch#10444 Signed-off-by: Ricardo Alves de Souza <ricardoasouz@hotmail.com>
998514e to
8aae748
Compare
|
@psiddh @kirklandsign @larryliu0820 @nil-is-all I rebuilt this PR on main (new head This is the opt-in flag psiddh suggested on Oct 7. I named it Two other changes since the last revision: the Buck flag now also reaches While validating, I found that The earlier |
Summary
Part of #10444. This adds
EXECUTORCH_USE_GENERIC_JNI, an opt-in build option that is OFF by default, and uses it to moveExecuTorchRuntimeandTensorfrom fbjni to standard JNI. With the option OFF the bindings build from the same fbjni code paths as on main, so the default build keeps its current behavior.libfbjni.sostays a dependency in both modes, sinceModule,LlmModule,TrainingModuleandSGDstill useHybridClass.The option is exposed as a CMake option, as the
executorch.use_generic_jniBuck config (applied to every target that compiles the JNI sources,selective_jni_targetincluded), and as an environment variable forscripts/build_android_library.sh.With the option ON,
ExecuTorchRuntime's natives are exported asJava_*symbols, whichversion_script.txtalready keeps global, instead of being registered through fbjni.JTensoralso becomes a plainJavaClass: as aHybridClassits C++ instance held no state, since the constructor discarded its argument and theHybridDataattached to each JavaTensorwas never read back. Native code then creates tensors through anativeNewTensoroverload without that parameter, so no C++ object is allocated for each tensor returned to Java. The dim order support from #23820 is carried into both paths.Review order: the first commit moves the
JTensorandJEValuedeclarations intojni_layer_types.hand defines the members out of line injni_layer.cpp.jni_layer.cppandjni_layer_training.cppeach declared these classes with different definitions, which violated the ODR, and the training translation unit depended onjni_layer.cppemitting the inline definitions. The function bodies are unchanged; the size of the diff comes from indentation and theTensorHybrid→JTensorrename. The second commit adds the option and theExecuTorchRuntimepath, and the third adds theTensorpath. In both, the existing fbjni code stays as it is under#else.The Buck changes can't be built in OSS because
fb_android_cxx_libraryis Meta-only, so they are worth a check during the import.Test plan
On
8aae748, based ona84676e:Built with
scripts/build_android_library.shfor x86_64 withEXECUTORCH_USE_GENERIC_JNIunset (OFF) and set to ON; the Gradle build (lint and spotless) and the unit tests pass in both. With ON,llvm-nm -DlistsJava_org_pytorch_executorch_ExecuTorchRuntime_getRegisteredOpsandgetRegisteredBackends; with OFF they are absent.libfbjni.soisNEEDEDin both.Instrumentation tests on an x86_64 API 30 emulator (
RuntimeInstrumentationTest,ModuleInstrumentationTest,ModuleE2ETest,TrainingModuleE2ETest): 27/29 pass with OFF and 27/29 with ON. The two failures aretestMissingPteFileandtestMissingPtdFile, whose expected messages are stale on main and are updated in #23480.ModuleInstrumentationTest#testNonPteFileis excluded from those runs because it aborts the test process, on main (a84676e) as well. The abort comes from fbjni'sgetJavaExceptionForCppExceptionreceiving a nullstd::exception_ptr(abort messageptr), called fromtranslatePendingCppExceptionToJavaException.libexecutorch.solinks libc++ statically while the prebuiltlibfbjni.souseslibc++_shared, which would explain it. This is independent of this PR.