Обсуждение: non-trivial finalize() on AbstractJdbc2Statement

Поиск
Список
Период
Сортировка

non-trivial finalize() on AbstractJdbc2Statement

От
Imran
Дата:
Hello

We've been having OOM errors in our applications through GC overhead limits under heave load resources running queries. Inspecting the heap dump, it appears that the finalizer queue is taken up most of the heap space. Almost all of the the finalizer objects I've seen seem to have a jdbc3PreparedStatement object in it. Going through the source code of the driver I see that the 'AbstractJdbc2Statement' has a non-trivial finalize method. I guess this explains why these objects end up in the finalizer queue. Can I clarify the need to having this finalize() method here? It seems to be calling the close() method of the statement which I would have thought is the responsibility of the client building a Statement object. Is there any chance this can be dropped so we don't see these objects ending up in the finalizer queue under heavy load and the jvm running out of memory before the GC threads gets around to 'actually' reclaim the memory?

Also we are using postgres 9.0.4 and the 8.3-604.jdbc3 version of the postgresql jdbc driver.

Cheers
-- Imran

Re: non-trivial finalize() on AbstractJdbc2Statement

От
Dave Cramer
Дата:
Well this is a typical which is worse case scenario. People leaking
resources because they don't explicitly close them, or your case ? I'm
not sure which is worse.

Given that the driver is being used in many very high throughput sites
without this problem, I'm curious as to why nobody else has complained

Dave Cramer

dave.cramer(at)credativ(dot)ca
http://www.credativ.ca



On Fri, Feb 10, 2012 at 12:39 PM, Imran <imranbohoran@gmail.com> wrote:
> Hello
>
> We've been having OOM errors in our applications through GC overhead limits
> under heave load resources running queries. Inspecting the heap dump, it
> appears that the finalizer queue is taken up most of the heap space. Almost
> all of the the finalizer objects I've seen seem to have a
> jdbc3PreparedStatement object in it. Going through the source code of the
> driver I see that the 'AbstractJdbc2Statement' has a non-trivial finalize
> method. I guess this explains why these objects end up in the finalizer
> queue. Can I clarify the need to having this finalize() method here? It
> seems to be calling the close() method of the statement which I would have
> thought is the responsibility of the client building a Statement object. Is
> there any chance this can be dropped so we don't see these objects ending up
> in the finalizer queue under heavy load and the jvm running out of memory
> before the GC threads gets around to 'actually' reclaim the memory?
>
> Also we are using postgres 9.0.4 and the 8.3-604.jdbc3 version of the
> postgresql jdbc driver.
>
> Cheers
> -- Imran

Re: non-trivial finalize() on AbstractJdbc2Statement

От
Imran
Дата:
Hi Dave

Thanks for your response. I agree that this might not be widespread. And I haven't seen much mentions around this problem (hitting GC issues due to non-trivial finalize() methods) reported (based on my google searches). However, I guess the existence of it does provide the opportunity for this to happen as we've noticed. IMHO, encouraging clients to use the api as recommended (i.e. closing resources once they are done with them) is better than the driver allowing opportunity for bad things to happen. Or perhaps the driver caters to this kind of situation using WeakReference as oppose to using a non-trivial finalize(). 

What are your thoughts?

Cheers
-- Imran  

On Mon, Feb 13, 2012 at 12:09 PM, Dave Cramer <pg@fastcrypt.com> wrote:
Well this is a typical which is worse case scenario. People leaking
resources because they don't explicitly close them, or your case ? I'm
not sure which is worse.

Given that the driver is being used in many very high throughput sites
without this problem, I'm curious as to why nobody else has complained

Dave Cramer

dave.cramer(at)credativ(dot)ca
http://www.credativ.ca



On Fri, Feb 10, 2012 at 12:39 PM, Imran <imranbohoran@gmail.com> wrote:
> Hello
>
> We've been having OOM errors in our applications through GC overhead limits
> under heave load resources running queries. Inspecting the heap dump, it
> appears that the finalizer queue is taken up most of the heap space. Almost
> all of the the finalizer objects I've seen seem to have a
> jdbc3PreparedStatement object in it. Going through the source code of the
> driver I see that the 'AbstractJdbc2Statement' has a non-trivial finalize
> method. I guess this explains why these objects end up in the finalizer
> queue. Can I clarify the need to having this finalize() method here? It
> seems to be calling the close() method of the statement which I would have
> thought is the responsibility of the client building a Statement object. Is
> there any chance this can be dropped so we don't see these objects ending up
> in the finalizer queue under heavy load and the jvm running out of memory
> before the GC threads gets around to 'actually' reclaim the memory?
>
> Also we are using postgres 9.0.4 and the 8.3-604.jdbc3 version of the
> postgresql jdbc driver.
>
> Cheers
> -- Imran

