>Are you forcing a full GC or just a small one? Depending on a /lot/ of
>things, those objects might not be freed until a full GC runs.

  I'm not sure. Either NetBeans profiler uses. I think it's just a "small" one, 
because sometimes when I click on it several times, it frees up a little 
memory...

>Every request will eat up memory, but /should/ eventually be freed. Does
>your "simple" page have any filters operating on it?

No. There are only struts <html:...> tags and some other <bean:...> tags. There 
are no scriptlets on it.

>When you say the profile claims that memory is eaten up in the
>InflaterInputStream constructor, I assume you mean that the memory is
>allocated in that method. It looks like the default byte buffer length
>is 512 bytes (in my Sun 1.5 source). How big are your byte arrays that
>seem to be piling up?

Yes, it's allocated in that method. Well, since my last post I kept on testing 
other pages and discovered that char[] and byte[] objects are piled up by other 
methods as well. InflaterInputStream is there, however it doesn't allocate as 
much memory than others do now.
Here you can see 2 screenshots of my profiler. the first one is a "memory 
snapshot" and the other is an "allocation stack traces" window.
Now it seems that (among others) java.util.Arrays.copyOfRange eats up lots of 
memory. This might be caused by me not properly using my database connection 
pool, so here's how I use and probably everything gets clear...
Here are two screenshots of my profiler and please keep on reading to see what 
I realized:

http://www.inf.u-szeged.hu/~michnay/profiler/

1) Every time I'd like to connect to my db, I use the java code posted 
everywhere, but since I want to store more than 1 row of the resultset, I 
declare an ArrayList. Probably this shouldn't be done this way, because memory 
is eaten up by array operations...
Here's my code:

-----------------------------
public class LoginHelper {
    
    private  ArrayList   ID_klinikak = null;
    private  ArrayList   nev_klinikak = null;

    /** Creates a new instance of LoginHelper */
        public LoginHelper() {
    }

     public void klinikakatListaz() {
        
        this.ID_klinikak = new ArrayList();
        this.nev_klinikak = new ArrayList();
        
        Connection conn = null;
        Statement stmt = null;  // Or PreparedStatement if needed
        ResultSet rst = null;
        
        try{
            
            Context ctx = new InitialContext();
            if(ctx == null )
                throw new Exception("Boom - No Context");
            
            Context envCtx = (Context) ctx.lookup("java:comp/env");
            DataSource ds = (DataSource) envCtx.lookup("jdbc/akr_db");
            
            if (ds != null) {
                conn = ds.getConnection();
                
                if(conn != null)  {
                    
                    stmt = conn.createStatement();
                    rst =stmt.executeQuery("SELECT ID_klinika, nev FROM 
torzs_klinika");
                    while (rst.next()) {
                        // Get the data from the row using the column name
                        
this.getID_klinikak().add(rst.getString("ID_klinika").toString());
                        
this.getNev_klinikak().add(rst.getString("nev").toString());
                    }
                    stmt.close();
                    stmt = null;
                    
                    conn.close();
                    conn = null;
                    
                    rst.close();
                    rst = null;
                }
            }
        }catch(Exception e) {
            e.printStackTrace();
        } finally {
            // Always make sure result sets and statements are closed,
            // and the connection is returned to the pool
            if (rst != null) {
                try { rst.close(); } catch (SQLException e) { ; }
                rst = null;
            }
            if (stmt != null) {
                try { stmt.close(); } catch (SQLException e) { ; }
                stmt = null;
            }
            if (conn != null) {
                try { conn.close(); } catch (SQLException e) { ; }
                conn = null;
            }
        }
    }
    
    // ***Now come some getter methods...***
}
-----------------------------

So you can see that I have an instance variable that I only instantiate inside 
this specific method so instantiating this class will not result in creating 
the ArrayLists themselves.

>From my JSP I instantiate this class and call the method and iterate the 
>instance variables (ArrayLists):

------------------------------
<%
      db_helpers.LoginHelper login = new db_helpers.LoginHelper();
      login.klinikakatListaz();
                                            
      Iterator ID_klinikak = login.getID_klinikak().iterator();                 
                           
