Skip to content

fix: don't load session_util from ProStatusManager class init - #2154

Closed
Bilb wants to merge 1 commit into
devfrom
fix/pro-status-manager-native-clinit
Closed

fix: don't load session_util from ProStatusManager class init#2154
Bilb wants to merge 1 commit into
devfrom
fix/pro-status-manager-native-clinit

Conversation

@Bilb

@Bilb Bilb commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Problem

testPlayDebugUnitTest has been failing on dev since c203de9 ("Native codepoint counting; route char-limit policy through libsession") — 9 ConversationViewModelTest failures. Every PR branched off dev inherits it (e.g. #2137, which only bumps actions/cache).

From the test-reports artifact (the console log only shows the truncated ExceptionInInitializerError):

java.lang.UnsatisfiedLinkError: no session_util in java.library.path: …
  at network.loki.messenger.libsession_util.LibSessionUtilCApi.<init>(LibSessionUtilCApi.kt:10)
  at …protocol.SessionProtocol.<clinit>(SessionProtocol.kt)
  at org.thoughtcrime.securesms.pro.ProStatusManager.<clinit>(ProStatusManager.kt:495)
  at org.mockito…InlineBytecodeGenerator.assureInitialization(…)

SessionProtocol is a Kotlin object extending LibSessionUtilCApi, whose constructor calls System.loadLibrary("session_util"). Because the char limits were read into companion vals, they were compiled into ProStatusManager.<clinit> — so merely class-loading ProStatusManager loaded the native library. There is no session_util on the JVM, so mock<ProStatusManager>() in ConversationViewModelTest.createViewModel blew up and the 8 subsequent tests followed with NoClassDefFoundError.

Fix

Read both limits through getters instead of storing them in the initialiser, keeping class init free of native side effects. SessionProtocol already caches both values via by lazy, so each call site is still a field read, and the values are only fetched when a real ProStatusManager needs them.

Both are only used from instance methods (getIncomingMessageMaxLength, getCharacterLimit) and nowhere outside the file, so no callers change.

Verification

./gradlew testPlayDebugUnitTest locally: 198 tests, 0 failures (was 198 tests completed, 9 failed in CI).

The companion `val`s reading SessionProtocol.PRO_HIGHER_CHARACTER_LIMIT /
STANDARD_CHARACTER_LIMIT were compiled into ProStatusManager.<clinit>.
SessionProtocol is an object extending LibSessionUtilCApi, whose constructor
calls System.loadLibrary("session_util"), so merely class-loading
ProStatusManager pulled in the native library. There is no session_util on the
JVM, which broke `testPlayDebugUnitTest` on dev: mock<ProStatusManager>() in
ConversationViewModelTest.createViewModel failed with

  UnsatisfiedLinkError: no session_util in java.library.path

and the 8 following tests died with NoClassDefFoundError (9 failures total).

Read both limits through getters instead, keeping class init free of native
side effects. SessionProtocol already caches them via `by lazy`, so each call
site is still a field read, and the values are only fetched when a real
ProStatusManager needs them.
@Bilb

Bilb commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

Closing as https://github.com/session-foundation/session-android/pull/2153/changes already have the same fix

@Bilb Bilb closed this Aug 6, 2026
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.

1 participant