Re: non-trivial finalize() on AbstractJdbc2Statement

От
Vitalii Tymchyshyn
Дата:
Hello.

While it would be better to handle resource closing with reference queues, are you sure your client does not leave resources unclosed? As for me, driver in finalize should do only work not done because of close not have been called correctly.  In other words, your situation may be an indication of close not been called, and so driver does required work in finalize, so saturating finalize thread.

Best regards, Vitalii Tymchyshyn

13.02.12 15:02, Imran написав(ла):
Hi Dave

Thanks for your response. I agree that this might not be widespread. And I haven't seen much mentions around this problem (hitting GC issues due to non-trivial finalize() methods) reported (based on my google searches). However, I guess the existence of it does provide the opportunity for this to happen as we've noticed. IMHO, encouraging clients to use the api as recommended (i.e. closing resources once they are done with them) is better than the driver allowing opportunity for bad things to happen. Or perhaps the driver caters to this kind of situation using WeakReference as oppose to using a non-trivial finalize(). 

What are your thoughts?

Cheers
-- Imran  

On Mon, Feb 13, 2012 at 12:09 PM, Dave Cramer <pg@fastcrypt.com> wrote:
Well this is a typical which is worse case scenario. People leaking
resources because they don't explicitly close them, or your case ? I'm
not sure which is worse.

Given that the driver is being used in many very high throughput sites
without this problem, I'm curious as to why nobody else has complained

Dave Cramer

dave.cramer(at)credativ(dot)ca
http://www.credativ.ca



On Fri, Feb 10, 2012 at 12:39 PM, Imran <imranbohoran@gmail.com> wrote:
> Hello
>
> We've been having OOM errors in our applications through GC overhead limits
> under heave load resources running queries. Inspecting the heap dump, it
> appears that the finalizer queue is taken up most of the heap space. Almost
> all of the the finalizer objects I've seen seem to have a
> jdbc3PreparedStatement object in it. Going through the source code of the
> driver I see that the 'AbstractJdbc2Statement' has a non-trivial finalize
> method. I guess this explains why these objects end up in the finalizer
> queue. Can I clarify the need to having this finalize() method here? It
> seems to be calling the close() method of the statement which I would have
> thought is the responsibility of the client building a Statement object. Is
> there any chance this can be dropped so we don't see these objects ending up
> in the finalizer queue under heavy load and the jvm running out of memory
> before the GC threads gets around to 'actually' reclaim the memory?
>
> Also we are using postgres 9.0.4 and the 8.3-604.jdbc3 version of the
> postgresql jdbc driver.
>
> Cheers
> -- Imran


Re: non-trivial finalize() on AbstractJdbc2Statement

От
Imran
Дата:
Hi Vitalli

Yes my clients are definitely closing the PreparedStatements opened. In fact we are using the hibernate query interface and I've been through the code to make sure the close is been called in a finally block.
I agree that closing work done by the finalizer() method would actually close the resource if its not closed. However the issue I'm raising is that by having the non-trivial finalize() method, it adds every PreparedStatement object created into the finalizer queue. And hence the a GC not reclaiming all memory is should. So before the finalizer thread (which is a low priority thread) gets to it, the application has ran out of memory.

Cheers
-- Imran 

On Mon, Feb 13, 2012 at 1:28 PM, Vitalii Tymchyshyn <tivv00@gmail.com> wrote:
Hello.

While it would be better to handle resource closing with reference queues, are you sure your client does not leave resources unclosed? As for me, driver in finalize should do only work not done because of close not have been called correctly.  In other words, your situation may be an indication of close not been called, and so driver does required work in finalize, so saturating finalize thread.

Best regards, Vitalii Tymchyshyn

13.02.12 15:02, Imran написав(ла):
Hi Dave

Thanks for your response. I agree that this might not be widespread. And I haven't seen much mentions around this problem (hitting GC issues due to non-trivial finalize() methods) reported (based on my google searches). However, I guess the existence of it does provide the opportunity for this to happen as we've noticed. IMHO, encouraging clients to use the api as recommended (i.e. closing resources once they are done with them) is better than the driver allowing opportunity for bad things to happen. Or perhaps the driver caters to this kind of situation using WeakReference as oppose to using a non-trivial finalize(). 

