从strings.xml获取大型字符串数组时出现JNI错误的求助
getStringArray抛出JNI错误的问题 先看你给出的错误日志,核心问题是JNI DETECTED ERROR IN APPLICATION: chars == null && char_count > 0——这说明ART虚拟机在尝试把原生字符串转成Java String时,遇到了「字符指针为空但字符长度大于0」的矛盾情况,大概率是资源解析环节出了问题。结合你提到的「只有大数组报错、精简数据也无效」的细节,给你几个针对性的解决方案:
1. 把<array>替换为<string-array>标签
虽然<array>理论上能存字符串,但Android官方专门提供了<string-array>来处理字符串数组资源,系统对它的解析逻辑更完善,尤其是针对长内容场景。把你的大数组定义改成:
<string-array name="your_large_array"> <item>长内容1</item> <item>长内容2</item> <!-- 其他数组项 --> </string-array>
之后还是用getResources().getStringArray(R.array.your_large_array)调用,很多类似的JNI解析错误都是因为用错资源标签导致的,这个方法最容易验证。
2. 排查数组中的特殊字符或编码问题
精简数据后依然报错,说明大概率不是数组大小的问题,而是某个字符串项里藏着系统解析不了的特殊内容:
- 检查是否有未转义的XML特殊字符,比如
&、'、",这些必须转义成&、'、" - 排查是否存在不可见的Unicode字符(比如零宽空格、控制字符),可以把数组内容复制到Notepad++这类编辑器,开启「显示所有字符」功能检查
- 确保所有字符串的编码都是UTF-8,避免乱码导致解析失败
3. 拆分大型数组
如果上面的方法无效,尝试把大数组拆分成多个小数组,比如:
<string-array name="large_array_part1"> <item>项1</item> <!-- 前半部分内容 --> </string-array> <string-array name="large_array_part2"> <item>项51</item> <!-- 后半部分内容 --> </string-array>
然后在代码里合并数组:
String[] part1 = getResources().getStringArray(R.array.large_array_part1); String[] part2 = getResources().getStringArray(R.array.large_array_part2); String[] fullArray = new String[part1.length + part2.length]; System.arraycopy(part1, 0, fullArray, 0, part1.length); System.arraycopy(part2, 0, fullArray, part1.length, part2.length);
这种方法能绕过系统对单个数组的解析限制,Android 8.1的ART虚拟机可能存在单个数组大小的隐藏阈值。
4. 绕过系统解析,手动读取资源
如果以上方法都不行,直接把大数组内容放在res/raw目录下的文本文件(比如large_array.txt)里,每行存一个数组项,然后手动读取解析:
List<String> arrayList = new ArrayList<>(); InputStream is = getResources().openRawResource(R.raw.large_array); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line; try { while ((line = reader.readLine()) != null) { arrayList.add(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } String[] fullArray = arrayList.toArray(new String[0]);
这种方法完全绕过了系统的getStringArray解析逻辑,从根源上避免JNI层的错误。
建议你先从替换标签开始尝试,这个操作成本最低,很多开发者遇到类似问题都靠这个解决了。
内容的提问来源于stack exchange,提问作者Kvazios

