Skip to main content

WINCE501bException

95 replies [Last post]
mkant
Offline
Joined: 2010-02-03
Points: 0

Hello,

my problem is that this exceptionn comes during the use of my programm on my mobile phone.

winCE501bexception

Does anyone know what could it be?

Thank you.

Best regards,

Mathias

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
mkant
Offline
Joined: 2010-02-03
Points: 0

Hello,
I think this thread is a little bit confused.
The Dates are not all right, or?
So my question:
Is there something new for the problems?
- for the WINCE501Exception and
- for the OutOfMemoryException?

Thank you for the update.
Best regards,
Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

I have been able to remove a few stale references, but there a few ones but there are still a few ones left (the JNI Frame ones) that I have trouble getting rid of. This goes deep into the VM and it is a bit of new terrain for me. Unfortunately, as long as these references are not cleaned up, garbage collection will not kick in and you still get the exceptions you mentioned.
Cheers,
Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Davy,
is there now a solution for the problem?
Thank you for the help.
Best regards,

Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

Hi Mathias,
I have been trying to rewrite the native peers to stablize the memory usage, but without much success I am afraid :-(
Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Davy,
this bug is a blocker for us.
Do you know an alternative solutions (VMs) for my software, if this bug will not fixed?
Thank you very much,
Best regards,
Mathias.

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Davy,
thank you very much for your trying to solve this problem.
I hope you will find a asoultion for this problem. :-)
Best regards,
Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

Mathias,

I had some luck in the past with running AWT and Swing applications on top of the Foundation Profile
for Windows Mobile 2003. To add AWT support, I used SwingWT and a SWT implementation for WinCE.
I basically did not have to change the application itself, but had to extend the bootclasspath to use the
additional libraries. Probably not all AWT features are fully supported due to some missing AWT classes.

It was a bit slower and base memory consumption was a bit higher, but the test application I made to
trigger the issue you mentioned does not occur with this setup.

Regards
Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Davy,
this is not really a alternative for me, because the second device that we have for this software only have 64 MB RAM.
Is there a chance that you find a solution for this?
I hope. ;-)
Best regards,
Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

Hi Mathias,

I must confess, I have not further looked into the issue lately. Let's say that with Windows Phone 7
and the inability to run phoneME (or any other native code for that matter) on these devices,
my interest in this platform has dropped a little :-(.

However, I did run this SwingWT/SWT setup on devices with only 64MB ram so YMMV.

Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

Here the complete error Stacktrace:

java.lang.OutOfMemoryError: invalid error
at sun.awt.pocketpc.PPCButtonPeer.create(Native method)
at sun.awt.pocketpc.PPCComponentPeer.(Compiled Method)(PPCComponentPeer.java:290)
at sun.awt.pocketpc.PPCButtonPeer.(Compiled Method)(PPCButtonPeer.java:47)
at sun.awt.pocketpc.PPCToolkit.createButton(Compiled Method)(PPCToolkit.java:170)
at java.awt.Button.addNotify(Compiled Method)(Button.java:136)
at java.awt.Container.addNotify(Compiled Method)(Container.java:1353)
at java.awt.Panel.addNotify(Compiled Method)(Panel.java:89)
at java.awt.Container.addImpl(Compiled Method)(Container.java:312)
at java.awt.Container.add(Compiled Method)(Container.java:216)
at TestFrame2$1.actionPerformed(Compiled Method)(TestFrame2.java:67)
at java.awt.Button.processActionEvent(Button.java:284)
at java.awt.Button.processEvent(Button.java:257)
at java.awt.Component.dispatchEventImpl(Component.java:2133)
at java.awt.Component.dispatchEvent(Component.java:1929)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:316)
at java.awt.EventQueueProxy.dispatchEvent(EventDispatchThread.java:325)
at java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:127)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:122)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:113)
at java.lang.Thread.startup(Thread.java:785)

davyp
Offline
Joined: 2007-01-03
Points: 0

Thanks Mathias for the new example, but if you look a little closer, I think it is normal that you
get an OutOfMemory exception at some point with this example.

If you run the application without pushing the button, memory usage should remain stable.
But with each button click, you add 3000 Panel objects to the same frame object (which
acts as a container), and you add the same action listener to each button over and over again.

Just remove the 100msec sleep function in the action listener, and run it on a desktop. At some
point you will get the out of memory exception there as well basically because the frame keeps
on growing and growing with new references to the same Panels.

Furthermore, after the first button click, you carry out the action listener. But because you
keep on adding action listeners to the same button, they all get executed in the next run
one after the other, making the memory allocation even worse.

So the second time you click on the button, you execute the body of the action listener two
times. With the 3rd click, you execute it 4 times (remember with each execution of the
listener you add another listener). With the 4th click, you execute it 8 times.