What are your thoughts?

Cheers
-- Imran  

On Mon, Feb 13, 2012 at 12:09 PM, Dave Cramer <pg@fastcrypt.com> wrote:
Well this is a typical which is worse case scenario. People leaking
resources because they don't explicitly close them, or your case ? I'm
not sure which is worse.

Given that the driver is being used in many very high throughput sites
without this problem, I'm curious as to why nobody else has complained

Dave Cramer

dave.cramer(at)credativ(dot)ca
http://www.credativ.ca



On Fri, Feb 10, 2012 at 12:39 PM, Imran <imranbohoran@gmail.com> wrote:
> Hello
>
> We've been having OOM errors in our applications through GC overhead limits
> under heave load resources running queries. Inspecting the heap dump, it
> appears that the finalizer queue is taken up most of the heap space. Almost
> all of the the finalizer objects I've seen seem to have a
> jdbc3PreparedStatement object in it. Going through the source code of the
> driver I see that the 'AbstractJdbc2Statement' has a non-trivial finalize
> method. I guess this explains why these objects end up in the finalizer
> queue. Can I clarify the need to having this finalize() method here? It
> seems to be calling the close() method of the statement which I would have
> thought is the responsibility of the client building a Statement object. Is
> there any chance this can be dropped so we don't see these objects ending up
> in the finalizer queue under heavy load and the jvm running out of memory
> before the GC threads gets around to 'actually' reclaim the memory?
>
> Also we are using postgres 9.0.4 and the 8.3-604.jdbc3 version of the
> postgresql jdbc driver.
>
> Cheers
> -- Imran



Re: non-trivial finalize() on AbstractJdbc2Statement

От
Віталій Тимчишин
Дата:
Hello.

That's rather strange. The whole thing statement does in it's finalize is calling close with 
if (isClosed) return ;
as the code without any synchronization. This should run very fast in all cases.
Are you sure there is no some other object class that is holding finalizer thread busy for long time? This may take not much memory, but prevent statement objects from finalizing. What does jstack says about this thread?
BTW: In my JDK finalizer thread has regular (5) priority.

Best regardsm Vitalii Tymchyshyn.

2012/2/13 Imran <imranbohoran@gmail.com>
Hi Vitalli

Yes my clients are definitely closing the PreparedStatements opened. In fact we are using the hibernate query interface and I've been through the code to make sure the close is been called in a finally block.
I agree that closing work done by the finalizer() method would actually close the resource if its not closed. However the issue I'm raising is that by having the non-trivial finalize() method, it adds every PreparedStatement object created into the finalizer queue. And hence the a GC not reclaiming all memory is should. So before the finalizer thread (which is a low priority thread) gets to it, the application has ran out of memory.

Cheers
-- Imran 


On Mon, Feb 13, 2012 at 1:28 PM, Vitalii Tymchyshyn <tivv00@gmail.com> wrote:
Hello.

While it would be better to handle resource closing with reference queues, are you sure your client does not leave resources unclosed? As for me, driver in finalize should do only work not done because of close not have been called correctly.  In other words, your situation may be an indication of close not been called, and so driver does required work in finalize, so saturating finalize thread.

Best regards, Vitalii Tymchyshyn

13.02.12 15:02, Imran написав(ла):
Hi Dave

Thanks for your response. I agree that this might not be widespread. And I haven't seen much mentions around this problem (hitting GC issues due to non-trivial finalize() methods) reported (based on my google searches). However, I guess the existence of it does provide the opportunity for this to happen as we've noticed. IMHO, encouraging clients to use the api as recommended (i.e. closing resources once they are done with them) is better than the driver allowing opportunity for bad things to happen. Or perhaps the driver caters to this kind of situation using WeakReference as oppose to using a non-trivial finalize(). 

What are your thoughts?

Cheers
-- Imran  

On Mon, Feb 13, 2012 at 12:09 PM, Dave Cramer <pg@fastcrypt.com> wrote:
Well this is a typical which is worse case scenario. People leaking
resources because they don't explicitly close them, or your case ? I'm
not sure which is worse.

Given that the driver is being used in many very high throughput sites
without this problem, I'm curious as to why nobody else has complained

Dave Cramer

dave.cramer(at)credativ(dot)ca
http://www.credativ.ca



