Throwing OutOfMemoryError “Could not allocate JNI Env“

09-09 15:28:57.588 7460-7471/com.moreunion.zhenghao I/art: Background sticky concurrent mark sweep GC freed 74917(4MB) AllocSpace objects, 15(580KB) LOS objects, 7% free, 59MB/64MB, paused 6.228ms total 59.379ms

07-22 11:55:26.373 17580 17590 I art : Background sticky concurrent mark sweep GC freed 1047697(16MB) AllocSpace objects, 0(0B) LOS objects, 31% free, 29MB/43MB, paused 4.934ms total 159.085ms
1207-22 11:55:26.377 17580 17862 E art : ashmem_create_region failed for 'indirect ref table': Bad file descriptor
1307-22 11:55:26.377 17580 17862 W art : Throwing OutOfMemoryError "Could not allocate JNI Env"
1407-22 11:55:26.387 17580 17580 I MainView: updateTMSIList
1507-22 11:55:26.370 17862 17862 W pool-6-thread-1: type=1400 audit(0.0:133498): avc: denied { read } for name="mem" dev="debugfs" ino=1015374 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:debugfs:s0 tclass=file permissive=0
1607-22 11:55:26.370 17862 17862 W pool-6-thread-1: type=1400 audit(0.0:133499): avc: denied { read } for name="mem" dev="debugfs" ino=1015374 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:debugfs:s0 tclass=file permissive=0

Throwing OutOfMemoryError “Could not allocate JNI Env”

可以导致OOM的原因有以下几种:

文件描述符(fd)数目超限,即proc/pid/fd下文件数目突破/proc/pid/limits中的限制。可能的发生场景有:
短时间内大量请求导致socket的fd数激增,大量(重复)打开文件等
线程数超限,即proc/pid/status中记录的线程数(threads项)突破/proc/sys/kernel/threads-max中规定的最大线程数。可能的发生场景有:
app内多线程使用不合理,如多个不共享线程池的OKhttpclient等等
传统的java堆内存超限,即申请堆内存大小超过了 Runtime.getRuntime().maxMemory()
(低概率)32为系统进程逻辑空间被占满导致OOM.
其他

可以利用linux的inotify机制进行监控:

watch /proc/pid/fd来监控app打开文件的情况,
watch /proc/pid/task来监控线程使用情况

### 解决方案分析 在处理 PCL 库中的 `pcl::PCDWriter` 出现的 `IOException` 异常时,通常是因为输入点云数据存在问题或者参数配置不正确。以下是针对该问题的具体解决方案: #### 1. **确认点云是否有有效数据** 如果程序抛出了 `[pcl::PCDWriter::writeASCII] Input point cloud has no data!` 的错误,则表明尝试写入的点云对象为空[^1]。这可能是由于点云未被正确初始化或填充。 - 需要验证点云是否已经加载了有效的点数据。 - 可以通过打印点云大小来检查其有效性: ```cpp std::cout << "Point Cloud Size: " << cloud->size() << std::endl; if(cloud->empty()){ std::cerr << "Error: Point cloud is empty!" << std::endl; } ``` #### 2. **校验宽度和高度的一致性** 当遇到 `[pcl::PCDWriter::writeASCII] Number of points different than width * height!` 错误时,说明点云的实际点数与其定义的宽度 (`width`) 和高度 (`height`) 不匹配[^2]。 - 点云的 `width` 表示每行的点数量,而 `height` 则表示总行数。两者相乘应等于实际存储的点的数量。 - 如果手动设置了这些属性,请确保它们与点云的真实结构一致。可以通过以下方式调整: ```cpp cloud->width = static_cast<uint32_t>(cloud->points.size()); cloud->height = 1; // 对于无序点云,默认设置为1 cloud->is_dense = false; // 设置为false允许存在无效点 ``` #### 3. **二进制模式下的特殊注意事项** 对于某些特定场景,在使用 `pcl::PCDWriter::writeBinary` 方法时可能会触发类似的异常。例如,浮点精度设置不当可能导致内部计算失败[^3]。 - 若发现更改某个数值(如从 `1.0` 修改至 `1000.0` 后恢复正常),则需进一步审查涉及此变量的相关逻辑及其默认值设定。 - 建议始终遵循官方文档推荐的最佳实践,并保持一致性。 #### 综合代码实例 下面提供了一段完整的示范代码用于安全保存点云到 `.pcd` 文件中: ```cpp #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> int main(){ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 添加一些测试点 for(int i=0;i<5;i++) { pcl::PointXYZ point; point.x = float(i); point.y = float(i)*2; point.z = 0.f; cloud->push_back(point); } // 检查并修正元数据 if(!cloud->isOrganized()) { cloud->width = static_cast<uint32_t>(cloud->points.size()); cloud->height = 1; } try{ pcl::io::savePCDFileASCII("output.pcd",*cloud); std::cout<<"Saved file successfully."<<std::endl; } catch(const pcl::IOException& e){ std::cerr << "Exception caught:" << e.what()<<std::endl; } return 0; } ``` ### 总结 上述方法涵盖了从基础排查到高级调试技巧等多个层面的内容,能够有效地帮助开发者定位并修复由 `pcl::PCDWriter` 所引发的各种 IO 异常情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值