There're two broad ways in which you can declare JNI functions.
The first is the more obvious way in which the JNI function has to follow a specific naming convention like JNIEXPORT void JNICALL Java_com_app_foo_bar. You can easily identify such functions using readelf.
The other not so obvious way is to use RegisterNatives. Here your functions can have any signature and further they not need be exported from the shared library. Typically, you would call RegisterNatives from JNI_OnLoad to register the native functions to the Java Run-time.
For your binary libcms.so, it uses the second method.
RegisterNatives has the following prototype
jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint Methods);
If you analyze the code of JNI_OnLoad you will come across RegisterNatives call like below.

The third argument points to an array of JNINativeMethod structures which is declared as
typedef struct {
char *name;
char *signature;
void *fnPtr;
} JNINativeMethod;
The first member is a pointer to a null terminated string denoting the function name. However, in your case all the names and signatures are encrypted.

These are decrypted at run-time by the .datadiv_decodeXXXXXXXX family of functions. The .init_array section contain pointers to these decryptor functions which implies they will be called at startup.

However, that is not all. The binary also employs Control Flow Flattening Obfuscation throughout, hence the execution path may not be easily discernible as shown below.

To analyze the binary you're better off resorting to dynamic analysis techniques using a tool such as Frida.
Further Read:
.datadiv_decodeseries of functions. – 0xec Oct 13 '19 at 07:51