On Fri, Feb 10, 2012 at 12:39 PM, Imran <imranbohoran@gmail.com> wrote:
> Hello
>
> We've been having OOM errors in our applications through GC overhead limits
> under heave load resources running queries. Inspecting the heap dump, it
> appears that the finalizer queue is taken up most of the heap space. Almost
> all of the the finalizer objects I've seen seem to have a
> jdbc3PreparedStatement object in it. Going through the source code of the
> driver I see that the 'AbstractJdbc2Statement' has a non-trivial finalize
> method. I guess this explains why these objects end up in the finalizer
> queue. Can I clarify the need to having this finalize() method here? It
> seems to be calling the close() method of the statement which I would have
> thought is the responsibility of the client building a Statement object. Is
> there any chance this can be dropped so we don't see these objects ending up
> in the finalizer queue under heavy load and the jvm running out of memory
> before the GC threads gets around to 'actually' reclaim the memory?
>
> Also we are using postgres 9.0.4 and the 8.3-604.jdbc3 version of the
> postgresql jdbc driver.
>
> Cheers
> -- Imran






--
Best regards,
 Vitalii Tymchyshyn

Re: non-trivial finalize() on AbstractJdbc2Statement

От
Віталій Тимчишин
Дата:
Looking at the code... Can it be because org.postgresql.jdbc2.AbstractJdbc2Statement#isClosed is not volatile? There is no synchronization and finalizer thread may simply not see statement was just closed by another thread.

Best regards, Vitalii Tymchyshyn

2012/2/13 Imran <imranbohoran@gmail.com>
Hi Vitalli

Yes my clients are definitely closing the PreparedStatements opened. In fact we are using the hibernate query interface and I've been through the code to make sure the close is been called in a finally block.
I agree that closing work done by the finalizer() method would actually close the resource if its not closed. However the issue I'm raising is that by having the non-trivial finalize() method, it adds every PreparedStatement object created into the finalizer queue. And hence the a GC not reclaiming all memory is should. So before the finalizer thread (which is a low priority thread) gets to it, the application has ran out of memory.

Cheers
-- Imran 


On Mon, Feb 13, 2012 at 1:28 PM, Vitalii Tymchyshyn <tivv00@gmail.com> wrote:
Hello.

While it would be better to handle resource closing with reference queues, are you sure your client does not leave resources unclosed? As for me, driver in finalize should do only work not done because of close not have been called correctly.  In other words, your situation may be an indication of close not been called, and so driver does required work in finalize, so saturating finalize thread.

Best regards, Vitalii Tymchyshyn

13.02.12 15:02, Imran написав(ла):
Hi Dave

Thanks for your response. I agree that this might not be widespread. And I haven't seen much mentions around this problem (hitting GC issues due to non-trivial finalize() methods) reported (based on my google searches). However, I guess the existence of it does provide the opportunity for this to happen as we've noticed. IMHO, encouraging clients to use the api as recommended (i.e. closing resources once they are done with them) is better than the driver allowing opportunity for bad things to happen. Or perhaps the driver caters to this kind of situation using WeakReference as oppose to using a non-trivial finalize(). 

What are your thoughts?

Cheers
-- Imran  

On Mon, Feb 13, 2012 at 12:09 PM, Dave Cramer <pg@fastcrypt.com> wrote:
Well this is a typical which is worse case scenario. People leaking
resources because they don't explicitly close them, or your case ? I'm
not sure which is worse.

Given that the driver is being used in many very high throughput sites
without this problem, I'm curious as to why nobody else has complained

Dave Cramer

dave.cramer(at)credativ(dot)ca
http://www.credativ.ca



On Fri, Feb 10, 2012 at 12:39 PM, Imran <imranbohoran@gmail.com> wrote:
> Hello
>
> We've been having OOM errors in our applications through GC overhead limits
> under heave load resources running queries. Inspecting the heap dump, it
> appears that the finalizer queue is taken up most of the heap space. Almost
> all of the the finalizer objects I've seen seem to have a
> jdbc3PreparedStatement object in it. Going through the source code of the
> driver I see that the 'AbstractJdbc2Statement' has a non-trivial finalize
> method. I guess this explains why these objects end up in the finalizer
> queue. Can I clarify the need to having this finalize() method here? It
> seems to be calling the close() method of the statement which I would have
> thought is the responsibility of the client building a Statement object. Is
> there any chance this can be dropped so we don't see these objects ending up
> in the finalizer queue under heavy load and the jvm running out of memory
> before the GC threads gets around to 'actually' reclaim the memory?
>
> Also we are using postgres 9.0.4 and the 8.3-604.jdbc3 version of the
> postgresql jdbc driver.
>
> Cheers
> -- Imran






--
Best regards,
 Vitalii Tymchyshyn

