Minimizing other objects in the packaged image
Here are some other ways to reduce the size of your packaged image.
Finding and removing hidden data
In general, objects that are generated by your application are discarded when they are dereferenced. If you store objects in global or class variables, however, these objects persist in your image until you take some action to remove them (for example, by removing a global variable or setting a class variable to nil). When a packaged image is created, such objects are packaged as is, unless otherwise specified. By default, whatever objects a variable contains in the development environment, it will contain in the packaged image.
Globals and class variables are frequently used in applications to store, for example, test data, or, perhaps, data retrieved from a host system. This data can take up considerable amount of space. The problem you face is trying to find such references. The packager can help you find data "hidden" in global and class variables.
To look for global variables containing hidden data, search the Global Variables in the Image Contents Browser during packaging.
To look for class or class instance variables that contain hidden data, do the following:
1. Perform all the steps to produce a packaged image.
2. Look in the CLASSVAR.ES statistics file located in the default directory. This file contains a list of classes that have been included in the packaged image, along with their class and class instance variables. For each variable, the file shows the packaging rule if one exists, or the class of the object that is contained in the variable.
3. If the variable contains an instance of a collection class, the file also shows the number of elements in the collection.
Discarding unnecessary components from base Smalltalk classes
For objects contained in the base Smalltalk classes, there is certain data that can be eliminated under some conditions:
• If there is no requirement to determine the subclass of a class, then the subclasses instance variable of Behavior can be excluded. However, some portions of the class hierarchy need subclasses to be present. Therefore, you should exclude subclasses in Behavior then include it in classes below Behavior in the hierarchy where it is needed.
Specifically, in the Windows environment, OSWidget and its subclasses require that subclasses be available. Also, PlatformFunction and its subclasses require that subclasses be available on all platforms. So, you can exclude the subclasses instance variable in Behavior and then include subclasses at the OSWidget and PlatformFunction level. The include rule is inherited by subclasses of OSWidget and PlatformFunction. You can perform a similar operation for your application classes that require the subclasses instance variable.
Remember that subclasses is an instance variable of Behavior, but becomes a class instance variable in OSWidget and PlatformFunction because of the inheritance hierarchy. You should exclude the variable on the instance side of Behavior, then include it on the class side of OSWidget and PlatformFunction.
• If the instance variable names of a class are not used (and the compiler is removed), then the instVarNames instance variable of ClassDescription can be excluded.
The variable instVarNames is an instance variable of ClassDescription, which is inherited by metaclasses (that is, the class side of a Smalltalk class), so you exclude it on the instance side of ClassDescription but then include it on the class side of the portion of the hierarchy that requires it.
The variable instVarNames may be required by the Swapper for those classes that are being loaded from files. It is required only when classes being loaded are derived from a class version that is different from the version in the current image.
Items removed by default
• The classPool instance variable of Class is used only by the compiler or if your application accesses class variables indirectly, like this:
• aClass classPool at:
If you use this kind of code, you should delete the rule associated with the variable.
• The sharedPoolNames instance variable of Class is used only when compiling, unless it is accessed directly as in:
• aClass sharedPoolNames at:
Your applications should not require this information at runtime, but, if they do, you can delete the rule associated with the variable.
• The transcriptMenus and removedMenus instance variables of EmSystemConfiguration are excluded because the Transcript is removed for runtime.
• If library management information is not required in the packaged image, the description instance variable of ClassDescription can be excluded. This information is only needed if your application does something like sending controller to a class, or sending application to a CompiledMethod. Typically, there is no need to send these messages at run time, but if your applications need to send them, you should delete the rule associated with the variable.
Avoiding unnecessary references to pool dictionaries
Pool dictionaries can normally be excluded from a packaged image. When a pool variable is referenced directly by a method, that method, when packaged, will contain the pool variable regardless of whether the pool dictionary was packaged also.
If a pool dictionary is excluded from the packaged image, only those pool variables that are referenced are included in the packaged image. If a pool dictionary is included, then every variable in the dictionary will be included in the packaged image.
Some pool dictionaries, such as CwConstants, contain thousands of items. You normally use only a small portion of them. A single reference to one of these dictionaries can increase the size of the packaged image by several hundred kilobytes.
If you make no references to a pool dictionary, the packager, by default, omits the dictionary in the packaged image.
Therefore, instead of using code like this:
line := aStream upTo: (CldtConstants at: 'Cr').
You should use the following:
line := aStream upTo: Cr.
The compiled method contains the pool variable Cr, so it will be included in the packaged image.
In some cases, you cannot avoid making direct references to a pool dictionary. For example, you might be using a pool dictionary for externalized strings, which you read from a file. In this situation, you can tell the packager to reduce the pool dictionary from the Image Contents Browser. The packager will ensure that only those pool variables that are referenced in methods in the packaged image are included in the pool dictionary in the packaged image.