View Javadoc

1   // KeepResidentPlugin.java, created Aug 14, 2004 1:20:44 AM by joewhaley
2   // Copyright (C) 2004 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the CPL; see LICENSE.txt for details.
4   package edu.stanford.suif.keepresident;
5   
6   import java.util.MissingResourceException;
7   import java.util.ResourceBundle;
8   import java.io.IOException;
9   import org.eclipse.core.runtime.IPluginDescriptor;
10  import org.eclipse.jface.dialogs.MessageDialog;
11  import org.eclipse.jface.preference.IPersistentPreferenceStore;
12  import org.eclipse.jface.preference.IPreferenceStore;
13  import org.eclipse.swt.widgets.Shell;
14  import org.eclipse.ui.IStartup;
15  import org.eclipse.ui.plugin.AbstractUIPlugin;
16  import org.osgi.framework.BundleContext;
17  import edu.stanford.suif.keepresident.preferences.KeepResidentPreferencePage;
18  
19  /***
20   * The main plugin class to be used in the desktop.
21   */
22  public class KeepResidentPlugin extends AbstractUIPlugin implements IStartup {
23      //The shared instance.
24      private static KeepResidentPlugin plugin;
25      //Resource bundle.
26      private ResourceBundle resourceBundle;
27  
28      KernelInterface i;
29      WindowsHeap heap;
30      int hardMinimum, hardMaximum;
31      int currentMinimum, currentMaximum;
32      int pageSize;
33      
34      public int getHardMinimum() {
35          return hardMinimum;
36      }
37      public int getHardMaximum() {
38          return hardMaximum;
39      }
40      public int getLockedBytes() {
41          return heap.getLockedBytes();
42      }
43  
44      private void initialize() {
45          i = new KernelInterface();
46          heap = new WindowsHeap(i);
47          int[] sSysInfo = new int[256];
48          int pSysInfo = KernelInterface.GetIntArrayElements(sSysInfo);
49          i.call("GetSystemInfo", pSysInfo);
50          KernelInterface.ReleaseIntArrayElements(sSysInfo, pSysInfo);
51          pageSize = sSysInfo[1];
52  
53          int pMemoryStatus = KernelInterface.GetIntArrayElements(sSysInfo);
54          i.call("GlobalMemoryStatus", pMemoryStatus);
55          KernelInterface.ReleaseIntArrayElements(sSysInfo, pMemoryStatus);
56          int totalPhysical = sSysInfo[2];
57          if (totalPhysical < 0) totalPhysical = Integer.MAX_VALUE;
58          
59          hardMinimum = 20 * pageSize;
60          hardMaximum = totalPhysical - 512 * pageSize;
61          
62          //System.out.println("Page size="+pageSize+", total physical="+totalPhysical);
63          //System.out.println("Minimum="+hardMinimum+", maximum="+hardMaximum);
64          
65      }
66      
67      private void setDefaults() {
68          IPreferenceStore store = getPreferenceStore();
69          // cannot use defaults due to eclipse stupidity!
70          // this doesn't seem to work when called from earlyStartup().
71          // any value which is the same as default is not saved in the preference store.
72          store.setDefault(KeepResidentPreferencePage.P_MIN, 100000000);
73          store.setDefault(KeepResidentPreferencePage.P_MAX, 500000000);
74          store.setDefault(KeepResidentPreferencePage.P_LOCK, true);
75      }
76      
77      /***
78       * The constructor.
79       */
80      //public KeepResidentPlugin() {
81      public KeepResidentPlugin(IPluginDescriptor d) {
82          //super();
83          super(d);
84          plugin = this;
85          try {
86              resourceBundle = ResourceBundle
87                  .getBundle("edu.stanford.suif.keepresident.KeepResidentPluginResources");
88          } catch (MissingResourceException x) {
89              resourceBundle = null;
90          }
91          try {
92              initialize();
93          } catch (KernelException x) {
94              MessageDialog.openInformation(new Shell(),
95                  "KeepResident Plug-in", x.getMessage());
96          }
97      }
98  
99      public void updateProcessWorkingSetSize() {
100         int proc = i.call("GetCurrentProcess");
101         int[] a = new int[1];
102         int[] b = new int[1];
103         int pa = KernelInterface.GetIntArrayElements(a);
104         int pb = KernelInterface.GetIntArrayElements(b);
105         i.call_nz("GetProcessWorkingSetSize", proc, pa, pb);
106         KernelInterface.ReleaseIntArrayElements(b, pb);
107         KernelInterface.ReleaseIntArrayElements(a, pa);
108         currentMinimum = a[0];
109         currentMaximum = b[0];
110         //System.out.println("Process working set size: "+currentMinimum+", "+currentMaximum);
111         IPreferenceStore store = getPreferenceStore();
112         store.setValue(KeepResidentPreferencePage.P_MIN, currentMinimum);
113         store.setValue(KeepResidentPreferencePage.P_MAX, currentMaximum);
114     }
115     
116     public int TECHNIQUE = 2;
117     
118     public void setProcessWorkingSetSize(int min, int max, boolean useVirtualLock) {
119         int proc = i.call("GetCurrentProcess");
120         
121         // First, release all locks on memory so that it is possible to shrink
122         // working set size.
123         heap.releaseAllLocks();
124         
125         // Set the process working set size.
126         System.out.println("Setting process working set size to "+min+", "+max);
127         i.call_nz("SetProcessWorkingSetSize", proc, min, max);
128         
129         if (useVirtualLock) {
130             {
131                 // Use of VirtualLock is potentially unstable, so temporarily disable the
132                 // preference setting so if it *does* crash, we won't try it again.
133                 IPreferenceStore store = getPreferenceStore();
134                 store.setValue(KeepResidentPreferencePage.P_LOCK, false);
135                 try {
136                     ((IPersistentPreferenceStore) store).save();
137                 } catch (IOException x) {
138                 }
139             }
140             
141             int lockedBytes;
142             // lockAllVM seems to work much better than lockAllHeaps,
143             // and lockAllMemory seems to sometimes be unstable on some systems.
144             switch (TECHNIQUE) {
145             case 1:
146                 lockedBytes = heap.lockAllHeaps(pageSize);
147                 break;
148             case 2:
149                 lockedBytes = heap.lockAllVM();
150                 break;
151             case 3:
152                 int minAddr = WindowsHeap.SystemInfo[WindowsHeap.lpMinimumApplicationAddress];
153                 int maxAddr = WindowsHeap.SystemInfo[WindowsHeap.lpMaximumApplicationAddress];
154                 lockedBytes = heap.lockAllMemory(minAddr, maxAddr, pageSize);
155                 break;
156             default:
157                 throw new IllegalArgumentException("Unknown technique "+TECHNIQUE);
158             }
159             System.out.println(lockedBytes+" bytes locked.");
160             
161             {
162                 // Locking was successful: re-enable the flag.
163                 IPreferenceStore store = getPreferenceStore();
164                 store.setValue(KeepResidentPreferencePage.P_LOCK, true);
165                 // Now if Eclipse exits normally, it will automatically
166                 // save the flag in the preferences.
167             }
168         }
169         updateProcessWorkingSetSize();
170     }
171     
172     /***
173      * Update.
174      */
175     public void update() {
176         IPreferenceStore store = getPreferenceStore();
177         int min = store.getInt(KeepResidentPreferencePage.P_MIN);
178         int max = store.getInt(KeepResidentPreferencePage.P_MAX);
179         boolean b = store.getBoolean(KeepResidentPreferencePage.P_LOCK);
180         if (min != 0 && max != 0) {
181             min = Math.max(min, hardMinimum);
182             max = Math.min(max, hardMaximum);
183             min = Math.min(min, max);
184             setProcessWorkingSetSize(min, max, b);
185         }
186     }
187     
188     /***
189      * This method is called upon plug-in activation
190      */
191     public void start(BundleContext context) throws Exception {
192         super.start(context);
193     }
194 
195     /***
196      * This method is called when the plug-in is stopped
197      */
198     public void stop(BundleContext context) throws Exception {
199         super.stop(context);
200     }
201 
202     /***
203      * Returns the shared instance.
204      */
205     public static KeepResidentPlugin getDefault() {
206         return plugin;
207     }
208 
209     /***
210      * Returns the string from the plugin's resource bundle, or 'key' if not
211      * found.
212      */
213     public static String getResourceString(String key) {
214         ResourceBundle bundle = KeepResidentPlugin.getDefault()
215             .getResourceBundle();
216         try {
217             return (bundle != null) ? bundle.getString(key) : key;
218         } catch (MissingResourceException e) {
219             return key;
220         }
221     }
222 
223     /***
224      * Returns the plugin's resource bundle,
225      */
226     public ResourceBundle getResourceBundle() {
227         return resourceBundle;
228     }
229     
230     /* (non-Javadoc)
231      * @see org.eclipse.ui.IStartup#earlyStartup()
232      */
233     public void earlyStartup() {
234         try {
235             update();
236         } catch (KernelException x) {
237             MessageDialog.openInformation(new Shell(),
238                 "KeepResident Plug-in", x.getMessage());
239         }
240     }
241     
242 }