Re: non-trivial finalize() on AbstractJdbc2Statement

От
"Kevin Grittner"
Дата:
******* ********<tivv00@gmail.com> wrote:
> Looking at the code... Can it be because
> org.postgresql.jdbc2.AbstractJdbc2Statement#isClosed is not
> volatile? There is no synchronization and finalizer thread may
> simply not see statement was just closed by another thread.

That sounds likely enough to me.  I don't know whether declaring the
flag volatile would be enough, but it needs either that or access
only through synchronized blocks.

In addition, I would recommend something like the attached to make
the code more bullet-proof.

-Kevin


Вложения

Re: non-trivial finalize() on AbstractJdbc2Statement

От
Imran
Дата:
Hi Guys

I dont think I'm referring to the speed or workings of the finalize() method available on AbstractJdbc2Statement. As said earlier I agree that it should return quickly if statements are closed by clients and also having safeguards around it looks nice. But my point is that by having a non-trivial finalize() an extra JdbcxStatement object is been created and referenced through a Finalizer, which is in a reference queue that would be picked up by the Finalizer thread. And a GC wouldn't reclaim the memory until the finalizer thread has done its work. As we have many queries executing, the main thread keeps filling this queue at a much faster rate than the finalizer thread (which is a low priority thread by default) would get to it. Under heavy load this paves the way for possible OOM issues as we've noticed. Also just to check this, we've patched up the driver we have without the finalize() method and we've seen much better GC and have not experienced OOM on similar load that resulted in OOMs. 

The general feeling as I've learned over the years is that finalize() should be used cautiously. So I was wondering if its really required for the AbstractJdbc2Statement to have a finalize() that only closes the statement, which one would expect the client to do anyway.

Cheers
-- Imran

On Mon, Feb 13, 2012 at 4:49 PM, Kevin Grittner <Kevin.Grittner@wicourts.gov> wrote:
******* ********<tivv00@gmail.com> wrote:
> Looking at the code... Can it be because
> org.postgresql.jdbc2.AbstractJdbc2Statement#isClosed is not
> volatile? There is no synchronization and finalizer thread may
> simply not see statement was just closed by another thread.

That sounds likely enough to me.  I don't know whether declaring the
flag volatile would be enough, but it needs either that or access
only through synchronized blocks.

In addition, I would recommend something like the attached to make
the code more bullet-proof.

-Kevin


Re: non-trivial finalize() on AbstractJdbc2Statement

От
Vitalii Tymchyshyn
Дата:
Hello.

The finalizer thread is not a low priority thread in my JVM (openjdk) and as soon as Statement.close does nothing (and it does nothing if statement is closed), I don't see how can it be a problem to free memory. Actually statement creation is much more heavy thing than "if (flag) return". It's perfectly valid to close native resource (and as far as I know statement allocates server-side native resources) in finalizer. Another implementation can be to create a ReferenceQueue and a bunch of References that should be checked now and then during connection calls, but this introduces additional processing that is not needed most time. You can't drop this code altogether as while it's good practice to close statements in client code, you can't guarantee it's done everywhere. Actually it's common practice in java to clean-up external resources in finalize, see for example FileOutputStream.
As of your problem, I don't thing statement finalize method is the problem cause. I can see two causes:
1) The code bug mentioned in this thread
2) Some another class with long finalize method. This is the case that can lead to confusion. Say, you have an object created once in 5 minutes that has 3 minutes finalize. It won't hurt by itself as it's enough time to be finalized. But as soon as you have additional object with finalized method defined (say, Statement), even empty, all this objects can't be freed during this 3 minutes run and you will get OOM. And you will rarely blame your custom object. The best check that can be done to show real reason is to check Finalizer object stack with jstack. I did often see cases when custom finalize method is fast, but is synchronized by some heavy-used  resource.

Best regards, Vitalii Tymchyshyn


15.02.12 13:11, Imran написав(ла):
Hi Guys

I dont think I'm referring to the speed or workings of the finalize() method available on AbstractJdbc2Statement. As said earlier I agree that it should return quickly if statements are closed by clients and also having safeguards around it looks nice. But my point is that by having a non-trivial finalize() an extra JdbcxStatement object is been created and referenced through a Finalizer, which is in a reference queue that would be picked up by the Finalizer thread. And a GC wouldn't reclaim the memory until the finalizer thread has done its work. As we have many queries executing, the main thread keeps filling this queue at a much faster rate than the finalizer thread (which is a low priority thread by default) would get to it. Under heavy load this paves the way for possible OOM issues as we've noticed. Also just to check this, we've patched up the driver we have without the finalize() method and we've seen much better GC and have not experienced OOM on similar load that resulted in OOMs. 

