Problem with Job and JobManagerAdapter [message #129763] |
Thu, 23 April 2009 11:58 |
Loïc Bertholet Messages: 57 Registered: July 2009 |
Member |
|
|
Hi all,
I have a memory leak issue in my application that, I think, comes from the
JobManagerAdpater. Indeed, in the method done(final IJobChangeEvent
event), there is the following code :
Job job = event.getJob();
if( !job.shouldSchedule() ) {
jobs.remove( job );
}
However, shouldSchedule() always returns true so that the job is never
removed from jobs.
I'm using a job in an Editor and when this editor is closed, he is still
present in the JVM because of this job which is still contained in the
JobManagerAdpater jobs.
Fortunately, everything is well released when session is unvalidated.
I use a workaround by overriding the shouldSchedule() method but I think
this behavior is strange because not the same in RCP.
Moreover, the status bar keep displaying my job's name, even when it is
done, until another job is executed...
Loïc
|
|
|
|
|
Re: Problem with Job and JobManagerAdapter [message #130123 is a reply to message #129790] |
Fri, 24 April 2009 12:43 |
Loïc Bertholet Messages: 57 Registered: July 2009 |
Member |
|
|
Hi all,
I want to point your attention on this method because I don't understand
its behavior and it causes, I think, an important memory leak.
private void bindToSession( final Object keyToRemove ) {
ISessionStore session = RWT.getSessionStore();
HttpSessionBindingListener watchDog = new HttpSessionBindingListener()
{
public void valueBound( final HttpSessionBindingEvent event ) {
}
public void valueUnbound( final HttpSessionBindingEvent event ) {
try {
handleWatchDog( keyToRemove );
} finally {
synchronized( lock ) {
jobs.remove( keyToRemove );
}
}
}
private void handleWatchDog( final Object keyToRemove ) {
//
//////////////////////////////////////////////////////////// ////////
// TODO [fappel]: Very ugly hack to avoid a memory leak.
// As a job can not be removed from the
// running set directly, I use reflection. Jobs
// can be catched in the set on session timeouts.
// Don't know a proper solution yet.
// Note that this is still under investigation.
if( keyToRemove instanceof Job ) {
final Job jobToRemove = ( Job )keyToRemove;
Display display = ( Display )jobs.get( jobToRemove );
if( display != null ) {
UICallBack.runNonUIThreadWithFakeContext( display, new
Runnable() {
public void run() {
jobToRemove.cancel();
jobToRemove.addJobChangeListener( new JobCanceler() );
}
} );
}
try {
IJobManager jobManager = Job.getJobManager();
Class clazz = jobManager.getClass();
Field running = clazz.getDeclaredField( "running" );
running.setAccessible( true );
Set set = ( Set )running.get( jobManager );
synchronized( lock ) {
set.remove( keyToRemove );
// still sometimes job get catched - use the job marker
adapter
// to check whether they can be eliminated
Object[] runningJobs = set.toArray();
for( int i = 0; i < runningJobs.length; i++ ) {
Job toCheck = ( Job )runningJobs[ i ];
IJobMarker marker
= ( IJobMarker )toCheck.getAdapter( IJobMarker.class );
if( marker != null && marker.canBeRemoved() ) {
set.remove( toCheck );
}
}
}
} catch( final Throwable thr ) {
// TODO [fappel]: exception handling
thr.printStackTrace();
}
}
}
};
session.setAttribute( String.valueOf( watchDog.hashCode() ), watchDog
);
}
As I say, it is called by the JobManagerAdapter scheduled(...) method.
watchDog is put in the session with it hashCode as key but is never
removed from it.
Moreover it is a HttpSessionBindingListener whose valueUnbound method will
never be called as this object is instantiated inside the method and can
not be retrieved so session.setAttribute(...) won't be called again with
the same key.
So as I run a job, bindToSession(...) is called by scheduled() like 4
times and I have 4 watchDog inside the session...
Am I missing something ?
Is this a bug ?
Do you have a workaround ?
Thanks,
Loïc
Loïc Bertholet wrote:
> Even with the workaround, I still have my memory leak because the job has
> been put in the SessionStore thanks to bindToSession(final Object
> keyToRemove) which is called by the JobManagerAdapter scheduled(...)
> method.
> Why is it put in SessionStore and how can I remove it without doing
> specific RAP stuff (my wish is to have the same code running in RCP and
> RAP).
> Thanks.
> Loïc
|
|
|
Re: Problem with Job and JobManagerAdapter [message #130411 is a reply to message #130123] |
Mon, 27 April 2009 15:45 |
Rüdiger Herrmann Messages: 581 Registered: July 2009 |
Senior Member |
|
|
Loïc,
just to clarify: the memory leak you describe is resolved after the
session terminates, right?
Cheers,
Rüdiger
Loïc Bertholet wrote:
> Hi all,
>
> I want to point your attention on this method because I don't understand
> its behavior and it causes, I think, an important memory leak.
>
> private void bindToSession( final Object keyToRemove ) {
> ISessionStore session = RWT.getSessionStore();
> HttpSessionBindingListener watchDog = new HttpSessionBindingListener() {
> public void valueBound( final HttpSessionBindingEvent event ) {
> }
> public void valueUnbound( final HttpSessionBindingEvent event ) {
> try {
> handleWatchDog( keyToRemove );
> } finally {
> synchronized( lock ) {
> jobs.remove( keyToRemove );
> }
> }
> }
>
> private void handleWatchDog( final Object keyToRemove ) {
> //
> //////////////////////////////////////////////////////////// ////////
> // TODO [fappel]: Very ugly hack to avoid a memory leak.
> // As a job can not be removed from the
> // running set directly, I use reflection. Jobs
> // can be catched in the set on session timeouts.
> // Don't know a proper solution yet.
> // Note that this is still under investigation.
> if( keyToRemove instanceof Job ) {
> final Job jobToRemove = ( Job )keyToRemove;
> Display display = ( Display )jobs.get( jobToRemove );
> if( display != null ) {
> UICallBack.runNonUIThreadWithFakeContext( display, new
> Runnable() {
> public void run() {
> jobToRemove.cancel();
> jobToRemove.addJobChangeListener( new JobCanceler() );
> }
> } );
> }
> try {
> IJobManager jobManager = Job.getJobManager();
> Class clazz = jobManager.getClass();
> Field running = clazz.getDeclaredField( "running" );
> running.setAccessible( true );
> Set set = ( Set )running.get( jobManager );
> synchronized( lock ) {
> set.remove( keyToRemove );
> // still sometimes job get catched - use the job marker
> adapter
> // to check whether they can be eliminated
> Object[] runningJobs = set.toArray();
> for( int i = 0; i < runningJobs.length; i++ ) {
> Job toCheck = ( Job )runningJobs[ i ];
> IJobMarker marker
> = ( IJobMarker )toCheck.getAdapter( IJobMarker.class );
> if( marker != null && marker.canBeRemoved() ) {
> set.remove( toCheck );
> }
> }
> }
> } catch( final Throwable thr ) {
> // TODO [fappel]: exception handling
> thr.printStackTrace();
> }
> }
> }
> };
> session.setAttribute( String.valueOf( watchDog.hashCode() ), watchDog );
> }
>
> As I say, it is called by the JobManagerAdapter scheduled(...) method.
> watchDog is put in the session with it hashCode as key but is never
> removed from it.
> Moreover it is a HttpSessionBindingListener whose valueUnbound method
> will never be called as this object is instantiated inside the method
> and can not be retrieved so session.setAttribute(...) won't be called
> again with the same key.
> So as I run a job, bindToSession(...) is called by scheduled() like 4
> times and I have 4 watchDog inside the session...
>
> Am I missing something ?
> Is this a bug ?
> Do you have a workaround ?
>
> Thanks,
>
> Loïc
>
> Loïc Bertholet wrote:
>
>> Even with the workaround, I still have my memory leak because the job
>> has been put in the SessionStore thanks to bindToSession(final Object
>> keyToRemove) which is called by the JobManagerAdapter scheduled(...)
>> method.
>
>> Why is it put in SessionStore and how can I remove it without doing
>> specific RAP stuff (my wish is to have the same code running in RCP
>> and RAP).
>
>> Thanks.
>
>> Loïc
>
>
|
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.04970 seconds