      Iterator nev_klinikak = login.getNev_klinikak().iterator();               
                             
                                            
      while ( ID_klinikak.hasNext() ) {
      %>
      <html:option 
value="<%=ID_klinikak.next().toString()%>"><%=nev_klinikak.next().toString()%></html:option>
      <%
      }
%>
------------------------------

It this the right way to use my connection pool? If not, this might be the 
reason of my memory leaks, because some objects may not be able to be 
freed-up...

>When you say the profile claims that memory is eaten up in the
>InflaterInputStream constructor, I assume you mean that the memory is
>allocated in that method. It looks like the default byte buffer length
>is 512 bytes (in my Sun 1.5 source). How big are your byte arrays that
>seem to be piling up?

It's now nothing compared to those allocated by java.util.Arrays.copyOfRange 
method...
Each request (a reload) causes a memory allocation of another 1-3 Mbytes that 
the profiler gc() won't free up.

>I would bet that InflaterInputStream is responsible for eating up a
>chunk of memory due to class loading. Does the number of byte[] objects
>created by InflaterInputStream increase whenever you reload that page?
>Or are other objects increasing in size and/or count?

Yes, it's increased on each reload and yes, there are some increasing char[] 
objects as well. (Take a look at the pictures found on the URL I posted...)

>Does your profiler confirm that all the byte[] objects are coming from
>InflaterInputStream, or does it list them separately and you browsed a
>few of them and say that they were all from that method?

No, not all, but most of them were allocated by InflaterInputStream. (Now it's 
other methods causing the same thing...)

>The reason I'm asking all of these seemingly stupid questions is that,
>with many Struts users out there, and such a simple problem, either
>everyone has this problem and Struts is untenable (which is clearly not
>true), or something is unique about your environment, or you are
>misinterpreting your data.

No, I'm pretty sure that it's me not working properly, not Struts :) That's why 
I posted the way I'm using my connection pool and other codes as well, so that 
you can point out what I'm (not struts) doing wrong...

>What JVM, app server, etc. versions are you using?

I have the latest Java installed (Version 6 Update 1).

Any hey, thanks so much for taking a look at my code, and helping at all, I 
appreciate it.

Regards,

  BM

----- Original Message ----
From: Christopher Schultz <[EMAIL PROTECTED]>
To: Struts Users Mailing List <user@struts.apache.org>
Sent: Wednesday, May 23, 2007 2:53:44 PM
Subject: Re: Serious memory leak

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Balazs,

Balazs Michnay wrote:
>> Are you sure they cannot be garbage-collected? How do you know?
> 
> The profiler can perform garbage-collection at any time I press a
> button. After pressing this, no memory is freed-up  :(

Are you forcing a full GC or just a small one? Depending on a /lot/ of
things, those objects might not be freed until a full GC runs.

>> Usually, JAR files are read to load class files. When class files
>> are read, their code needs to be read into memory (in byte arrays).
>> It also need to stay in memory in order to be executed. It's true,
>> class loading uses memory ;)
> 
> But does it load the classes each time I reload the page?

Probably not.

> Because
> (just for testing) I have a simple, static page with only struts
> <html:...> tags on it and pressing the reload button eats up some
> more memory.

Every request to the server creates many objects: request, response,
extras for any wrappers that are created going through filters, etc.
event objects fired for any session activity, maps of request parameters
(whose Strings contain lots of byte[] objects), and on and on.

Every request will eat up memory, but /should/ eventually be freed. Does
your "simple" page have any filters operating on it? How about session
interaction?

>>> After browsing through about 80-100 pages I get an OutOfMemory 
>>> error...
> 
>> Are you sure these facts are related? Class loading almost never
>> causes a problem unless you are loading millions of classes.
> 
> Well, I'm not sure, but since my page has "nothing" on it, I don't
> know what else may cause such thing... and again, it's the profiler
> that says memory is eaten up by the constructor of
> InflaterInputStream class.

So your testing strategy looks something like this:

1. Start up app server + attach profiler
2. Wait for app server to be ready for requests
3. Request simple page
4. Go to step #3 until OOM

Is that accurate? And nobody else is using your server at the same time,
right?

When you say the profile claims that memory is eaten up in the
InflaterInputStream constructor, I assume you mean that the memory is
allocated in that method. It looks like the default byte buffer length
is 512 bytes (in my Sun 1.5 source). How big are your byte arrays that
seem to be piling up?

I would bet that InflaterInputStream is responsible for eating up a
chunk of memory due to class loading. Does the number of byte[] objects
created by InflaterInputStream increase whenever you reload that page?
Or are other objects increasing in size and/or count?

Does your profiler confirm that all the byte[] objects are coming from
InflaterInputStream, or does it list them separately and you browsed a
few of them and say that they were all from that method?

The reason I'm asking all of these seemingly stupid questions is that,
with many Struts users out there, and such a simple problem, either
everyone has this problem and Struts is untenable (which is clearly not
true), or something is unique about your environment, or you are
misinterpreting your data.

What JVM, app server, etc. versions are you using?

Finally, can you post the code to your "simple" page that can be
observed to eat up memory?

- -chris

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFGVDlY9CaO5/Lv0PARAus4AJ9x9vs/Rs8sK2SfOJ99Xn/hH0lnegCePmKU
gPOCQmdQ02HzxCmL0L4xen4=
=J13G
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]








       
____________________________________________________________________________________Looking
 for a deal? Find great prices on flights and hotels with Yahoo! FareChase.
http://farechase.yahoo.com/

Reply via email to