1. 背景
当我们开发串口通信相关的应用时,通常需要通过串口的名称获取到串口的资源,然后收发消息,最后释放串口给其它应用。但是在部分情况下,serialPort.closePort();并不能释放端口,用SSCOM再进行端口打开还是提示占用。
2.SerialPort.getCommPort(portLinkName) 存在问题
由于网络上没有太多有用信息,在尝试了多处没有效果后,我开始将目标瞄准这个静态方法。发现这个静态方法中有这样的代码:
// Create the SerialPort object
SerialPort serialPort = new SerialPort();
serialPort.comPort = portDescriptor;
serialPort.friendlyName = "User-Specified Port";
serialPort.portDescription = "User-Specified Port";
return serialPort;
而且在setComPortParameters中调用了本地方法,然而它并没有写finalize。
我就猜想它是否无法释放对应的系统资源?每次这样获取和设定时,是否都会导致系统增加对于对象的引用,然后无法释放资源?
3.解决方案
那每次创建这个对象时,必须用Map存起来,然后再次使用的时候,指向这个唯一的对象,不再通过SerialPort.getCommPort(portLinkName)来获取。
比如:
portIdToSerialPortMap.putIfAbsent(portInfoId, serialPort);
需要操作它的时候,从Map中拿:
portIdToSerialPortMap.get(portInfoId);
当我们调用serialPort.closePort();后,则从Map中移除:
portIdToSerialPortMap.remove(portId);
这样我们的SSCOM不再持续报端口占用了,我们顺利解决了此问题。
总结
这个错误告诉我们:在使用操作系统资源时,尤其是设备时,需要考虑到 Java 是否调用了 native 方法,如果有这种情况,则需要管理好每一次资源的申请和释放。