The general feeling as I've learned over the years is that finalize() should be used cautiously. So I was wondering if its really required for the AbstractJdbc2Statement to have a finalize() that only closes the statement, which one would expect the client to do anyway.

Cheers
-- Imran

On Mon, Feb 13, 2012 at 4:49 PM, Kevin Grittner <Kevin.Grittner@wicourts.gov> wrote:
******* ********<tivv00@gmail.com> wrote:
> Looking at the code... Can it be because
> org.postgresql.jdbc2.AbstractJdbc2Statement#isClosed is not
> volatile? There is no synchronization and finalizer thread may
> simply not see statement was just closed by another thread.

That sounds likely enough to me.  I don't know whether declaring the
flag volatile would be enough, but it needs either that or access
only through synchronized blocks.

In addition, I would recommend something like the attached to make
the code more bullet-proof.

-Kevin



Re: non-trivial finalize() on AbstractJdbc2Statement

От
Dave Cramer
Дата:
On Wed, Feb 15, 2012 at 6:30 AM, Vitalii Tymchyshyn <tivv00@gmail.com> wrote:
> Hello.
>
> The finalizer thread is not a low priority thread in my JVM (openjdk) and as
> soon as Statement.close does nothing (and it does nothing if statement is
> closed), I don't see how can it be a problem to free memory. Actually
> statement creation is much more heavy thing than "if (flag) return". It's
> perfectly valid to close native resource (and as far as I know statement
> allocates server-side native resources) in finalizer. Another implementation
> can be to create a ReferenceQueue and a bunch of References that should be
> checked now and then during connection calls, but this introduces additional
> processing that is not needed most time. You can't drop this code altogether
> as while it's good practice to close statements in client code, you can't
> guarantee it's done everywhere. Actually it's common practice in java to
> clean-up external resources in finalize, see for example FileOutputStream.
> As of your problem, I don't thing statement finalize method is the problem
> cause. I can see two causes:
> 1) The code bug mentioned in this thread
> 2) Some another class with long finalize method. This is the case that can
> lead to confusion. Say, you have an object created once in 5 minutes that
> has 3 minutes finalize. It won't hurt by itself as it's enough time to be
> finalized. But as soon as you have additional object with finalized method
> defined (say, Statement), even empty, all this objects can't be freed during
> this 3 minutes run and you will get OOM. And you will rarely blame your
> custom object. The best check that can be done to show real reason is to
> check Finalizer object stack with jstack. I did often see cases when custom
> finalize method is fast, but is synchronized by some heavy-used  resource.
>
> Best regards, Vitalii Tymchyshyn


Just for kicks why don't you remove the finalize method recompile the
JDBC jar and try it.


Dave Cramer

dave.cramer(at)credativ(dot)ca
http://www.credativ.ca

Re: non-trivial finalize() on AbstractJdbc2Statement

От
Imran
Дата:
@Vitalli - w.r.t Thread priority, I've tried to get the priority off the jvm I'm running, but the thread dump nor jconsole/jvisualvm is giving this out to me. We run 1.6.0_12 on a 64bit linux platform. jvisualvm however shows that the Running percentage of the Finalizer thread is comparatively low. To my knowledge Finalizer thread is low by default, and looking at the Finalizer code, it does appear to be setting the priority to MAX_PRIORITY - 2.
Anyways that aside, heap dumps I've collected when we had OOMs have pointed at high Finalizer objects and the referent of those have been jdbc3Satement objects, which is why I raised this question. I'm not sure if its common practice to always use finalize() for any mop-up tasks, as I've seen other cautions raised around it, although I can see there are valid cases to do so.

@Dave - I have done this and as mentioned in the previous post, I haven't run into the OOM issues under similar load.

Cheers
-- Imran