And with each run you keep on adding Panels in the main frame. So at some point this is bound
to give an outofmemory exception.

Do you get what I am trying to explain?

Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Davy,

I get the exception on the first run. I do not push the button again, only one time.

I understand your explanation, if I push more than one time.

In my main app I have one frame, too. And I add each panel to the frame. So I try to rebuild the main app with this demo app.

my main app:
- I create all panels (without UI)
- when the frame show the panel (with Cardlayout) the UI is build and the panel is shown

Best regards,

Mathias

billp
Offline
Joined: 2006-09-19
Points: 0

When a thread is created a new Java stack is allocated. Frame 0, where we see those two references, is initialized as a JNI frame and a number of local references are allocated in that frame. See CVMinitExecEnv() in interpreter.c.:
/* Allocate JNI local refs for targetEE
*/
CVMcurrentThreadICell(targetEE) = CVMjniCreateLocalRef0(ee, targetEE);
CVMmiscICell(targetEE) = CVMjniCreateLocalRef0(ee, targetEE);
CVMsyncICell(targetEE) = CVMjniCreateLocalRef0(ee, targetEE);
CVMfinalizerRegisterICell(targetEE) = CVMjniCreateLocalRef0(ee, targetEE);
CVMallocationRetryICell(targetEE) = CVMjniCreateLocalRef0(ee, targetEE);
CVMlocalExceptionICell(targetEE) = CVMjniCreateLocalRef0(ee, targetEE);
#ifdef CVM_REMOTE_EXCEPTIONS_SUPPORTED
CVMremoteExceptionICell(targetEE) = CVMjniCreateLocalRef0(ee, targetEE);
#endif
CVMcurrentExceptionICell(targetEE) = CVMjniCreateLocalRef0(ee, targetEE);

These local ref addresses are stored into the EE at various locations such as CVMcurrentThreadICell, CVMmiscICell etc. See interpreter.h for where these macros point.
You should be able to examine each of these references stored in the EE and see which ones have a reference to the object in question.

bill

mkant
Offline
Joined: 2010-02-03
Points: 0

Sorry for the many post. I only notice the things of my mind.

Could it be a problem with the parameter useLargeMemoryArea?

Or is my command line incorrect?

Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

Mathias,

I think both Hinkmond and I are just guessing at what the problem is. At the moment, I can
only reproduce the memory issue you mentioned earlier and I am still investigating the dangling
pointers with the CVM inspector. I have pinned it down to the event loop code, but "fixing" it is
not trivial as I have to mess around with the WinCE event loop too. However, if you have
reworked your code like Hinkmond said, it should not affect you anymore.

Regarding the second problem, my guess is that it is also memory related but I cannot be
sure. The useLargeMemoryArea option has seen some code changes recently. You could see
what happens if you allocate less than 32MB and disable that option.

