| <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
| <meta name="Author" content="Carolyn MacLeod"> |
| <link rel="stylesheet" href="../default_style.css"> |
| <title>Managing Operating System Resources</title> |
| </head> |
| <body> |
| <div align=right><font face="Times New Roman, Times, serif"><font size=-1>Copyright |
| © 2001 Object Technology International, Inc.</font></font></div> |
| <table BORDER=0 CELLSPACING=0 CELLPADDING=2 WIDTH="100%" > |
| <tr> |
| <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica"><font color="#FFFFFF"> Eclipse |
| Corner Article</font></font></b></td> |
| </tr> |
| </table> |
| |
| <h1> |
| <img SRC="Idea.jpg" height=86 width=120 align=CENTER></h1> |
| |
| <center> |
| <h1> |
| SWT: The Standard Widget Toolkit</h1></center> |
| |
| <center> |
| <h3> |
| PART 2: Managing Operating System Resources</h3></center> |
| |
| <center><i>The second in a series of articles about the design ideas behind |
| SWT.</i></center> |
| |
| <blockquote><b>Summary</b> |
| <br>SWT uses operating system resources to deliver its native graphics and widget |
| functionality. Allocating |
| and freeing operating system resources is traditionally an area of programming |
| that is error prone. Languages that include garbage collection, such as the |
| Java™ language, relieve the programmer from the burden of managing memory, but not |
| from the allocation and freeing of operating system resources. This article discusses the simple strategy used by |
| SWT to help application designers manage operating system resources. |
| <p><b>By Carolyn MacLeod and Steve Northover, OTI</b><br> |
| <span style="font-size: 10pt; mso-bookmark: _Toc496069418">November 27, 2001</span></p> |
| </blockquote> |
| <p> |
| <hr WIDTH="100%"> |
| <h3> |
| Simple rules to help get it right!</h3> |
| <p>When programming in a GUI operating system, you allocate operating system |
| resources for widgets, images, fonts, and other graphical objects. Since |
| there is a platform limit on the amount of resources you can allocate, you must |
| be careful to free any objects that you allocate in your application. If you |
| allocate a resource and do not free it when you are done with it, your application is "leaking" |
| resources. An application that repeatedly leaks resources will |
| eventually consume all of the available resources, forcing the user to reboot |
| the operating system.</p> |
| <p>Fortunately, SWT makes resource allocation and disposal a straightforward |
| process. There are only two rules that you need to remember when allocating and |
| freeing SWT resource-based objects:</p> |
| <p align="center" style="border-style: solid"><b>Rule 1: </b><i>If you created it, you dispose it</i>.<p>This is |
| a simple rule. SWT makes it easy for you to remember when |
| operating system resources are allocated: <i>all</i> SWT resource-based objects (like <i>Color</i>, |
| <i>Cursor</i>, |
| <i>Display</i>, |
| <i>Font</i>, |
| <i>GC</i>, |
| <i>Image</i>, |
| <i>Printer</i>, |
| <i>Region</i>, |
| <i>Widget |
| and subclasses</i>) allocate any needed operating system resources in their constructor. |
| There are no exceptions to this rule. There are no methods in SWT (other |
| than constructors) that allocate operating system resources that the programmer |
| must manage. If |
| you didn't call the constructor, then you don't need to free the resources, |
| so don't call dispose on the object. For example, in the following |
| line of code, an operating system font is allocated: |
| <p> <font size=-1>Font font = new Font |
| (display, "Courier", |
| 10, SWT.NORMAL);</font> |
| <p>Since you called the <i>Font</i> constructor to create the resource, |
| you must dispose the font when |
| you are finished with it, as follows: |
| <p> <font size=-1>font.dispose();</font> |
| <p>In the following line of code, however, a constructor is not called: |
| <p> <font size=-1>Font font = control.getFont |
| ();</font> |
| <p>Therefore, you must not call dispose. The <b>font</b> variable does contain |
| an operating system font resource, but you did not allocate it. If you |
| were to dispose of this font, you would be leaving the <b>control</b> without |
| a font! The results are undefined. So, if you are using <i>any</i> |
| getter that returns an SWT resource-based object that you did not allocate, do not dispose the object. |
| <p>This rule occasionally leads to API that seems artificial. For |
| example, <b>GC.getClipping (Region)</b> forces the programmer to create |
| a <i>Region</i> in order to get the clipping region from a <i>GC</i>. Although it |
| might have been a bit "prettier" to provide GC.getClipping () that |
| returned a <i>Region</i>, this would break the rule because it would have to allocate an operating system |
| resource outside of a constructor. |
| While it could be documented that the programmer needs to free the <i>Region</i> |
| returned by GC.getClipping (), programmers don't always read the documentation. |
| Making the programmer call the constructor for the <i>Region</i> makes |
| it clear that it is the <i><u>programmer's</u></i> responsibility to free |
| the resource. |
| <p align="center" style="border-style: solid"><b>Rule 2: </b><i>Disposing the parent disposes the children.</i> |
| <p> |
| When you dispose a <i>Shell</i>, |
| its children are disposed. In fact, disposing any <i>Composite</i> |
| will dispose all of the <i>Composite</i>'s children. Disposing a |
| <i>Menu</i> |
| disposes all menu items. Disposing a <i>Tree</i> or |
| <i>TreeItem</i> |
| disposes all child items. |
| <p>Why does this make sense? Apart from the obvious burden of having |
| to dispose each child if this were not the case, the fact that a widget |
| cannot exist in the operating system without a parent implies that when |
| the parent is disposed, the child <i>must</i> also be disposed. |
| <p>What about the fonts and colors that you created and set into a |
| <i>Widget</i>? |
| Since they are not children of the widget, they are not disposed |
| when the parent is disposed. A widget will never dispose |
| a resource that you allocated. To do so would mean that the widget was |
| breaking rule 1. Because fonts |
| and colors can be shared by different widgets, disposing a resource in one |
| widget would dispose it in another, leading to unpredictable results. |
| <h4>Extensions to Rule 2</h4> |
| <p>There are two extensions to rule 2. These are places where a relationship |
| exists that is not strictly a parent-child relationship, but where it still |
| makes sense for rule 2 to apply. |
| <p><b> MenuItem.setMenu: </b>Disposing a cascade <i>MenuItem</i> |
| that has a submenu set with <b>setMenu (Menu)</b> disposes the submenu. This is a natural extension of rule 2. It would be a burden |
| to the programmer to dispose each individual submenu. It's also common behavior in most operating systems to do this automatically. |
| Both Windows® and X dispose submenus when a cascade menu item is |
| disposed.<p><b> Control.setMenu: </b>Disposing a <i>Control</i> |
| that has a pop-up menu set with <b>setMenu (Menu)</b> disposes the pop-up |
| menu. Many application programmers expected this behavior, even though many operating systems don't |
| do this automatically. Leaving the |
| application programmer responsible for disposing a pop-up menu when disposing the |
| <i>Control</i> |
| led to temporary leaks. (The leak was only temporary because the pop-up menu is eventually disposed when |
| the shell is disposed). |
| <h3> |
| Why free at all?</h3> |
| The operating system frees all of a program's resources when the program |
| exits. Why not just rely on this? Operating system resources are |
| not infinite. If your program doesn't free up resources as they are no |
| longer needed, it can run out of resources. It can also cause other programs |
| to run out of resources. So waiting until the program exits to free up resources |
| is generally a bad idea. Leak tools exist to help detect resource leaks. |
| You can use the <i><a href="sleak.htm">Sleak</a></i> tool to look for leaks in your SWT application. |
| <h3> |
| The Java language has Garbage Collection - Why not use it?</h3> |
| The Java language successfully uses a garbage collector to manage the memory used by |
| Java objects. Why doesn't SWT use the Java garbage collector to manage |
| operating system resources too? Many Java programmers ask this question. We will answer it with the following discussion on finalization.<h4><b>Finalization</b></h4> |
| <p>Most attempts to use the Java garbage collector to |
| manage operating system resources involve finalization. When an object |
| is about to become garbage, the garbage collector sends it the finalize message. This seems |
| like a logical place to free the resource, right?<p>Conventional wisdom says that managing operating system |
| resources in finalization is difficult and error prone. To quote Joshua |
| Bloch in his "Java Series" book <i>Effective Java</i>, |
| <blockquote> |
| <p><i>"Finalizers are |
| unpredictable, often dangerous, and generally unnecessary. Their use can |
| cause erratic behavior, poor performance, and portability problems."</i> |
| [JB, 2.6]. |
| </blockquote> |
| <p>One of |
| the main reasons that this statement is true is that there is no guarantee how |
| soon after an object becomes garbage that the finalize method for the object will run. Even if you could predict |
| this time interval for a particular VM, you |
| certainly couldn't guarantee it for new versions of the VM. Worse still, if there |
| is plenty of memory or if an exception occurs in an object's finalize method, there is no |
| guarantee that the object will be finalized at all! All of this is stated right in <i>The Java |
| Language Specification</i>: |
| <blockquote> |
| <p><i>"<span style="mso-fareast-font-family: Times New Roman; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">The |
| Java programming language does not specify how soon a finalizer will be |
| invoked, except to say that it will happen before the storage for the object |
| is reused. ... If an uncaught exception is thrown during the finalization, the |
| exception is ignored and finalization of that object terminates.</span>"</i> |
| <span style="mso-fareast-font-family: Times New Roman; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">[JLS, |
| 12.6]</span>. |
| </blockquote> |
| <p>Releasing operating system resources is |
| critical to correct program execution. Freeing resources at some unknown time in the future (or not at all) typically leads to program |
| failure. Here are some examples of typical problems encountered when using |
| finalization: |
| <ul> |
| <li> |
| If a non-garbage object references another object, that object is not garbage |
| and won't be collected. If the object has operating system resources that it |
| frees in its finalize method, those resources will never be freed because finalize |
| will never be called. This is a classic programming error because it's easy to hang on to objects |
| accidentally in an inner class or a static variable.<br> |
| </li> |
| |
| <li> |
| It is possible to starve other operating system processes by creating lots |
| of "garbage resources" that have not yet been finalized. When another |
| program attempts to acquire a resource, it fails because it cannot run |
| the Java finalizer. SWT could run the finalizer if it couldn't get a resource, but |
| other programs (i.e. non-Java programs or even Java programs running in a |
| different VM) - and operating system calls that allocate |
| and free resources internally - can't run the Java finalizer.<br> |
| </li> |
| |
| <li> |
| Some resources are very limited. For example, only a small number |
| of cached HDCs are available on Windows 98. It is essential to free |
| these up right away, instead of waiting for finalization.<br> |
| </li> |
| |
| <li> |
| Different types of resource are shared on the same operating system heap, so a |
| failure to acquire one resource may be caused by failure to free another. |
| For example, on Windows 98, HBRUSH and HFONT are both allocated from the |
| GDI heap, so failure to create an HBRUSH can happen if too many HFONTs are |
| awaiting finalization. This can cause applications to have some strange |
| dependencies on the timing of finalizer runs.</li> |
| |
| </ul> |
| <p class="MsoNormal">The non-deterministic nature of finalization is sufficient reason to avoid using |
| it to free |
| resources, but even if we decided to go against conventional wisdom and implement a resource management scheme using finalization, we |
| would still face many other problems. The implementation would require the addition of some very |
| complex, platform-specific code that would be difficult to get right, and tough |
| to debug. Here are a |
| few examples of some of the tricky issues that would need to be carefully coded |
| around in each object's finalize method:</p> |
| <ul> |
| <li> |
| <p class="MsoNormal">Operating system objects can have subtle limitations on when particular objects can be |
| disposed. For example in the X Window System, a GC can contain a Font. If you |
| dispose the Font before the GC, you leave the operating system in an |
| indeterminate state. The following quote from <i>The Java Language |
| Specification</i> hints at the complexity of the code that would be required |
| to handle such limitations for each object finalizer:</li> |
| </ul> |
| <blockquote> |
| <blockquote> |
| <p class="MsoNormal"><i>"The Java programming language imposes no |
| ordering on finalize method calls. Finalizers may be called in any order, or |
| even concurrently."</i><span style="mso-spacerun: yes"> </span>[JLS |
| 12.6.2]</p> |
| </blockquote> |
| <p class="MsoNormal">Add to this that for some operating systems, subtle |
| platform behavior in this area may be undocumented and can change in future |
| versions of the operating system.</p> |
| </blockquote> |
| <ul> |
| <li> |
| <p class="MsoNormal">On some platforms, operating system resources need to be disposed |
| in the UI thread. According to <i>The Java Language Specification</i>:</li> |
| </ul> |
| <blockquote> |
| <blockquote> |
| <p class="MsoNormal"><i>"... the language does not specify which |
| thread will invoke the finalizer for any given object."</i> [JLS 12.6]</p> |
| </blockquote> |
| <p class="MsoNormal">This means that SWT finalize methods would need to |
| synchronize with the UI thread, which would mean that there would be a significant cost overhead for each |
| dispose. In addition, given the previous point that disposal order is |
| important for some resources, we think it is possible to get into a deadlock |
| situation if we are trying to reorder multiple concurrent threads that are |
| trying to synchronize with the UI thread.</p> |
| </blockquote> |
| <ul> |
| |
| <li> |
| The Java objects that model operating system objects need to capture all of the subtle |
| relationships between the operating system objects. For example, on Windows, an HBRUSH |
| can be referenced in the operating system by an HDC, but not referenced |
| in Java code. When the Java object representing the HBRUSH becomes garbage, |
| freeing it will cause unexpected results. In fact, it's necessary |
| to break the reference from the HDC first before attempting to free the HBRUSH. |
| If these relationships are not captured and managed, it is possible for a resource to be finalized when there are still references |
| to it in the operating system. <br> |
| </li> |
| |
| <li> |
| Freeing some resources automatically frees others. For example, on Windows, |
| destroying a parent HWND automatically destroys the children HWNDs. |
| On some operating systems, freeing a top level window also frees the icon |
| associated with the window. Different rules for freeing resources need to be custom coded |
| on a per platform basis. <br> |
| </li> |
| |
| <li> |
| Freeing resources can be time |
| consuming, so a critical memory allocation may need to wait until finalization |
| is complete.<br> |
| </li> |
| |
| <li> |
| Long waits in finalizers can also make it difficult to get good benchmarks when |
| you are trying to performance tune your code.</li> |
| |
| </ul> |
| <p>Our final point against finalization is this: SWT keeps as much state in the operating system as possible to simplify |
| the implementation (less code, smaller objects). If we were to use |
| finalization, we could not store resources only in the operating system. We would have |
| to hold on to them in Java code so that they would not get garbage collected. |
| For example, when you set a <i>Font</i> into a <i>Button</i>, SWT sets the font |
| resource in the OS button. The <i>Button</i> doesn't keep a reference |
| to the font resource, because it doesn't need to. The state is in |
| the operating system. In order to determine the <i>Button</i>'s font, we query the OS. There is |
| no point caching the font resource in Java code, because it just takes up space |
| and complicates the <i>Button</i> code, which now has to make sure there |
| are no stale cache problems.</p> |
| <p> |
| Given that there are many problems when trying to use finalization to free |
| resources, we think itÂ’s dangerous to offer it as a solution in SWT, which is |
| designed to expose operating system functionality. We believe it is reasonable to expect programs to explicitly free operating |
| system resources. We see this as simply a fact of life because the |
| current generation of operating systems do not support garbage collection. |
| <h3>When should you free?</h3> |
| <p class="MsoNormal">You have created an SWT resource, so when do you free it? |
| First of all, for many of the reasons mentioned above, we do not recommend that you use finalization to manage |
| your SWT resources either. If you feel you absolutely must implement a finalize |
| method in your classes, do |
| so only as a "safety net" or "backup", and dispose your resource as |
| usual. Remember to synchronize with the UI thread, as follows:</p> |
| <font size=-1><p style="margin-top: 0; margin-bottom: 0"> protected void finalize() {<span style="mso-spacerun: |
| yes"> </span>// NOT recommended |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>super.finalize();</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>display.asyncExec(new Runnable() {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>public void run() {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>if (!myResource.isDisposed()) {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>myResource.dispose();</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>}</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>}</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>});</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"> }</p> |
| </font> |
| <p class="MsoNormal">Even this minimal "safety net" use of finalizers is not recommended, because if memory is limited, |
| your application could end up having to wait for a bunch of your finalize |
| methods to run before the memory from those |
| objects can be |
| reclaimed.</p> |
| <p class="MsoNormal">The best way to manage SWT resources is to dispose them as |
| soon as you are through with them. In the case of certain resource types, such as |
| GC and Printer, you almost always create them and dispose them within the scope of |
| the same method.<span style="mso-spacerun: yes"> This makes it easy to |
| verify that the resource is being disposed properly, because you only have to go |
| to one place to see the code to create the resource and the code to dispose it. </span>For example:</p> |
| <font size=-1><p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>GC gc = new GC(canvas);</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| gc.draw... </span>// do some drawing on the canvas using the GC</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>gc.dispose();</p></font> |
| <p class="MsoNormal">In the case of resources that are set into a GC for |
| drawing, you need to be careful not to dispose them while they are still set |
| into the GC. Dispose the GC before the resource. For example:</p> |
| <font size=-1><p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span><font color="#000000">Font font </font> = new Font |
| (display, "Courier", |
| 10, SWT.NORMAL);</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"> <span style="mso-tab-count: 1"> |
| </span>GC gc = new GC(canvas);</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"> |
| gc.setFont(font);</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| gc.drawText... </span>// do some text drawing on the canvas using the GC</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>gc.dispose();</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"> |
| font.dispose();</p></font> |
| <p class="MsoNormal">Remember that you do not dispose the GC that is |
| passed to you in a paint listener, because you did not allocate it!</p> |
| <font size=-1><p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>public void paintControl(PaintEvent event) {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span> event.gc.draw...</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span> <span style="mso-tab-count: 1"> // do NOT call event.</span>gc.dispose();</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"> |
| }</p></font> |
| <p class="MsoNormal">If you are using graphics resources in a widget - for example, |
| widget.setFont(font) - it is often best to clean these up when the |
| widget they are used in is disposed, so you can hook a dispose listener on the |
| widget as follows:</p> |
| <font size=-1><p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>widget.addDisposeListener(new DisposeListener() {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>public void widgetDisposed(DisposeEvent e) {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>font.dispose();</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>}</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>}</p></font> |
| <p class="MsoNormal">If resources are shared by multiple widgets (or other |
| objects) in your application, then you may want to implement a |
| reference-counting scheme in a "resource manager" class, which would |
| keep track of the number of references to a resource, and dispose the resource |
| when the reference count reaches 0.<span style="mso-spacerun: yes"> </span>In |
| this case, you would ask your resource manager for each resource you need, |
| perhaps something like this:</p> |
| <font size=-1><p class="MsoNormal"><span style="mso-tab-count:1"> |
| </span>Image image = myResourceManager.getNamedResource("imageName");</p> |
| </font> |
| <p class="MsoNormal">and the dispose listener on your widget(s) might look |
| something like this:</p> |
| <font size=-1> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>widget.addDisposeListener(new DisposeListener() {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>public void widgetDisposed(DisposeEvent e) {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>myResourceManager.dispose(image);</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>}</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>});</p></font> |
| <p class="MsoNormal">Whether or not to use a reference-counting scheme, and how |
| to implement it, are design decisions that must be made on a per-application |
| basis.</p> |
| <p class="MsoNormal">Widgets themselves do not usually need to be disposed |
| programmatically. A shell and its children are disposed when the user closes its |
| window. There are a couple of places where shells are typically disposed programmatically: when the user |
| selects File->Exit in an application window, or OK in a dialog. Here is an |
| example of disposing a shell when File->Exit is selected:</p> |
| <font size=-1> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| // Create menu bar |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count: 1"> |
| </span><span style="mso-tab-count:1">Menu menuBar = new Menu(shell, SWT.BAR); |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| // Create File menu |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| MenuItem item = new MenuItem(menuBar, SWT.CASCADE); |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| item.setText("File"); |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| Menu fileMenu = new Menu(shell, SWT.DROP_DOWN); |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| item.setMenu(fileMenu); |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| // Create File -> Exit menu item and add selection listener |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| item = new MenuItem(fileMenu, SWT.NULL); |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| item.setText("Exit"); |
| </span></p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count: 1"> |
| </span>item.addSelectionListener(new SelectionAdapter() {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>public void widgetSelected(SelectionEvent event) {</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>shell.close(); // calls dispose() - see note below</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>}</p> |
| <p class="MsoNormal" style="margin-top: 0; margin-bottom: 0"><span style="mso-tab-count:1"> |
| </span>});</p></font> |
| <p class="MsoNormal">Note that we actually call <b>close()</b> instead of <b>dispose()</b>. |
| This gives the application a chance to cancel the close operation if necessary |
| (for example, if something was not saved) inside of a shell listener. We could |
| call <b>dispose()</b>, which would simply destroy the shell without invoking the |
| shell listener, but it's better style to call <b>close()</b>.</p> |
| <h3> |
| A note about Color</h3> |
| <i>Color</i> is just like any other SWT resource-based object. To ensure |
| that your application works on all platforms for all display types, always |
| follow rule 1. If you are using a high-color (direct palette) display and you forget to follow |
| the rules for disposing <i>Color</i>, you may notice that nothing bad happens. |
| But if the rules for disposing <i>Color</i> |
| are not followed on a low-color (indexed palette) display, real problems can occur. You |
| should always program your application with the assumption that some of |
| your customers will be using low-color displays. For more information, |
| see the <i>SWT Color Model</i> article. |
| <h3> |
| Conclusion</h3> |
| When you use SWT, you will probably need to manage operating system resources |
| allocated by SWT objects. Resource management |
| takes thought to get right. Getting into good habits and following the rules |
| reduces the programming effort significantly. Simple rules help make |
| it clear who has responsibility for disposing resources: |
| <ul> |
| <li> |
| <i>If you created it, you dispose it</i> (<i>if you didn't create it, don't dispose it)</i>.</li> |
| |
| <li> |
| <i>Disposing the parent disposes the children.</i></li> |
| </ul> |
| <h3>Further reading</h3> |
| <p>JFace provides a registry mechanism on top of SWT |
| for image and font resource management. See the article <i>Using Images |
| in the Eclipse UI</i> for more information on the JFace image management |
| facilities.</p> |
| <h3>References</h3> |
| <p>[JB] Bloch, Joshua. <i>Effective Java - Programming Language |
| Guide</i>. Addison-Wesley, Boston, 2001.<br> |
| ISBN: |
| 0-201-31005-8.</p> |
| <p>[JLS] Gosling James, Bill Joy, Guy Steele, Gilad Bracha. <i>The Java |
| Language Specification</i>, <i>Second Edition<br> |
| http://java.sun.com/docs/books/jls/second_edition/html/j.title.doc.html</i></p> |
| |
| <p><small>Java and all Java-based trademarks and logos are trademarks or registered |
| trademarks of Sun Microsystems, Inc. in the United States, other countries, or |
| both.</small></p> |
| <p><small>Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both.</small></p> |
| |
| </body> |
| </html> |