메뉴 컨트리뷰션을 이용하여 커맨드를 기여 한 경우, CommandContributionItem이 메뉴 매니저나, 툴바 매니저등에 포함되어 해당 커맨드를 기여하게 됩니다. 이 때, 스타일이 SWT.DROP_DOWN 인 경우, 이 기여의 ID가 메뉴 아이디로 사용될 수 있게 됩니다.
문제는 이 주소를 통해 기여한 커맨드 역시, CommandContributionItem을 통해 기여 되는 데, 이들은 영영 dispose 되지 않는 다는 점입니다. 이 문제는 CommandContributionItem#openDropDownMenu() 를 보면 더 확실해 집니다.
/** * Determines if the selection was on the dropdown affordance and, if so, * opens the drop down menu (populated using the same id as this item... * * @param event * TheSWT.Selection
event to be tested * * @returntrue
iff a drop down menu was opened */ private boolean openDropDownMenu(Event event) { Widget item = event.widget; if (item != null) { int style = item.getStyle(); if ((style & SWT.DROP_DOWN) != 0) { if (event.detail == 4) { // on drop-down button ToolItem ti = (ToolItem) item; final MenuManager menuManager = new MenuManager(); Menu menu = menuManager.createContextMenu(ti.getParent()); if (workbenchHelpSystem != null) { workbenchHelpSystem.setHelp(menu, helpContextId); } menuManager.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { String id = getId(); if (dropDownMenuOverride != null) { id = dropDownMenuOverride; } menuService.populateContributionManager( menuManager, "menu:" + id); //$NON-NLS-1$ } }); // position the menu below the drop down item Point point = ti.getParent().toDisplay( new Point(event.x, event.y)); menu.setLocation(point.x, point.y); // waiting for SWT // 0.42 menu.setVisible(true); return true; // we don't fire the action } } } return false; }
메뉴를 만들기 위해 임시로 메뉴매니저를 사용하고, 플랫폼에 메뉴 서비스를 통해 기여시키지만, 릴리즈 및 디스포즈가 없습니다. menuManager가 로컬 변수 이므로, 집단 고립되서 GC에 수집될 것 같지만, 실제로는 그렇지 않습니다. 왜냐하면, 메뉴서비스와 이미 연결되어 버렸기 때문이지요.
사소한 릭일 것 같지만, CommandContributionItem은 핸들러 서비스, 커맨드 서비스와 결합할 뿐만 아니라 상황에 따라서는, 에디터의 셀렉션, 에디터 등과 같은 매우 비싼 객체를 참조하고 있는 경우도 심심찮게 발생합니다.