Android集成ARCore与ML Kit调用process方法报内部错误及SIGSEGV崩溃
问题描述
我正按照ARCore官方文档的指引,在Android Studio中开展ARCore与ML Kit的集成开发,所使用的Java代码如下:
ObjectDetector objectDetector = createObjectDetector(); Image cameraImage = null; try { cameraImage = frame.acquireCameraImage(); // Process `cameraImage` using your ML inference model. objectDetector.process(InputImage.fromMediaImage(cameraImage, getRotationCompensation("1", this, false))) .addOnSuccessListener( new OnSuccessListener<List<DetectedObject>>() { @Override public void onSuccess(List<DetectedObject> detectedObjects) { // Task completed successfully // The list of detected objects contains one item if multiple // object detection wasn't enabled. for (DetectedObject detectedObject : detectedObjects) { Rect boundingBox = detectedObject.getBoundingBox(); Integer trackingId = detectedObject.getTrackingId(); for (DetectedObject.Label label : detectedObject.getLabels()) { String text = label.getText(); if (PredefinedCategory.FOOD.equals(text)) { } int index = label.getIndex(); if (PredefinedCategory.FOOD_INDEX == index) { } float confidence = label.getConfidence(); } } } }) .addOnFailureListener( new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception Log.e("Failure Listener", e.getMessage()); } }); } catch (NotYetAvailableException e) { // NotYetAvailableException is an exception that can be expected when the camera is not ready // yet. The image may become available on a next frame. } catch (RuntimeException e) { // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException. // Handle this error appropriately. Log.e("Error", e.toString()); } catch (CameraAccessException e) { e.printStackTrace(); } finally { if (cameraImage != null) { cameraImage.close(); } }
代码运行时出现如下报错:
Internal error has occurred when executing ML Kit tasks
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4faee70000000 in tid 14906 ...
经初步定位,错误由objectDetector.process(...)触发。
问题根因
这个SIGSEGV段错误属于native层内存访问违规,核心原因是图像资源提前释放:
ML Kit的process()方法是异步执行的,调用该方法后推理任务会在后台线程运行,当前线程会立刻走到外层finally代码块执行cameraImage.close()。此时后台推理线程还在读取cameraImage绑定的native内存,访问已经被释放的内存地址就会触发段错误崩溃。
另外两个可能触发同类崩溃的诱因:
ObjectDetector实例频繁创建销毁,没有全局复用,导致native内存泄漏/野指针getRotationCompensation()返回的旋转角度不是0/90/180/270四个合法值,触发ML Kit图像处理逻辑的native异常
修复方案
- 移除原有外层try-catch的
finally块中关闭cameraImage的逻辑 - 将图像关闭逻辑绑定到ML Kit推理任务的完成回调中,保证推理完成后再释放资源
- 将
ObjectDetector改为全局单例复用,不要每帧新建检测器 - 校验旋转角度返回值,确保为0、90、180、270四个合法值
修正后的核心代码如下:
// ObjectDetector设为全局单例复用,禁止在帧回调中重复创建 private final ObjectDetector objectDetector = createObjectDetector(); // 帧处理逻辑 Image cameraImage = null; try { cameraImage = frame.acquireCameraImage(); int rotation = getRotationCompensation("1", this, false); // 校验旋转角度合法性 if (rotation % 90 != 0) { cameraImage.close(); return; } InputImage inputImage = InputImage.fromMediaImage(cameraImage, rotation); objectDetector.process(inputImage) .addOnSuccessListener(detectedObjects -> { // 原有检测结果处理逻辑保持不变 for (DetectedObject detectedObject : detectedObjects) { Rect boundingBox = detectedObject.getBoundingBox(); Integer trackingId = detectedObject.getTrackingId(); for (DetectedObject.Label label : detectedObject.getLabels()) { String text = label.getText(); if (PredefinedCategory.FOOD.equals(text)) {} int index = label.getIndex(); if (PredefinedCategory.FOOD_INDEX == index) {} float confidence = label.getConfidence(); } } }) .addOnFailureListener(e -> Log.e("ML Kit Inference", e.getMessage())) // 推理任务无论成功失败,执行完成后再释放图像资源 .addOnCompleteListener(task -> { if (cameraImage != null) { cameraImage.close(); } }); } catch (NotYetAvailableException e) { // 相机未就绪属于正常情况,直接跳过当前帧即可 } catch (RuntimeException | CameraAccessException e) { Log.e("Frame Acquire Error", e.toString()); // 获取帧异常分支也要及时释放已获取的图像 if (cameraImage != null) { cameraImage.close(); } }
内容的提问来源于stack exchange,提问作者salam
相关产品推荐
相关产品推荐