Can you share your application for testing purposes? I could add debug statements in the VM
code and see what would happen if I run your application with it. If you cannot make it publicly
available, you can send me a private email (see http://davy.preuveneers.be for details), and I will
see what I can do to help.

Davy

Hinkmond Wong

On 10/15/2010 10:16 AM, phonemeadvanced@mobileandembedded.org wrote:
> Mathias,
>
> I think both Hinkmond and I are just guessing at what the problem is. At the moment, I can
> only reproduce the memory issue you mentioned earlier and I am still investigating the dangling
> pointers with the CVM inspector. I have pinned it down to the event loop code, but "fixing" it is
> not trivial as I have to mess around with the WinCE event loop too. However, if you have
> reworked your code like Hinkmond said, it should not affect you anymore.
>
> Regarding the second problem, my guess is that it is also memory related but I cannot be
> sure. The useLargeMemoryArea option has seen some code changes recently. You could see
> what happens if you allocate less than 32MB and disable that option.
>
> Can you share your application for testing purposes? I could add debug statements in the VM
> code and see what would happen if I run your application with it. If you cannot make it publicly
> available, you can send me a private email (see http://davy.preuveneers.be for details), and I will
> see what I can do to help.

Hi Mathias,

I agree with Davy. The next step is for you to try allocating -Xms30m
and don't use use the large memory area option. If that doesn't work,
if you don't want to post your entire app to this public forum or to
Davy privately, a small testcase that can demonstrate the same error
would be needed.

Hinkmond

---------------------------------------------------------------------
To unsubscribe, e-mail: advanced-unsubscribe@phoneme.dev.java.net
For additional commands, e-mail: advanced-help@phoneme.dev.java.net

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello,

I tried it witohout the parameter uselargememoryarea.
But with the following commands nothing happens. The app does not start.

#"\Programme\pMEA PP\bin\cvm.exe" -Djava.library.path=\mobileforms\lib -Xmx30M -Duser.language=de -Duser.country=DE -cp "\mobileforms\MobileForms.jar" de.igosys.mobileforms.MobileForms

#"\Programme\pMEA PP\bin\cvm.exe" -Djava.library.path=\mobileforms\lib -Xms30M -Duser.language=de -Duser.country=DE -cp "\mobileforms\MobileForms.jar" de.igosys.mobileforms.MobileForms

I have tried the commands with -Xopt:useLargeMemoryArea=false, too.

Do you see a mistake in my command?

Thank you.

Best regards,

Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

Setting the max heap with -Xmx30m should be enough. Setting the minimum heap is not necessary. FWIW, you can also add the parameters:

"-Xopt:stdioPrefix=/storage card,useConsole=true"

It will display errors etc. onto a console window and also log it to files in /storage card

Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Davy,

this parameters change nothing. UseConsole is already activated in config.exe of the runtime.

With these paramters no file was created.

Very strange, that nothing happens and no error was throwing.

#"\Programme\pMEA PP\bin\cvm.exe" "-Xopt:stdioPrefix=\SD Card,useConsole=true" -Djava.library.path=\mobileforms\lib -Xmx30M -Duser.language=de -Duser.country=DE -cp "\mobileforms\MobileForms.jar" de.igosys.mobileforms.MobileForms

Best regards,

Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

Odd indeed.

Make sure that the lnk file is smaller than 255 bytes (I think it is the case) with no \n (newline)
character at the end. Also, normally a lnk file starts with a number:

254#"\storage card\personal\bin\cvm.exe" ...

I cannot think of anything else at the moment. Perhaps see what happens if you do set the
maximum heap to -Xmx16M.

Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Davy,

I have changed my Demo program.
With this code I get a outofmemoryerror: invalid error (not at each try)
when I add a panel to the frame (at ca. 25000 KB used memory)

I think this must be the same error as at my main app.

Can you explain this error?

Thank you.

Best regards,

Mathias

import java.awt.CardLayout;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class TestFrame2 {

List frames;
CardLayout layout = new CardLayout();
Frame frame;

public static void main (String args[]) {
try {
new TestFrame2();
}
catch (Exception _e) {
System.out.println(_e);
_e.printStackTrace();
try {
Thread.sleep(20000);
}
catch (InterruptedException _e1) {
// TODO Auto-generated catch block
_e1.printStackTrace();
}
}
}

public TestFrame2() {
TestFrame2.updateTimer();
this.frame = new Frame();
this.frame.setLayout(this.layout);

this.frames = new ArrayList();
for (int i = 0; i < 3000; i++) {
this.frames.add(new ChangeFrame2(i));
}

this.frame.add((Panel)
(((ChangeFrame2)TestFrame2.this.frames.get(0)).getPanel()),
String.valueOf(0));

((ChangeFrame2)this.frames.get(0)).getButton().
addActionListener(new ActionListener()
{

public void actionPerformed(ActionEvent _e) {

/* add each button in the panel an actionlistener
* and show the panel */
for (int i = 0; i < TestFrame2.this.frames.size(); i++) {
((ChangeFrame2)TestFrame2.this.frames.get(i)).getPanel();
((ChangeFrame2)TestFrame2.this.frames.get(i)).getButton().
addActionListener(this);

Object obj;
Panel panel;

obj = TestFrame2.this.frames.get(i);
panel = (Panel)(((ChangeFrame2)obj).getPanel());

TestFrame2.this.frame.add(panel, String.valueOf(i));

TestFrame2.this.layout.show(TestFrame2.this.frame, String.valueOf(i));
try {
Thread.sleep(100);
}
catch (InterruptedException _e1) {
// TODO Auto-generated catch block
_e1.printStackTrace();
}

}

System.out.println((Runtime.getRuntime().totalMemory() >> 10) -
(Runtime.getRuntime().freeMemory() >> 10));
}
});
TestFrame2.this.frame.setSize(200,200);
TestFrame2.this.frame.setVisible(true);
TestFrame2.this.layout.show(TestFrame2.this.frame, String.valueOf(0));

}

/**
* updateTimer to log the memory.
*/
public static void updateTimer() {
Timer timer;
TimerTask task;

timer = new Timer();
task = new TimerTask() {
public void run() {
System.gc();
System.out.println((Runtime.getRuntime().totalMemory() >> 10) -
(Runtime.getRuntime().freeMemory() >> 10));

}
};

timer.schedule(task, 2000, 10000);
}
}

import java.awt.Button;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Label;
import java.awt.Panel;

public class ChangeFrame2 {

public static int count = 0;
public int i;
private Button button;
private Panel panel;

public ChangeFrame2(int _i) {
i = _i;
}

public Button getButton() {
return this.button;
}

public Panel getPanel() {
if (this.panel == null) {
this.panel = new Panel(new GridBagLayout());
this.initializeUI(this.panel);
}
return this.panel;
}

/**
*
*/
public void dispose() {
this.getPanel().removeAll();
this.button = null;
}

protected void initializeUI(Container _frame) {
GridBagConstraints gbc;
Label label;

gbc = new GridBagConstraints();
this.button = new Button("sdsd");

label = new Label("dfdsfd");

_frame.setLayout(new GridBagLayout());
_frame.add(this.button, gbc);
_frame.add(label, gbc);
_frame.add(label, gbc);
_frame.setSize(200, 200);
_frame.setVisible(true);

}
}

mkant
Offline
Joined: 2010-02-03
Points: 0

Only a question: Is there another possibility to chat with you (Davy or Hinkmond)? like ICQ, Skype or anything else.

This could make it a little bit faster.

Thank you,

Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

Mathias,

I am trying to help you as good as I can and I am sure Hinkmond is too. However, the
information we have is just not enough to reproduce this problem. Having access to your
application would help (also see my other post).

Also, I know my WinCE phoneME port may have issues and the support on this forum is not
what you would get for commercially supported products, but it is the best I can do with the limited
spare time I have.

Regards,
Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

I am very helpless for this problem and this is for my app a very big problem.

I have free memory but the app collapsed with an outofmemory.

I can not explain it for me.

Is there any parameter to change something with the memory or is there another memory which throw the outofmemory exception?

I don't know.

I hope somebody can help me wiht this problem.

Thank you.

Best regards,

Mathias

Message was edited by: mkant

mkant
Offline
Joined: 2010-02-03
Points: 0

I have found an exception.
I get an OutOfMemoryException() when the app collapsed.
BUT:
totalMemory: 40124KB
free memory: 8834KB
used memory: 31290KB

Why comes ther an outofmemory exception?

I work with the 168 build of davy.

Best regards,

Mathias

Hinkmond Wong

On 10/14/2010 6:12 AM, phonemeadvanced@mobileandembedded.org wrote:
> I have found an exception.
> I get an OutOfMemoryException() when the app collapsed.
> BUT:
> totalMemory: 40124KB
> free memory: 8834KB
> used memory: 31290KB
>
> Why comes ther an outofmemory exception?

Does the exception happen as the VM is being initialized or after the
app has been running for a while?

Hinkmond

---------------------------------------------------------------------
To unsubscribe, e-mail: advanced-unsubscribe@phoneme.dev.java.net
For additional commands, e-mail: advanced-help@phoneme.dev.java.net

mkant
Offline
Joined: 2010-02-03
Points: 0

after 10 to 15 minutes (when I have 280 to 300 panels (questions) finished.

Mathias

Message was edited by: mkant

davyp
Offline
Joined: 2007-01-03
Points: 0

I am a bit stuck here. This is what I do:

cvmsh> gc
free memory = 1984076
total memory = 2097152

cvmsh> run TestFrame
Done.

cvmsh> gc
free memory = 1926336
total memory = 2097152

cvmsh> gc
free memory = 1926748
total memory = 2097152

cvmsh> disableGC

cvmsh> dumpClassReferences java.awt.Panel
Addr: 0x2c27dc Size: 204 Class: java.awt.Panel
List of references to object 0x2c27dc (java.awt.Panel):
Ref 0x434c6b4 type: JNI FRAME ROOT ee 0x434c360 frame 0
Ref 0x434c6b0 type: JNI FRAME ROOT ee 0x434c360 frame 0

cvmsh> dumpStack 0x434c360
Stack for thread EE 0x434c360:
JNI Frame sun.awt.pocketpc.PPCToolkit.eventLoop()V(Native Method)
Java Frame sun.awt.pocketpc.PPCToolkit.run()V(PPCToolkit.java:126)
Java Frame java.lang.Thread.run()V(Thread.java:715)
Java Frame java.lang.Thread.startup(Z)V(Thread.java:785)
Transition Frame java.lang.Thread.startup(Z)V(Transition Method)
Free List Frame (JNI Local Frame)

With the last command I have a stacktrace of the thread that holds a reference to a
java.awt.Panel object. The eventLoop call goes native into a blocking while loop that receives
events (picking WinCE messages from a queue). I don't see any references to the
java.awt.Panel in the eventLoop code.

The above thread is created as soon as the peer toolkit is created as a factory for the awt panel
peer objects. It basically stays alive until the application quits. In fact, even when the
application has ended, I can see 6 live threads (of which one or two are used for running the
CVM inspector, the others are old threads managing the event dispatching, exit handler, etc).

Is my understanding correct that with the above dumpStack command I only know on which
Java thread the dangling references were made? I am trying to make sense of it using Mark's
map of the CVM (http://weblogs.java.net/blog/mlam/archive/2006/11/the_big_picture.html).

If so, as a thread can intersect a lot of code, can I narrow down the search space in native code
a bit further? I have noticed a lot of AWT objects are not GC'ed and I am looking for the root
cause.

Davy

Hinkmond Wong

On 10/16/2010 4:16 PM, phonemeadvanced@mobileandembedded.org wrote:
> ...
> Is my understanding correct that with the above dumpStack command I only know on which
> Java thread the dangling references were made? I am trying to make sense of it using Mark's
> map of the CVM (http://weblogs.java.net/blog/mlam/archive/2006/11/the_big_picture.html).
>
> If so, as a thread can intersect a lot of code, can I narrow down the search space in native code
> a bit further? I have noticed a lot of AWT objects are not GC'ed and I am looking for the root
> cause.
>

Bill, do you think having Davy use a JVMPI build of phoneME Advanced,
then analyze the hprof output with something like the Heap Analysis Tool
(HAT: http://jovial.com/javasoft/heap/index.html ) would help?

Thanks,
Hinkmond

---------------------------------------------------------------------
To unsubscribe, e-mail: advanced-unsubscribe@phoneme.dev.java.net
For additional commands, e-mail: advanced-help@phoneme.dev.java.net

billp
Offline
Joined: 2006-09-19
Points: 0

Haven't used that tool myself. I think the answer is in the local refs created when a thread starts. See my previous post.

bill

mkant
Offline
Joined: 2010-02-03
Points: 0

I see one problem in my app:
At ca. 34MB used memory (total - free) the app collapsed. (the app does not react)
Free memory is enough (ca. 8 MB).
I notice that because of new questionnaires and new panels with it.
When I let out the new questionnaires it works.

Before it, the whole questioning works.

What can it be? Another memory problem?

#"\Programme\pMEA PP\bin\cvm.exe" -Dsun.java2d.pmoffscreen=true -Djava.library.path=\mobileforms\lib -Xopt:useLargeMemoryArea=true -Xmx64M -Duser.language=de -Duser.country=DE -cp "\mobileforms\MobileForms.jar" de.igosys.mobileforms.MobileForms

Thank you

Best regards,

Mathias

Message was edited by: mkant

Message was edited by: mkant

Hinkmond Wong

On 10/13/2010 6:14 AM, phonemeadvanced@mobileandembedded.org wrote:
> I see one problem in my app:
> At ca. 34MB used memory (total - free) the app collapsed.
> Free memory is enough (ca. 8 MB).
> I notice that because of new questionnaires and new panels with it.
> When I let out the new questionnaires it works.
>
> Before it, the whole questioning works.
>
> What can it be? Another memory problem?

It could also be a Threading problem. Are you creating threads in your
application? Do you synchronize your threads or make sure to block when
the UI thread is running?

Hinkmond

---------------------------------------------------------------------
To unsubscribe, e-mail: advanced-unsubscribe@phoneme.dev.java.net
For additional commands, e-mail: advanced-help@phoneme.dev.java.net

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello,

I only use threads for NON-GUI things. But I will look to this possibility of problem.

ANd ActionListener for the actions.

Thank you,

Mathias

Message was edited by: mkant

davyp
Offline
Joined: 2007-01-03
Points: 0

Are you using any additional WinCE DLLs (accessed through JNI) in your application?

Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

I use a dll for executing an extern program. Why?

But the app collapsed without using this dll.

Message was edited by: mkant

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Hinkmond,

I have write it in this forum: Now, I do not delete or remove the panels. I hold the panels and if I need the panels again, I fill the panels with my content and show them.
And the memory doesn' t rise and raise. But the WINCE501Exception come again after minutes.

Thank you for the tip.

Bes regards,

Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

Glad to hear you were able to work around the AWT memory retaining issue.

If you google for WINCE501bException, you will notice this exception is not easy to pin down.

In order to rule out differences between the different versions of WM6:
-Do you get this behavior on the HP Ipaq 214 (which runs Windows Mobile 6 Classic)?
-Can you reproduce this exception in the MS Device Emulator running Windows Mobile 6
Professional (or equivalent device)?

In order to figure out if it is memory related:
-Does it happen sooner if you decrease the amount of available memory?

Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Davy,

-Do you get this behavior on the HP Ipaq 214 (which runs Windows Mobile 6 Classic)?

yes, there the exception comes.

-Can you reproduce this exception in the MS Device Emulator running Windows Mobile 6
Professional (or equivalent device)?

I do not use an emulator.

-Does it happen sooner if you decrease the amount of available memory?

yes, it happens before.

This exception is very annoying.

I hope somebody can help me.

Thank you.
Best regards,

Mathias

Hinkmond Wong

On 10/6/2010 11:33 AM, phonemeadvanced@mobileandembedded.org wrote:
> Based on what I found elsewhere a WINCE501bException usually means that an out-of-memory
> has occurred.
>
> http://social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/530c30...
>
> http://social.msdn.microsoft.com/Forums/en-US/sqlce/thread/04afe059-095e...
>
> For phoneME, it means an error in the native part of the VM (rather than in the Java heap space).
> If I can fix the native widget's memory release issue, it might solve this problem as well. My gut
> feeling tells me there is somewhere in the native peer implement a reference to certain AWT
> objects not explicitly being released and this may explain why you run out of memory as the
> garbage collector cannot clean up all the objects.

Hi Mathias,

As a workaround for now (and as a better coding practice in general) you
should try rewriting your app to not keep creating and destroying
multiple AWT objects in your Panel each time you want your UI to
change. Instead, just reuse the AWT objects in your Panel already and
reset the values (String Objects) to the new values instead. This way,
you will not keep creating and destroying UI objects which may not be
getting garbage collected correctly for whatever reason. Also, this way
saves time in object destruction/creation and makes your UI much
faster. This approach is usually the best practice for UI programming,
not the way you are doing it currently.

Hinkmond

---------------------------------------------------------------------
To unsubscribe, e-mail: advanced-unsubscribe@phoneme.dev.java.net
For additional commands, e-mail: advanced-help@phoneme.dev.java.net

mkant
Offline
Joined: 2010-02-03
Points: 0

I have updated my app to this way already.
Now th memory is not the problem I think.
Now comes after work with the app the WINCE501Exception.
I hope if davy have fix the problem, the Exception does not come again.

Best regards,

Mathias

davyp
Offline
Joined: 2007-01-03
Points: 0

I spent the whole day trying to fix the problem, but I have not made any progress I am afraid. I
tested a linux x86 build with Qt based AWT peers and it releases memory as expected. I
assumed the bug in the WinCE port was due to one of my AWT patches, but I have eliminated
them to a bare minimum needed to get the sources compiling. Now I only have a few changes
compared to the original code base in subversion and with the resulting build, the issue remains.
So it is quite likely the issue was there before I started fixing the port.

Hinkmond: I have checked for CVM_USE_MMAP_APIS=true in the log file and this was not
the case. However, it is set to 1 in src/win32/javavm/include/memory_md.h and included in
cdc/src/win32/javavm/runtime/memory_md.c.

I have been using the test code above, and although it has some issues of its own causing the
main frame not to release/remove all panels after the button click. It should however release
references to most objects. My guess is that this issue may have to do with the way how Java
AWT peers are addressed natively by getting and storing a global reference to the object and
that therefore memory cannot be reclaimed as long as the native object is not destructed.

Right now I could use some help from the experts for finding a good way to figure out which
objects are holding on to memory (i.e. the live objects that are not being garbage collected)
because another object holds a (stale) reference to the object. What is the best way to do or
debug this?

Davy

davyp
Offline
Joined: 2007-01-03
Points: 0

After another day of experimenting, I have figured out what is causing the "memory leak". It
happens when you modify a native window (such as an AWT Frame) after it has been made visible
with x.show() or x.setVisible(true). Here is my simplified test example:

import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class TestFrame {

ArrayList frames;
Frame frame;

public TestFrame() {
frame = new Frame();
frame.setLayout(new FlowLayout());
frame.setSize(240, 150);
// frame.setVisible(true);
}

public void runGCTest() {
System.out.println((Runtime.getRuntime().totalMemory() >> 10) -
(Runtime.getRuntime().freeMemory() >> 10));

frames = new ArrayList();
for (int i = 0; i < 2500; i++) {
frames.add(new Panel());
}

for (int i = 0; i < frames.size(); i++) {
frame.add(((Panel)frames.get(i)));
frame.remove(((Panel)frames.get(i)));
}
frame.validate();
frames.clear();
frames = null;

System.gc();
System.out.println((Runtime.getRuntime().totalMemory() >> 10) -
(Runtime.getRuntime().freeMemory() >> 10));
}

public static void main(String args[]) {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
System.gc();
System.out.println((Runtime.getRuntime().totalMemory() >> 10) -
(Runtime.getRuntime().freeMemory() >> 10));
}
};
timer.schedule(task, 1000, 1000);

TestFrame testframe = new TestFrame();
for (int i=0; i<5; i++) {
try {
Thread.sleep(1000);
}
catch (Exception e) {}
testframe.runGCTest();
}

System.out.println("Show frame ...");
testframe.frame.setVisible(true);
testframe.frame.show();

try {
Thread.sleep(5000);
}
catch (Exception e) {}

task.cancel();
System.exit(0);
}
}

If you enable the frame.setVisible(true); in the constructor, you appear to have the memory
leak when calling to the frame.add() and frame.remove() instructions. If you disable it like above,
the "memory leak" is gone. Obviously, if you disable the frame.add() and frame.remove(), there
is no "memory leak" either.

Mathias: could you try to modify your app (not calling setVisible(true) to early) and see if this
fixes the memory issue?

Ideally, the PocketPC peers should somehow take care of this, but you now can at least work
your way around it. If I have some more time, I will check what is so different between adding
AWT components to a container before and after a frame has been made visible.

Davy

mkant
Offline
Joined: 2010-02-03
Points: 0

Hello Davy,

thank you you for your work, but I do not think that this helps me.

My applicatin is something lke a questionnaire. That means that I must call setVisible()
after each question. I have a main frame and this frame shows all panels (with a cardlayout).

In your example you does not show a panel. You add it and remove it and at the end you show the frame.

I hope I understand your example right.

Thank you.

Best regards,

Mathis

davyp
Offline
Joined: 2007-01-03
Points: 0

Hi Mathias,

Yes, my example is slightly different, but it also has the memory retaining issue. I don't mind
that is not functionally identical. I just want a small example with which I can experiment.

In the meantime, I have figured out what is happening. If you make the frame visible in the
constructor, it automatically creates the platform dependent AWT peer objects for PocketPC.
That's fine, but I have noticed with the CVM inspector:

http://weblogs.java.net/blog/2007/07/31/cvms-vm-inspector

that after adding and removing a lot of Panel objects, these objects are not garbage collected
due to circular references between e.g. java.awt.Panel and java.awt.LightweightDispatcher

java.awt.LightweightDispatcher: nativeContainer -> java.awt.Panel
java.awt.Panel: dispatcher -> java.awt.LightweightDispatcher

There is also an object sun.awt.IdentityWeakHashMap$Entry holding a reference:
sun.awt.IdentityWeakHashMap$Entry: referent -> java.awt.Panel

There is no quick solution for this, and fixing this issue quite likely requires a side-by-side
comparison with e.g. the Qt AWT peer backends in order to figure out why the latter does not
have this problem :-(

Davy

Hinkmond Wong

On 10/11/2010 7:43 AM, phonemeadvanced@mobileandembedded.org wrote:
> Hi Mathias,
>
> Yes, my example is slightly different, but it also has the memory retaining issue. I don't mind
> that is not functionally identical. I just want a small example with which I can experiment.
>
> In the meantime, I have figured out what is happening. If you make the frame visible in the
> constructor, it automatically creates the platform dependent AWT peer objects for PocketPC.
> That's fine, but I have noticed with the CVM inspector:
>
> http://weblogs.java.net/blog/2007/07/31/cvms-vm-inspector
>
> that after adding and removing a lot of Panel objects, these objects are not garbage collected
> due to circular references between e.g. java.awt.Panel and java.awt.LightweightDispatcher
>
> java.awt.LightweightDispatcher: nativeContainer -> java.awt.Panel
> java.awt.Panel: dispatcher -> java.awt.LightweightDispatcher
>
> There is also an object sun.awt.IdentityWeakHashMap$Entry holding a reference:
> sun.awt.IdentityWeakHashMap$Entry: referent -> java.awt.Panel
>
> There is no quick solution for this, and fixing this issue quite likely requires a side-by-side
> comparison with e.g. the Qt AWT peer backends in order to figure out why the latter does not
> have this problem :-(

Thanks, Davy, for the further details on this issue. I agree there will
be no quick solution for this problem, since a circular reference like
that starting from making the frame visible might take some time to sort
out.

Mathias, the quickest fix is probably best as I suggested: Rewrite you
app to not create/destroy so many AWT objects in your Panel, but instead
have one Panel where you update the String values of each of the
children AWT objects to reflect new questions in your questionnaire each
time you want to switch to a new "screen". This way you will reuse the
AWT components and the user will see a brand new screen every time you
refresh the String values in all the children AWT objects. There should
be no memory leaks if you follow this workaround, and the visual effect
will be the same as if you were creating and destroying multiple AWT
objects.

Hinkmond

---------------------------------------------------------------------
To unsubscribe, e-mail: advanced-unsubscribe@phoneme.dev.java.net
For additional commands, e-mail: advanced-help@phoneme.dev.java.net

davyp
Offline
Joined: 2007-01-03
Points: 0

I am trying to clean up all stale references to the java.awt.Panel objects. I messed around with
some code in the java.awt.Component and java.awt.Container classes, and I know it is not
the proper way to fix it, but I would like to see where these references to the Panel objects
are created.

The CVM inspector has been quite helpful, but now I have some references left and I have
difficulty with understanding what the following means. This is the output of
'dumpClassReferences java.awt.Panel' (with just one java.awt.Panel created in the application).

Addr: 0x32a010 Size: 204 Class: java.awt.Panel
List of references to object 0x32a010 (java.awt.Panel):
Ref 0x43e6444 type: JNI FRAME ROOT ee 0x43dbcc0 frame 0
Ref 0x43e6440 type: JNI FRAME ROOT ee 0x43dbcc0 frame 0

I am talking about the JNI FRAME ROOT references here. I assume there are some global or
local references in some native code, but how do I trace it back to the Java or native object that
holds the reference?

Thanks,
Davy

billp
Offline
Joined: 2006-09-19
Points: 0

A JNI frame is pushed on the Java stack before calling a JNI method. Native code can then create JNI local references on the stack which is probably what you see in this output.
If you are using the cvm inspector, try the dumpStack command to see the Java stack trace for this thread. It might lead you to the Java code that is calling into native and from there you might be able to figure out where this reference is being created.

bill

davyp
Offline
Joined: 2007-01-03
Points: 0

Thanks Bill for the tip. I tried this already but could not find the reference this way. I will dig a little
deeper.

Davy

Hinkmond Wong

Hi Davy,

When you build from the current phoneME Advanced trunk, do you know if
your WinMobile build is picking up the following default makefile
variable and setting it automatically for you:

CVM_USE_MMAP_APIS=true

I think you should be able to check in your build directory that was
used to create your binary in the following build generated file:

build/win32-arm-wm6/.previous.build.flags

With the above make variable set to true, it validates that there is
probably a bug in the native widget porting layer, since the
growable/shrinkable heap is enabled and should be working.

Thanks,
Hinkmond

---------------------------------------------------------------------
To unsubscribe, e-mail: advanced-unsubscribe@phoneme.dev.java.net
For additional commands, e-mail: advanced-help@phoneme.dev.java.net

davyp
Offline
Joined: 2007-01-03
Points: 0

There seems to be a delay with Hinkmond's posts. Anyway, it is quoted below.

I am pretty sure it is a native widget issue, and therefore not that trivial to investigate. I don't have
access to my build machine right now to check the build flag, but I more or less confirmed my
assumption by creating a simple console example:

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class TestExample {
List objects;

public class TestObject {
int data[] = new int[1000];
int num;

public TestObject(int n) {
num = n;
for (int i=0; i data[i] = n;
}

public int getSum() {
int sum = 0;
for (int i=0; i sum += data[i];

return sum;
}
}

public static void main (String args[]) {
new TestExample();
}

public TestExample() {
TestExample.updateTimer();

System.out.println("Create objects ...");
this.objects = new ArrayList();
for (int i = 0; i < 1000; i++) {
this.objects.add(new TestObject(i));
}
System.gc();
System.out.println((Runtime.getRuntime().totalMemory() >> 10) -
(Runtime.getRuntime().freeMemory() >> 10));

try {
Thread.sleep(5000);
}
catch (Exception e) {}

System.out.println("Clean up objects ...");
TestExample.this.objects.clear();
TestExample.this.objects = null;

try {
Thread.sleep(5000);
}
catch (Exception e) {}

System.exit(0);
}

public static void updateTimer() {
Timer timer;
TimerTask task;

timer = new Timer();
task = new TimerTask() {
public void run() {
System.gc();
System.out.println((Runtime.getRuntime().totalMemory() >> 10) -
(Runtime.getRuntime().freeMemory() >> 10));
}
};

timer.schedule(task, 2000, 2000);
}
}

And if I run that, it prints something like the following output:
Create objects ...
4031
4031
4032
Clean up objects ...
90
90
90
90

Here it is clear the memory consumption decreases like it should. I will see if I can get it
fixed over the weekend, no promises though.

Davy

On Tuesday, October 05, 2010 12:56:34 am Hinkmond Wong wrote:
> Hi Davy,
>
> When you build from the current phoneME Advanced trunk, do you know if
> your WinMobile build is picking up the following default makefile
> variable and setting it automatically for you:
>
> CVM_USE_MMAP_APIS=true
>
> I think you should be able to check in your build directory that was
> used to create your binary in the following build generated file:
>
> build/win32-arm-wm6/.previous.build.flags
>
>
> With the above make variable set to true, it validates that there is
> probably a bug in the native widget porting layer, since the
> growable/shrinkable heap is enabled and should be working.
>
>
> Thanks,
> Hinkmond
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: advanced-unsubscribe@phoneme.dev.java.net
> For additional commands, e-mail: advanced-help@phoneme.dev.java.net