下面是一段参考网上的检测串口,能实时检测到有多少个串口或者虚拟串口连接,并且返回串口名字。
但是循环运行一段时间之后,就会出现
nSetOwner: Error 8 in MapViewOfFile
的错误,而且在运行过程当中,内存也在渐渐上升(如果每2ms调用一次,大概每秒内存增加8k,3分钟左右出现上面错误,时延增加之后,会运行长一点时间,但是也会出错)请高手们指点一下,谢谢,下面是程序段。public int getConnectedComPorts(String [] Coms){
    int index=0;
    Enumeration en;
    try //try reloading the driver
    {
        Field masterIdList_Field = CommPortIdentifier.class.getDeclaredField("masterIdList");
        masterIdList_Field.setAccessible(true);
        masterIdList_Field.set(null, null);
        //  String temp_string = "lib" + File.separator + "javax.comm.properties";        String temp_string = System.getProperty("java.home") + File.separator + "lib" + File.separator + "javax.comm.properties";        //    JOptionPane.showMessageDialog(null, temp_string);
        Method loadDriver_Method = CommPortIdentifier.class.getDeclaredMethod("loadDriver", new Class[] {String.class});
        loadDriver_Method.setAccessible(true); //unprotect it
        loadDriver_Method.invoke(null, new Object[] {temp_string});    
        en = CommPortIdentifier.getPortIdentifiers();
        masterIdList_Field = null;
        temp_string = null;
        loadDriver_Method=null;        CommPortIdentifier portId;
        while (en.hasMoreElements())
        {            portId = (CommPortIdentifier)en.nextElement();         //   System.out.println("sss");
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL)
            {
                Coms[index] = portId.getName();
                index++;
             //   System.out.println(spotCom+"sss");
            }
            portId=null;
       
        }
        en = null;
    }
    catch(Exception e)
    {
    //System.out.println("error:"+e); //***** add logger
        JOptionPane.showMessageDialog(null, "serial library load fail");
    }
    return index;}

解决方案 »

  1.   

    下面的这段代码是加载驱动,个人认为没必要每次都去加载,加载一次足以。
    Method loadDriver_Method = CommPortIdentifier.class.getDeclaredMethod("loadDriver", new Class[] {String.class});
            loadDriver_Method.setAccessible(true); //unprotect it
            loadDriver_Method.invoke(null, new Object[] {temp_string}); 不规范代码,字符串级联:
    String temp_string = System.getProperty("java.home") + File.separator + "lib" + File.separator + "javax.comm.properties"; 
    temp_string这本身就是一个固定的字符串,干嘛每次都去级联计算,凭空多出那么多对象,何况还是循环!!一次构建,作为全局变量。MapViewOfFile 的错误代码8是内存不足,建议代码规范后适当加大程序内存分配:-Xmx128m
      

  2.   

    这个很明显是采用Enumeration 占用内存的问题。Enumeration en=en.elements(); 
    while(en.hasMoreElements()){ 
    portId = (CommPortIdentifier)en.nextElement(); 

    上面的语句看起来很简洁,但是却不适用于J2ME/Sockets开发,
    因为当程序中有比较多的Vector对象时,如果都用上面的语句进行遍历就会产生许多Enumeration对象,带来很大的额外内存开销,
    可以采用以下语句遍历: int n=v.size(); for(int i=0;i ...            
      

  3.   

    我把和Enumeration有关的代码都注释掉了,还是一样出错,可能问题不是出在这里。问题确实是出在多次重复加载驱动上。如果注释掉这三行代码,长时间运行也没有错误,但是如果不重新加载驱动,程序运行之后新增加的串口不会出现在列表里面。这也是这三行代码的作用。我不太明白这几行代码的意思,所以也不知道该怎么改。有没有办法加载完之后,读出来串口信息,再把驱动卸载?非常感谢高手们的指点!
      

  4.   

    又试了几次,发现Enumeration也确实在占用内存。但是CommPortIdentifier.getPortIdentifiers(); 返回的就是Enumeration类型。
    有没有办法使用6楼说的方法呢?driver的问题还没解决,用另外的办法:
    在类初始化的时候调用:
    System.loadLibrary("win32com");
    driver = (CommDriver)Class.forName("com.sun.comm.Win32Driver").newInstance();
    然后再我的循环里面只调用
    driver.initialize();
    代替三行loaddriver的代码。能找到新连上的串口,但是还是会出现同样的mapviewoffile错误。呜呜~~~, 高手们帮帮忙想想办法啊,我也好早点结贴给分!谢谢啦
      

  5.   

    把driver.initialize(); 放到循环外(在类初始化时)不行么?
      

  6.   

    或者看看这个文章:http://piscesky.javaeye.com/blog/282024
    代码太多,不好贴。
      

  7.   

    把driver.initialize()放到循环外面之后,就不能实时刷新串口的情况了。如果在运行程序之前,系统有com1和com3,那么运行程序之后,连接com4,列表中永远只有com1和com3,除非重新运行一次driver.initialize() 才会将com4刷新到列表里面。这可能是串口API的一个bug吧。
    后来发现windwos的注册表里面实时更新串口信息,所以换了一个办法了(这个办法可能是原创,呵呵~~),不断读注册表信息,便能知道串口的实时连接情况。
    public int getConnectedComPorts(String [] Coms){
        int index=0;
        if(regkey.hasValues()) {
               Iterator i = regkey.values();
               while(i.hasNext()) {
                  RegistryValue v = (RegistryValue)i.next();
                  String str = v.toString();
                  int tmp = str.indexOf("COM");
                  int tmp1 = str.indexOf("USBSER000");//因为我是USB的串口,缩小寻找串口的范围
                  if(tmp!=-1&&tmp1!=-1){
                      Coms[index] = str.substring(tmp);
                      index++;
                  }
               } // while
          }
        return index;
    }长时间运行,没有错误,也没内存泄漏问题,算是临时解决了我的需求了;p非常感谢各位高手的指点,帮我指出了问题,给分结贴!