NetBeans 平台重新打开关闭的项目 StackOverflowError
NetBeans Platform Re-Open Closed Project StackOverflowError
我正在编写一个基于 NetBeans 平台 (7.4) 的应用程序,并且我已经创建了一个自定义的 ProjecType 和 FileType。 ProjectType 有一个弱文件更改侦听器,用于侦听项目文件夹中放置的新文件。问题是,如果我打开一个项目,关闭它然后再次尝试重新打开它,它会耗尽内存并抛出 Mutex 异常:
Blockquote java.lang.IllegalStateException: Should not acquire Children.MUTEX while holding ProjectManager.mutex
或 IllegalStateException:
Blockquote java.lang.IllegalStateException: at org.openide.nodes.Node.assignTo(Node.java:354)
at org.openide.nodes.EntrySupportDefault.justComputeNodes(EntrySupportDefault.java:212)
at org.openide.nodes.ChildrenArray.nodes(ChildrenArray.java:88)
at org.openide.nodes.EntrySupportDefault.getNodes(EntrySupportDefault.java:130)
at org.openide.nodes.EntrySupportDefault.getNodes(EntrySupportDefault.java:172)
at org.openide.nodes.Children.getNodes(Children.java:469)
另一个有趣的事情是,如果我关闭项目并对项目文件夹进行任何小的更改,例如将其移动到新位置,或者甚至只是打开该文件夹中的文件,当我尝试重新加载它时工作正常。
我已经尝试完全删除弱文件侦听器但没有成功。而且我知道这不是文件更改侦听器问题,因为 Windows 不会阻止我操作项目文件夹中的文件。下面是我的 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()
};
}
...............
}
}
经过大量谷歌搜索和调试后,我无法检测到为什么会发生这种内存泄漏,但我确实在下面 link 找到了解决方案,这可能对其他人有用 运行进入同一个问题。
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() 是不够的,但我假设当项目第一次关闭时,一些引用没有被释放,并且在重新打开时遇到问题。通过获取克隆,它创建了一个没有这些问题的全新父节点。我希望这对某人有所帮助,因为我很难找到解决方案。
我正在编写一个基于 NetBeans 平台 (7.4) 的应用程序,并且我已经创建了一个自定义的 ProjecType 和 FileType。 ProjectType 有一个弱文件更改侦听器,用于侦听项目文件夹中放置的新文件。问题是,如果我打开一个项目,关闭它然后再次尝试重新打开它,它会耗尽内存并抛出 Mutex 异常:
Blockquote java.lang.IllegalStateException: Should not acquire Children.MUTEX while holding ProjectManager.mutex
或 IllegalStateException:
Blockquote java.lang.IllegalStateException: at org.openide.nodes.Node.assignTo(Node.java:354) at org.openide.nodes.EntrySupportDefault.justComputeNodes(EntrySupportDefault.java:212) at org.openide.nodes.ChildrenArray.nodes(ChildrenArray.java:88) at org.openide.nodes.EntrySupportDefault.getNodes(EntrySupportDefault.java:130) at org.openide.nodes.EntrySupportDefault.getNodes(EntrySupportDefault.java:172) at org.openide.nodes.Children.getNodes(Children.java:469)
另一个有趣的事情是,如果我关闭项目并对项目文件夹进行任何小的更改,例如将其移动到新位置,或者甚至只是打开该文件夹中的文件,当我尝试重新加载它时工作正常。 我已经尝试完全删除弱文件侦听器但没有成功。而且我知道这不是文件更改侦听器问题,因为 Windows 不会阻止我操作项目文件夹中的文件。下面是我的 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()
};
}
...............
}
}
经过大量谷歌搜索和调试后,我无法检测到为什么会发生这种内存泄漏,但我确实在下面 link 找到了解决方案,这可能对其他人有用 运行进入同一个问题。 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() 是不够的,但我假设当项目第一次关闭时,一些引用没有被释放,并且在重新打开时遇到问题。通过获取克隆,它创建了一个没有这些问题的全新父节点。我希望这对某人有所帮助,因为我很难找到解决方案。