On Wed, Feb 15, 2012 at 11:42 AM, Dave Cramer <pg@fastcrypt.com> wrote:
On Wed, Feb 15, 2012 at 6:30 AM, Vitalii Tymchyshyn <tivv00@gmail.com> wrote:
> Hello.
>
> The finalizer thread is not a low priority thread in my JVM (openjdk) and as
> soon as Statement.close does nothing (and it does nothing if statement is
> closed), I don't see how can it be a problem to free memory. Actually
> statement creation is much more heavy thing than "if (flag) return". It's
> perfectly valid to close native resource (and as far as I know statement
> allocates server-side native resources) in finalizer. Another implementation
> can be to create a ReferenceQueue and a bunch of References that should be
> checked now and then during connection calls, but this introduces additional
> processing that is not needed most time. You can't drop this code altogether
> as while it's good practice to close statements in client code, you can't
> guarantee it's done everywhere. Actually it's common practice in java to
> clean-up external resources in finalize, see for example FileOutputStream.
> As of your problem, I don't thing statement finalize method is the problem
> cause. I can see two causes:
> 1) The code bug mentioned in this thread
> 2) Some another class with long finalize method. This is the case that can
> lead to confusion. Say, you have an object created once in 5 minutes that
> has 3 minutes finalize. It won't hurt by itself as it's enough time to be
> finalized. But as soon as you have additional object with finalized method
> defined (say, Statement), even empty, all this objects can't be freed during
> this 3 minutes run and you will get OOM. And you will rarely blame your
> custom object. The best check that can be done to show real reason is to
> check Finalizer object stack with jstack. I did often see cases when custom
> finalize method is fast, but is synchronized by some heavy-used  resource.
>
> Best regards, Vitalii Tymchyshyn


Just for kicks why don't you remove the finalize method recompile the
JDBC jar and try it.


Dave Cramer

dave.cramer(at)credativ(dot)ca
http://www.credativ.ca

Re: non-trivial finalize() on AbstractJdbc2Statement

От
Vitalii Tymchyshyn
Дата:
15.02.12 14:30, Imran написав(ла):
> @Vitalli - w.r.t Thread priority, I've tried to get the priority off
> the jvm I'm running, but the thread dump nor jconsole/jvisualvm is
> giving this out to me. We run 1.6.0_12 on a 64bit linux platform.
> jvisualvm however shows that the Running percentage of the Finalizer
> thread is comparatively low. To my knowledge Finalizer thread is low
> by default, and looking at the Finalizer code, it does appear to be
> setting the priority to MAX_PRIORITY - 2.
> Anyways that aside, heap dumps I've collected when we had OOMs have
> pointed at high Finalizer objects and the referent of those have been
> jdbc3Satement objects, which is why I raised this question. I'm not
> sure if its common practice to always use finalize() for any mop-up
> tasks, as I've seen other cautions raised around it, although I can
> see there are valid cases to do so.
jstack shows you thread priorities.
For me:
Regular thread:
"Thread-69" daemon prio=10 tid=0x000000004683e800 nid=0x6834 waiting on
condition [0x00007f80a7649000]
Finalizer:
"Finalizer" daemon prio=10 tid=0x00007f80c4001000 nid=0x6d35 in
Object.wait() [0x00007f80c9747000]

So, priorities are equal.
Regarding heap sizes, that's what I am talking about! If someone holds
Finalizer thread, especially in some blocking state (say synchronized)
you will get OOM with a lot of objects that are created much, not ones
that really holds the thread! That's why it's Running is low - someone
it blocking on something in this thread. Otherwise if it has work, it
would be in running state, no matter is OS've given it CPU time. Check
it with jstack. You can do it even now, while you don't have OOMs you
should still have the problem root - someone who is sitting in the
finalizer doing it's work slow. You may even still have some leak, yet
now while you have much less finalizable objects, the leak is much less
visible. Note that you may not see it at single call if your cause does
not take 100% of Finalizer thread time.

BTW: You can try to find the object being finalized from heap dump,
check all objects visible from finalizer thread.

Best regards, Vitalii Tymchyshyn


Re: non-trivial finalize() on AbstractJdbc2Statement

От
Imran
Дата:

So I've tried to run jstack over five times and it kept in saying it can't walk over the threads. We have a fair amount of background processes running, not sure if that made jstack fail. I've read that its possible to hit the error on jstack. My thread dumps from jvisualvm doesn't show the priority of any threads. Also the only thing the tread dumps have shown to me is that its waiting on RefernceQueue.remove, which holds the Finalizer objects that gets created due to finalize methods.

I did go through most of the finalizer objects in my heap dumps and all had referents as the jsbc3PreparedStatement. Also with my patched driver I've noticed every time I force a GC I see the old generation cleaning up nicely, which I didn't see when I had the driver with the finalize method.

Cheers
--Imran

