javaruntimes/midp/runtime/javasrc/com/nokia/mj/impl/rt/midp/MemoryLogger.java
branchRCL_3
changeset 19 04becd199f91
child 23 98ccebc37403
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javaruntimes/midp/runtime/javasrc/com/nokia/mj/impl/rt/midp/MemoryLogger.java	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,193 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+package com.nokia.mj.impl.rt.midp;
+
+import java.io.OutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import com.nokia.mj.impl.fileutils.FileUtility;
+import com.nokia.mj.impl.rt.support.JvmInternal;
+
+/**
+ * A class for storing the heap usage to a file after fixed time period.
+ *
+ * @author Nokia Corporation
+ * @version $Rev$
+ */
+public class MemoryLogger extends Thread
+{
+    /**
+     * Singleton instance of the MemoryLogger.
+     */
+    private static MemoryLogger     sInstance;
+
+    // Keep the deafult values in sync with native side.
+    private static final int        DEFAULT_OLD_SPACE = 64 * 1024;
+    private static final int        DEFAULT_NEW_SPACE = 64 * 1024;
+    private static final String     FILE_NAME = "heap";
+    private static final int        MAX_OLD_SPACE = 1 * 1024 * 1024;
+
+    /**
+     * Used to stop montoring if the MIDlet is closed before the fixed timer
+     * has elapsed.
+     */
+    private        boolean          mForcedStop = false;
+
+    /*** ----------------------------- PRIVATE ---------------------------- */
+
+    /**
+     * Constructor of the MemoryLogger.
+     */
+    private MemoryLogger()
+    {
+    }
+
+    /*** ----------------------------- PACKAGE ---------------------------- */
+
+    /**
+     * Starts the heap monitoring by creating a dedicated thread.
+     */
+    static void startMonitoring()
+    {
+        if (sInstance == null)
+        {
+            if (Log.mOn) Log.logI("Memory monitor start request");
+            sInstance = new MemoryLogger();
+            sInstance.start();
+        }
+
+    }
+
+    /**
+     * Closes the heap monitoring. If the timer has already elapsed this
+     * method does nothing. If the not then the monitoring is interrupted.
+     */
+    static void close()
+    {
+
+        if (Log.mOn) Log.logI("Memory monitor close request");
+        if (sInstance != null)
+        {
+            if (Log.mOn) Log.logI("  interrupting thread");
+            sInstance.mForcedStop = true;
+            sInstance.interrupt();
+        }
+    }
+
+    /**
+     * Gets the amount of bytes how much the old space heap should be expanded.
+     */
+    static int getOldHeapSizeToExpand()
+    {
+        int currentTotalMemory = (int)Runtime.getRuntime().totalMemory();
+        int currentOldSpaceSize = currentTotalMemory - DEFAULT_NEW_SPACE;
+        int oldSpaceFromPreviousRun = getRecordedHeapSize();
+
+        int expandSize = 0;
+        if (oldSpaceFromPreviousRun > DEFAULT_OLD_SPACE)
+        {
+            // Expanding it to recorded value.
+            expandSize = oldSpaceFromPreviousRun - currentOldSpaceSize;
+        }
+        else
+        {
+            // Expanding it back to default value.
+            expandSize = DEFAULT_OLD_SPACE - currentOldSpaceSize;
+        }
+
+        int highLimit = MAX_OLD_SPACE - currentOldSpaceSize;
+
+        if (expandSize < 0)
+        {
+            expandSize = 0;
+        }
+        if (expandSize > highLimit)
+        {
+            expandSize = highLimit;
+        }
+        if (Log.mOn) Log.logI("getOldHeapSizeToExpand: " + expandSize);
+        return expandSize;
+    }
+
+    /**
+     * Reads the recorded heap size from possible previous runs. The heap size
+     * is read from the 'heap' file located in the root path of the MIDlet.
+     * @return heap size in bytes if available, 0 if not available.
+     */
+    static int getRecordedHeapSize()
+    {
+        // Construct the file name.
+        String heapFile = ApplicationInfoImpl.getMidletInfo().getRootPath();
+        heapFile += FILE_NAME;
+
+        int heap = _readFile(heapFile);
+        return heap;
+    }
+
+
+    /*** ----------------------------- PUBLIC ------------------------------ */
+
+    /**
+     * The thread will wait for fixed time and after elapsing will write the
+     * heap usage into the file. If the monitoring is interrupted, then the
+     * heap result will not be stored into the file.
+     */
+    public void run()
+    {
+        try
+        {
+            sleep(60000);
+        }
+        catch (Throwable t)
+        {
+        }
+
+        if (mForcedStop)
+        {
+            if (Log.mOn) Log.logI("MIDlet closed, no memory monitoring");
+            // The MIDlet was closed before timer elapsed, so no monitoring.
+            sInstance = null;
+            return;
+        }
+
+        try
+        {
+            Runtime rt = Runtime.getRuntime();
+            long freeMem = rt.freeMemory();
+            long totMem = rt.totalMemory();
+            int usedHeap = (int)(totMem-freeMem);
+
+            int heapSizeToStore = usedHeap - DEFAULT_NEW_SPACE;
+
+            if (Log.mOn) Log.logI("HeapSizeToStore: " + heapSizeToStore);
+
+            _writeFile(ApplicationInfoImpl.getMidletInfo().getRootPath()
+                       + FILE_NAME, heapSizeToStore);
+        }
+        catch (Throwable th)
+        {
+            Log.logE("Error in MemoryLogger: ", th);
+        }
+        sInstance = null;
+    }
+
+    private native void _writeFile(String file, int heapSize);
+    private static native int _readFile(String file);
+}