2015-06-25 2 views
1

Я пишу приложение на платформе NetBeans (7.4), и я создал пользовательский тип ProjecType и FileType. В ProjectType есть слабый прослушиватель изменений файлов для удаления новых файлов в папке проекта. Проблема заключается в том, что если открыть проект, закрыть его, а затем попытаться вновь открыть его снова, он бежит из памяти и либо выдает исключение мьютекс:Платформа NetBeans Re-Open Closed Project StackOverflowError

Blockquote java.lang.IllegalStateException: Не следует приобретать Children.MUTEX, удерживая ProjectManager.mutex

или IllegalStateException:

BLOCKQUOTE java.lang.IllegalStateException: на org.openide.nodes.Node.assignTo (Node.java:354) на org.openide.nodes.EntrySupportDefault.justCo mputeNodes (EntrySupportDefault.java:212) на org.openide.nodes.ChildrenArray.nodes (ChildrenArray.java:88) на org.openide.nodes.EntrySupportDefault.getNodes (EntrySupportDefault.java:130) на org.openide. nodes.EntrySupportDefault.getNodes (EntrySupportDefault.java:172) в org.openide.nodes.Children.getNodes (Children.java:469)

Еще одна интересная вещь, что если я закрыть проект и сделать малейшее перейдите в папку проекта, например, переместите ее в новое место или даже просто откройте файл в этой папке, когда я попытаюсь перезагрузить его, он отлично работает. Я попытался полностью удалить слабый прослушиватель файлов, но не успел. И я знаю, что это не проблема с прослушивателем файлов, потому что Windows не мешает мне манипулировать файлами в папке проекта. Bellow - это мой ProjectNodeFactory, который создает дочерние узлы для каждого распознанного типа файла в папке проекта.

public class MyProjectNodeFactory extends ChildFactory<FileObject> implements FileChangeListener { 

private final FileObject projectFolder; 

public MyProjectNodeFactory(MyProjectNode project) { 
    this.projectFolder = project.getProjectDirectory();     
    project.addFileChangeListener(this); 
    refresh(true); 
} 

@Override 
protected boolean createKeys(List<FileObject> list) { 

    for (FileObject fileObject : Collections.list(projectFolder.getData(false))) 
    { 
     if (fileObject.getExt().equals(Bundle.MY_FILETYPE_EXTENSION())) { 
      list.add(fileObject); 
     } 
    } 
    return true; 
} 

@Override 
protected Node[] createNodesForKey(FileObject key) { 
    ArrayList<Node> nodes = new ArrayList<Node>(); 
    // Add data files        
    try { 
     if(key.getExt().equals(Bundle.MY_FYLETYPE_EXTENSION())) 
     { 
      nodes.add(DataObject.find(key).getNodeDelegate());     
     } 
    } catch (DataObjectNotFoundException ex) { 
     Exceptions.printStackTrace(ex);     
    }        
    return (nodes.toArray(new Node[nodes.size()])); 
} 

Кроме того мой ProjecType LogicalView и ProjectNode

public class MyProjectType implements Project { 

private final FileObject projectDir; 
private final ProjectState state; 
private FileChangeListener fileChangeListener; 
private Lookup lkp; 

MyProjectType(FileObject dir, ProjectState state) { 
    this.projectDir = dir; 
    this.state = state; 
} 

@Override 
public FileObject getProjectDirectory() { 
    return projectDir; 
} 

@Override 
public Lookup getLookup() { 
    if (lkp == null) { 
     lkp = Lookups.fixed(new Object[]{ 
      // register your features here 
      this, 
      new MyProjectInfo(), 
      new MyProjectLogicalView(this),}); 
    } 
    return lkp; 
} 

public void addFileChangeListener(FileChangeListener regularFileChangeListener) { 
    this.fileChangeListener = (FileChangeListener)WeakListeners.create(FileChangeListener.class, regularFileChangeListener, this.projectDir.getPath());   
    this.projectDir.addFileChangeListener(fileChangeListener); 
} 

public void removeFileChangeListeners() { 
    if(fileChangeListener!=null) 
     this.projectDir.removeFileChangeListener(fileChangeListener); 
} 

private final class MyProjectInfo implements ProjectInformation { 

    @StaticResource() 
    public static final String PROJECT_ICON = "projectIcon.png"; 

    .................. 

} 

class MyProjectLogicalView implements LogicalViewProvider { 

    @StaticResource() 
    public static final String PROJECT_ICON = "projectIcon.png"; 

    private final MyProjectType project; 

    public MyProjectLogicalView(MyProjectType project) { 
     this.project = project;  
    } 

    @Override 
    public Node createLogicalView() { 
     try { 
      FileObject projectDirectory = project.getProjectDirectory(); 
      DataFolder projectFolder = DataFolder.findFolder(projectDirectory); 
      Node nodeOfProjectFolder = projectFolder.getNodeDelegate(); 

      return new ProjectNode(nodeOfProjectFolder, project); 
     } catch (DataObjectNotFoundException donfe) { 
      Exceptions.printStackTrace(donfe); 
      return new AbstractNode(Children.LEAF); 
     } 
    } 

    private final class ProjectNode extends FilterNode { 

     final MyProjectType project; 

     public ProjectNode(Node node, MyProjectType project) 
       throws DataObjectNotFoundException { 
      super(node, 
        Children.create(new MyProjectNodeFactory(project),true), 
        new ProxyLookup(
          new Lookup[]{ 
           Lookups.singleton(project), 
           node.getLookup() 
          })); 
      this.project = project; 
     } 

     @Override 
     public Action[] getActions(boolean arg0) { 
      return new Action[]{ 
       CommonProjectActions.newFileAction(), 
       CommonProjectActions.copyProjectAction(), 
       CommonProjectActions.deleteProjectAction(), 
       CommonProjectActions.closeProjectAction() 
      }; 
     } 

     ............... 
    } 

} 

ответ

1

После много прибегая к помощи и отладки я не был в состоянии обнаружить, почему происходит эта утечка памяти, но я нашел решение по следующей ссылке, которая может оказаться полезным для других людей, работающих в одной и той же проблеме. Solution to Open/Close/Re-Open a NetBeans Platform ProjectType

Решение состоит в том, чтобы получить клон дочерних узлов, а не только делегата.

public Node node(FileObject key) { 
    DataFolder folder = DataFolder.findFolder(key); 
    return folder.getNodeDelegate().cloneNode(); 
} 

Я до сих пор не понимаю, почему getNodeDelegate() не является достаточным, но я предполагаю, что, когда проект первого закрыт, некоторые ссылки не будут освобождены, и он работает в проблемы при повторном открытии. Получив клон, он создает совершенно новый родительский узел без этих проблем. Надеюсь, это помогает кому-то, потому что мне трудно найти решение.