1 Reply Latest reply: May 19, 2009 1:11 AM by 843849 RSS

    Memory leak in NSIcom CreMe VM?

    843849
      Dear Forum,

      I have some trouble with the CreMe virtual machine (NSICom) so I will just give it a try to post here. As NSICom support just does not answer my questions anymore (seems that I am already on there ignore list), I hope one of you can give me a hint on what's going wrong here.

      The actual problem is a leaking of memory. After ages of reviewing my own code I figured out, that this is not my fault. Since it has something to do with threads, I wrote a simple test class:
      import java.awt.BorderLayout;
      import java.awt.*;
      import java.io.*;
      import java.net.*;
      import java.text.SimpleDateFormat;
      import java.util.*;
      
      import javax.swing.*;
      import javax.swing.*;
      
      public class MemoryTest extends JFrame implements Runnable, ActionListener
      {
          private final static short MODE_SSL = 1;
      
          private static final String AC_RUN_GC = "RUN_GC", AC_END = "END", AC_EXIT = "EXIT", AC_MEM_INFO = "MEM_INFO",
          AC_OBJECT_MAP = "OBJECT_MAP";
      
          private final short m_sMode;
          private int m_iCycles;
          private final Runnable runnable;
          private final Thread m_thCollector;
          private final LinkedList m_llThreads;
          private static URL testUrl;
      
          private JTextArea m_taLog;
      
          public MemoryTest(final short p_sMode, final int p_iCycles, final String p_strTestUrl)
          throws MalformedURLException
          {
              super("CreMe Memory tester");
      
      
              m_sMode = p_sMode;
              m_iCycles = p_iCycles;
              runnable = new Runnable()
              {
                  public void run()
                  {
                      for (int i = 0; i < 100; i++)
                      {
                          Math.random();
                          try
                          {
                              Thread.sleep(20);
                          }
                          catch (InterruptedException e)
                          {}
                      }
                  }
              };
              m_thCollector = new Thread()
              {
                  public void run()
                  {
                      //... collect fiished threads
                  }
              };
              m_llThreads = new LinkedList();
              testUrl = new URL(p_strTestUrl);
      
              initComponents();
          }
      
          public void run()
          {
              log("Starting test (MODE " + (m_sMode == MODE_SSL ? "SSL" : "THREAD") + " | CYCLES: " + m_iCycles + "...");
              long lLoopCount = 0;
              while (m_iCycles != 0)
              {
                  switch (m_sMode)
                  {
                      case MODE_SSL:
                          runSSLTest();
                          break;
                      default:
                          runThreadTest();
                      break;
      
                  }
                  if (lLoopCount++ % 1000 == 0)
                  {
                      actionPerformed(new ActionEvent(this, 0, AC_MEM_INFO));
                      actionPerformed(new ActionEvent(this, 0, AC_OBJECT_MAP));
                  }
                  synchronized (this)
                  {
                      if (m_iCycles > 0)
                      {
                          m_iCycles--;
                      }
                  }
              }
              log("Test finished!");
          }
      
          private void runThreadTest()
          {
              while (m_llThreads.size() > 100)
              {
                  sleep(100);
              }
      
              Thread t = new Thread(runnable);
              t.start();
              log("Started thread: " + t.getName());
              synchronized (m_llThreads)
              {
                  m_llThreads.add(t);
              }
              if (!m_thCollector.isAlive())
              {
                  m_thCollector.start();
              }
              sleep((int) (Math.random() * 100));
          }
      
          private void runSSLTest()
          {
              try
              {
                  testUrl.openConnection();
              }
              catch (IOException e)
              {
                  log("runSSLTest: " + e.getMessage());
                  e.printStackTrace();
              }
          }
      
          private void initComponents()
          {
              // ... create ui
          }
      
          private final static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy_HHmmss: ");
          private void log(String p_strMsg)
          {
              // ... log to screen and file
          }
      
          private void sleep(final int p_iMillis)
          {
              try
              {
                  Thread.sleep(p_iMillis);
              }
              catch (InterruptedException e)
              {}
          }
      
          public void actionPerformed(final ActionEvent e)
          {
              if (e.getActionCommand().equals(AC_END))
              {
                  synchronized (this)
                  {
                      m_iCycles = 0;
                  }
                  log("Test canceled by user.");
              }
              else if (e.getActionCommand().equals(AC_MEM_INFO) || e.getActionCommand().equals(AC_RUN_GC))
              {
                  if (e.getActionCommand().equals(AC_RUN_GC))
                  {
                      System.gc();
                  }
                  log("Free...: " + (Runtime.getRuntime().freeMemory() / 1024) + " kb\n");
                  log("Total...: " + (Runtime.getRuntime().totalMemory() / 1024) + " kb\n");
              }
              else if (e.getActionCommand().equals(AC_EXIT))
              {
                  log("Exiting application...");
                  dispose();
                  System.exit(0);
              }
              else if (e.getActionCommand().equals(AC_EXIT))
              {
                  log("Printing object map of all objects...");
                  creme.ObjectMap.printAll();
                  log("...done");
              }
          }
      
      
          public static void main(final String[] args)
          {
              if (args.length != 3)
              {
                  System.out.println("Parameter help: MODE(1=SSL,0=THREAD) CYCLES(-1=forever) URL(testURL for SSL test)");
                  return;
              }
      
              try
              {
                  new Thread(new MemoryTest(Short.parseShort(args[0]), Integer.parseInt(args[1]), args[2])).start();
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }
          }
      }
      I ran it from the command line like that and monitored the system's memory with the Windows CE performance monitor tool:
      creme.exe -wd /Temp MemoryTester 0 -1 https://my.ssl.url/path/file.jsp
      After about an hour it came to this: [monitor results|http://i625.photobucket.com/albums/tt340/swebble/crememem.png]
      As you can see, the memory load of the system steadily increases. The heap memory of the application remains more or less on the same level of only a few kb. Can someone commit this problem or even figure out what's wrong?

      When I use the SSL test mode which actually just opens ssl connections, the behavior is the same. I guess that the ssl implementation makes much use of threads internally.

      Best regards and thanks in advance,

      Sebastian