On Feb 15, 2012 12:50 PM, "Vitalii Tymchyshyn" <tivv00@gmail.com> wrote:
15.02.12 14:30, Imran написав(ла):
@Vitalli - w.r.t Thread priority, I've tried to get the priority off the jvm I'm running, but the thread dump nor jconsole/jvisualvm is giving this out to me. We run 1.6.0_12 on a 64bit linux platform. jvisualvm however shows that the Running percentage of the Finalizer thread is comparatively low. To my knowledge Finalizer thread is low by default, and looking at the Finalizer code, it does appear to be setting the priority to MAX_PRIORITY - 2.
Anyways that aside, heap dumps I've collected when we had OOMs have pointed at high Finalizer objects and the referent of those have been jdbc3Satement objects, which is why I raised this question. I'm not sure if its common practice to always use finalize() for any mop-up tasks, as I've seen other cautions raised around it, although I can see there are valid cases to do so.
jstack shows you thread priorities.
For me:
Regular thread:
"Thread-69" daemon prio=10 tid=0x000000004683e800 nid=0x6834 waiting on condition [0x00007f80a7649000]
Finalizer:
"Finalizer" daemon prio=10 tid=0x00007f80c4001000 nid=0x6d35 in Object.wait() [0x00007f80c9747000]

So, priorities are equal.
Regarding heap sizes, that's what I am talking about! If someone holds Finalizer thread, especially in some blocking state (say synchronized) you will get OOM with a lot of objects that are created much, not ones that really holds the thread! That's why it's Running is low - someone it blocking on something in this thread. Otherwise if it has work, it would be in running state, no matter is OS've given it CPU time. Check it with jstack. You can do it even now, while you don't have OOMs you should still have the problem root - someone who is sitting in the finalizer doing it's work slow. You may even still have some leak, yet now while you have much less finalizable objects, the leak is much less visible. Note that you may not see it at single call if your cause does not take 100% of Finalizer thread time.

BTW: You can try to find the object being finalized from heap dump, check all objects visible from finalizer thread.

Best regards, Vitalii Tymchyshyn

Re: non-trivial finalize() on AbstractJdbc2Statement

От
Віталій Тимчишин
Дата:


2012/2/15 Imran <imranbohoran@gmail.com>

So I've tried to run jstack over five times and it kept in saying it can't walk over the threads. We have a fair amount of background processes running, not sure if that made jstack fail. I've read that its possible to hit the error on jstack. My thread dumps from jvisualvm doesn't show the priority of any threads.

I have visualvm 1.3. I can select application in the list -> popup menu with RMB -> thread dump. Another option is to click Thread Dump button in Threads tab of application open. This should open new tab with textual thread dump, pretty similar to jstack one. 

Also the only thing the tread dumps have shown to me is that its waiting on RefernceQueue.remove, which holds the Finalizer objects that gets created due to finalize methods.

This means that ReferenceQueue is empty. If you wish to dig deeper you need to check same thing with unpatched driver.
Another option is to load OOM heap dump with visual vm, then click "Show threads" in the Summary, then check for Finalizer thread. If it could not keep up, you should see exact object that caused problems.
--
Best regards,
 Vitalii Tymchyshyn

Re: non-trivial finalize() on AbstractJdbc2Statement

От
Imran
Дата:
Yes, that's how I got my thread dump. But the that doesn't give me the priority. This is not the openJDK, so that's probably the difference that's making you see a priority and me not seeing one (I've seen discussions around not being able to get thread priority from ThreadInfo in a plugin for jonsole that shows the topthreads).


My heap dumps are over 7GB and they crash jvisualvm if I try to open them. I've used YourKit to inspect these dumps and that's how I've looked the Finalizer objecets where I saw the jdbc3Statement being referenced.

Cheers
-- Imran

2012/2/15 Віталій Тимчишин <tivv00@gmail.com>


2012/2/15 Imran <imranbohoran@gmail.com>

So I've tried to run jstack over five times and it kept in saying it can't walk over the threads. We have a fair amount of background processes running, not sure if that made jstack fail. I've read that its possible to hit the error on jstack. My thread dumps from jvisualvm doesn't show the priority of any threads.

I have visualvm 1.3. I can select application in the list -> popup menu with RMB -> thread dump. Another option is to click Thread Dump button in Threads tab of application open. This should open new tab with textual thread dump, pretty similar to jstack one. 

Also the only thing the tread dumps have shown to me is that its waiting on RefernceQueue.remove, which holds the Finalizer objects that gets created due to finalize methods.

This means that ReferenceQueue is empty. If you wish to dig deeper you need to check same thing with unpatched driver.
Another option is to load OOM heap dump with visual vm, then click "Show threads" in the Summary, then check for Finalizer thread. If it could not keep up, you should see exact object that caused problems.
--
Best regards,
 Vitalii Tymchyshyn