KNI接口 "KNI_GetFieldID" 调用失败问题的解决
每次调用KNI_GetFieldID总是返回0,也就是在函数_KNI_field_lookup_helper()中执行到如下代码片段:
if (!field.is_valid() || (field.is_static() != is_static) ||
// We do not support field IDs in super classes:
(field.is_static() && !holder().equals(&ic))) {
return (jfieldID)0;
然而在 kni.h 中有这么一段注释:
/**
* Instance field access.
*
* Note specific to this VM: KNI_GetFieldID() must not be applied
* on a class whose
* fields have been renamed by the romizer. You need to use
* the DontRenameNonPublicFields flag in your romizer configuration
* file. See src/vm/cldc_rom.cfg in this VM source distribution
* for an example.
*/
KNIEXPORT jfieldID KNI_GetFieldID(jclass classHandle, const char* name,
const char* signature);
也就是说 class 的 fields 会被 romizer 改名,而KNI_GetFieldID对改名后的 fields 会获取失败;
为避免 fields 被改名,需要在cldc/src/vm/cldc_rom.cfg 中使用DontRenameNonPublicFields,如下:
# Do not rename the non-public fields/methods of the following classes,
# because these fields are accessed by name in KNI code.
DontRenameNonPublicFields = com.eastcom.eui.entity.Contact
DontRenameNonPublicFields = com.sun.cldc.io.ResourceInputStream
If CLDC_11
DontRenameNonPublicFields = java.lang.ref.WeakReference
EndIf
#Some symbols are referenced during bootstrap to verify the class
If ISOLATES
DontRenameNonPublicFields = com.sun.cldc.isolate.Isolate
DontRenameNonPublicMethods = com.sun.cldc.isolate.Isolate
EndIf
修改后验证,KNI_GetFieldID 获取成功。
结论就是KNI对应的JAVA上层实体类的成员一般最好定义成public的,如果是private,
需要修改cldc/src/vm/cldc_rom.cfg文件。
PS: 从字面上理解DontRenameNonPublicFields,private域会被修改,而public域是否不会被改名呢?
KNI_GetFieldID 对 public域是否能总是获取成功?此猜想待验证(不会改名)