Solved

How to Disable JSP caching on Tomcat 5.5.25

Posted on 2008-06-19
17
6,852 Views
Last Modified: 2008-06-24
Hi,

I'm currently working on a project involving JSP documents being served from an Apache Tomcat 2.2.25 server. The application and the pages are served out without any issues but I noticed that memory usage is rapidly being consumed by the tomcat5.exe process after page requests.

Each request results in a dynamically generated JSP file. I've been reading around the various forums and gather that for each new JSP that is served out - Tomcat automcatically converts the JSP to a in-memory servlet the first time someone tries to access the page's content.

As such, I find that with each new page that is generated, it constantly consumes memory. Is there a way to disable this caching of the JSP page or prevent the converting into in-memory servlet?

Many Thanks in advance


0
Comment
Question by:mikesung99
  • 6
  • 6
  • 5
17 Comments
 
LVL 19

Expert Comment

by:Kuldeepchaturvedi
ID: 21826740
for each JSP tomcat does convert it to a servlet for a first time use ( jsp compile).. BUT it does not keep it in memory...
your memory uses are going high because of something else..
0
 

Author Comment

by:mikesung99
ID: 21831075
Hi,

Thanks for your reponse - Just to explain exactly how I've coded the application to work - I'm using the JSP in conjunction with VXML code which ultimately directs

to a Java class which then produces a new JSP/VXML file. The Java class then directs to the page that's been produced:-

i.e.:-

                getServletConfig().getServletContext().getRequestDispatcher(sDecrptFile).forward(request, response);

(Where sDEcrpyt file is the name of the Newly produced JSP file)


It seems that the Memory usage grows as this process is repeat for subsequent new JSP page productions.

In investigating this, I hardcoded the JSP pages and made the code (still using  getServletConfig().getServletContext().getRequestDispatcher) to re-direct to the

pages and noticed that the memory usage in doing this remains fairly stable. Seconldy, I kept in the code which produces New JSp pages but I do not re-direct to

the newly prodcued page but just to one of the hardcoded ones and in doing this the memory usage still remain stable and did not grow rapidly.

It is only when I re-direct to the newly produced page that it causes the high memory usage. That is why that based on these tests, I thought that in directing to

the newly created JSP page, it caches the page in memory somehow.

Do you have any leads as to what may be causing the high memory usage when I re-direct to a new JSP page?


Many Thanks
0
 
LVL 19

Expert Comment

by:Kuldeepchaturvedi
ID: 21832321
>>>>
In investigating this, I hardcoded the JSP pages and made the code (still using  getServletConfig().getServletContext().getRequestDispatcher) to re-direct to the

pages and noticed that the memory usage in doing this remains fairly stable. Seconldy, I kept in the code which produces New JSp pages but I do not re-direct to

the newly prodcued page but just to one of the hardcoded ones and in doing this the memory usage still remain stable and did not grow rapidly.
>>>>
This is interesting. I would have thought that the in second case where you are generating the jsp pages, your memory uses should have gone higher..

Does this name of dcrypted jsp changes everytime? i.e. user A requests a Page, and then user B requests the same Page.. does your dcrypt variable gets two different values?
if yes, you may want to change it to be same. ( will save time and memory in generating the same page twice).

also instead of doing
getServletConfig().getServletContext().getRequestDispatcher(sDecrptFile).forward(request, response);

do
ctx.getRequestDispatcher(sDecrptFile).forward(request, response);

where ctx = getServletConfig().getServletContext(); ( this is done in the init method of your servlet once).
it saves multiple object creation where only one is needed.

0
 
LVL 27

Expert Comment

by:rrz
ID: 21837024
You should show us more of your code.   I am thinking like Kuldeep ( I hope I understand him)
>will save time and memory in generating the same page twice    
In other words I think that instead of
>How to Disable JSP caching on Tomcat 5.5.25  
you should be *enabling* caching.  If I am thinking correctly, then the problem your having  
>It is only when I re-direct to the newly produced page that it causes the high memory usage  
is because you are dynamically producing the pages every time that they are requested.  A "cache Filter" might be what you need if the generated content of your JSP is the same on multiple requests.   But if the generated content is different for each request then this technique will not help.   I hope I am not confusing the issue here.
0
 

Author Comment

by:mikesung99
ID: 21839262
Hi,

Thanks for the responses so far. Here's some more detail around the Java class functionality which is used to generate the dynamica JSP/VXMl pages:-

I have a variety of files which are encrypted JSP pages (in that the content of each JSP page has been encrypted). The java class contains a routine which decrypts the contents of the specific encrypted JSP page and saves the contents in a temporary file. The temporary file's name is generated by the following code:-

                HttpSession session = request.getSession(true);

            //Create unique filename for the temporary file....
                Date file_date = new Date(session.getLastAccessedTime());
                SimpleDateFormat format = new SimpleDateFormat("HHmmssSSS");
                String fordate = format.format(file_date);
                sDecrptFile = session.getId() + fordate + ".jsp";

                String sFileOutput = sJSPFilesFullLocation + sDecrptFile;
               
When the JSP page has been loaded, the temporary file is deleted. This process is repeated for each JSP page that is required.

In effect, when the class navigates to the next JSP page, it is always a newly produced JSP file (with a dymanically generated file name each time) and this seems to cause the high memory usage issue. However, from the class if I just navigate to an existing JSP page (i.e. the page has already been accessed before) then the memory usage is stable.

In this case would a cache filter be of any benefit? Essentially, the content that is decrpyted may have previoulsy been decytped before - is there any way for Tomcat to detect this? In my code, I tried using:-

      response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
      response.setHeader("Pragma","no-cache"); //HTTP 1.0
      response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
      
but this doesn't seem to make much difference. Also in my code, I tried to invoke the Garbage collection explicitly:-

      Runtime r = Runtime.getRuntime();
        r.gc();
       
but again, this doesn't seem to help much


Thanks
0
 
LVL 27

Expert Comment

by:rrz
ID: 21839542
Why are the JSP files encrypted ?  Are you protecting them from being viewed by someone at the server that has access to your filesystem ?    Or would it be sufficient for you to use password protection for each sensitive page ?
>Each request results in a dynamically generated JSP file.    
Is the resulting content unique ? To each user or some other condition ?  
>When the JSP page has been loaded, the temporary file is deleted.  
Loaded where ?  Do you mean after it is sent to the user that requested it ? Why is the file deleted ? For security ?
>response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
These headers direct the browser not to store the page on the client's machine.  This caching  is different from what we were discussing previously. Before we talking about caching the output of a JSP on the server. It could be saved for subsequent requests for the same page. But maybe that would be againest your security concerns. Is it ?
>Essentially, the content that is decrpyted may have previoulsy been decytped before - is there any way for Tomcat to detect this?    
I  would say yes, but I need to understand your web app better to suggest a way to implement it. Meanwhile look at the way the Filter detects file changes in this link
http://www.onjava.com/pub/a/onjava/2003/11/19/filters.html?page=3    
If you decide that you want to use a caching FIlter, then we will help you with the coding.
0
 

Author Comment

by:mikesung99
ID: 21840278
The JSP files are enrypted as there is a requirement to protect the code from being viewed by users who have access to the server, so that's why the enrcryption/decryption logic has been implemented.

I may have confused matters by stating that each request results in a dynamically generated JSP page - what I mean is that after the Class logic decrypts the specific encrypted JSP page it outputs the un-encrypted content to a text file with a unique name generated by a combination of the session ID and the current time. AS such the content isn't unique - it's just that it's ben decrypted and outputted to a temporary file.

The temporary JSP file is deleted after a user has requested the page and this is again for security. Saving the output of the JSP page on the server would also be against the security requirements. I've attached extracts from the Java class that I've implemented to help illustrate how I've coded the logic.

Thanks
public class LogVFormsProcessor extends HttpServlet

{

	......
 

	public void doGet(HttpServletRequest request, HttpServletResponse response)

    	{

		.....
 

		HttpSession session = request.getSession(true);
 

		//Create unique filename for the temporary file....

                Date accessed = new Date(session.getLastAccessedTime());

                SimpleDateFormat format = new SimpleDateFormat("HHmmssSSS");

                String fordate = format.format(accessed);

                sDecrptFile = session.getId() + fordate + ".jsp";
 

		String sFileOutput = sJSPFilesFullLocation + sDecrptFile;

                String sFormatedResults = "null";
 
 

		FileInputStream fis = new FileInputStream(sEncrptedFile);

                FileOutputStream fos = new FileOutputStream(sFileOutput);
 

		

		.......The logic then goes to the Decrypt logic takes in fis (which is the encrypted file)......

		...... and then unencypts fis and outputs the unencrypted output to fos.....
 

		fis.close();

		fos.close();
 

		 

		//VArious attributes are set to pass to the unencrypted JSP page

		request.setAttribute("sValue1", sValue1);

		request.setAttribute("sValue2", sValue2);

		request.setAttribute("sValue3", sValue3);

		..........

       

                getServletConfig().getServletContext().getRequestDispatcher(sJSPFilesLocation + sDecrptFile).forward(request, response);
 

	}
 

	.......

}

Open in new window

0
 
LVL 19

Expert Comment

by:Kuldeepchaturvedi
ID: 21841060
if you are doing it to save the page from being viewed for somebod who have access to the server, its not the best way..

go to your tomcat installation and look for a directory named "work".. go inside you will find your .java files and .class files for all your jsp pages that you have decrypted...:-)

I would have used the security of underlying operating system of the server to protect any unauthorized access to your files.  

"After all somebody would have created your encypted jsp files as well..!!" Also if you need to debug any jsp, this encrypting/decrypting would be making it too hard....".


Coming back to the current problem, we are making a jsp and accessing it on every request, so memory uses going to be high, you will have see what are the areas where you can cut back on mem uses a little.
like use buffered stream for your file operations,
make our servlet context a class level variable, do not create the objects that can be reused etc.

0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 27

Accepted Solution

by:
rrz earned 300 total points
ID: 21842343
Kuldeep is right. In order to achieve your desired security level, you will have to delete the translated java file and the compiled class file for each of your sensitive JSPs.
I also agree with Kuldeep that your operating system could restrict read permission on your sensitive files.  

>I have a variety of files which are encrypted JSP pages (in that the content of each JSP page has been encrypted).  
Do you mean to say that the output of the JSP pages are encrypted ? Or do you encrypt the JSP code itself ?  
>It is only when I re-direct to the newly produced page that it causes the high memory usage.  
I guess we should have asked you at beginning, are these pages really big ?
>That is why that based on these tests, I thought that in directing to the newly created JSP page, it caches the page in memory somehow.  
Yes, when a request for a JSP is received, the container keeps an instance of the servlet that was generated from the JSP in memory. It is kept there and used for the next request for that page.  So if your pages are really big maybe this is your memory problem.    
I have an idea. But I don't know if it will work for you.  After you have created a  JSP,  programmatically request it once. After you have encrypted the output and stored it, change that JSP to a small dummy code and then  programmatically request it again. That way Tomcat will only hold a small instance of the servlet which was generated from the dummy stand-in JSP.  Use a Filter to detect the request for that JSP and redirect to your LogVFormsProcessor  servlet.  In fact the Filter would need to have a list of all the secured JSPs.
0
 

Author Comment

by:mikesung99
ID: 21854790
Thanks for the information so far, threre is logic which deletes the .java and .class files from the tomcat server's work directory. Within each JSP page that's decrypted, at the end of the JSP logic, there's logic to delete the specific files from the work folder.

The actual JSP pages are all encrypted and LogVFormsProcessor class decrypts the specific JSP page and produces a new file which contains the unencrypted JSP logic (but with the file name composed of the session ID and timestamp). The JSP pages vary in size - with the largest being 86K (around 1000 lines of code).

Just for reference - I may be understanding this incorrectly but is there anyway to tell tomcat not to store newly accessed JSP pages in memory?

Many Thanks
0
 
LVL 19

Assisted Solution

by:Kuldeepchaturvedi
Kuldeepchaturvedi earned 200 total points
ID: 21855016
As I have said before as well, To the best of my knowledge, Tomcat does not keep any jsp in Memory... the JSPC ( that is the piece that compiles the jsp to a class).. does not cache any compiled jsp code in memory.
0
 

Author Comment

by:mikesung99
ID: 21856467
Sorry about the misunderstanding, I've been reading around the subject on-line and I must have wrongly understood how Tomcat  processes the JSP.  It must be something with my code somewhere that's leaking memory with each request to the newly created JSP page. I'll review my code again and see if I can cut back on the memory usage. As mentioned, it's strange that the memory shoots up when navigate to the newly created JSP pages but memory usage is stable if I just navigate to the unencrypted JSP code (even with the class still doing the decryption logic).

I'll have a few things to go on, so I'll do some more investigation - Thanks you guys for you time in looking into this and all your suggestions.
0
 
LVL 27

Expert Comment

by:rrz
ID: 21857001
>the JSPC ( that is the piece that compiles the jsp to a class).. does not cache any compiled jsp code in memory.  true  
>As I have said before as well, To the best of my knowledge, Tomcat does not keep any jsp in Memory  
I don't exactly agree, Kuldeep.
From paragraph labeled  "Servlet Containers"  at  
http://download-west.oracle.com/docs/cd/A87860_01/doc/java.817/a83726/tecbkgn1.htm  
I quote  
"For performance reasons, it is typical for a servlet container to keep a servlet instance in memory for reuse, rather than destroying it each time it has finished its task. It would be destroyed only for infrequent events, such as Web server shutdown."

>The JSP pages vary in size - with the largest being 86K (around 1000 lines of code).
That doesn't sound big. But there is a lot of processing to be done with each request.
1) file has to be decrypted
2) Tomcat has to translate JSP file into a java source file  
3) Tomcat has to compile source file into bytecode ( class file)  
4) Tomcat has to process the request (including execution of bytecode)
5) deletion of  temp file and deletion of work folder files that were created.

Can you redesign ? What about my idea in my last post ?  Could you encrypt the output from the request processing ? That way when a request is received and detected by a Filter it is decoupled from the JSP processing.    
0
 
LVL 27

Expert Comment

by:rrz
ID: 21857106
>As mentioned, it's strange that the memory shoots up when navigate to the newly created JSP pages but memory usage is stable if I just navigate to the unencrypted JSP code (even with the class still doing the decryption logic).                  
Do you see any difference between the first request and the sebsequent requests to the unencrypted JSP code ?
The difference should be due to my 2) and 3) points above here.
0
 
LVL 19

Expert Comment

by:Kuldeepchaturvedi
ID: 21857413
>>>As I have said before as well, To the best of my knowledge, Tomcat does not keep any jsp in Memory  
I don't exactly agree, Kuldeep.
From paragraph labeled  "Servlet Containers"  at  

I agree, the container can keep the servlet instance in memory or even multiple instances of the same servlet ( specially if its a catch all filter).
In his case it shdnt be happening though, as his jsps are ALWAYS accessed only once...

But again, the implemention of this logic is not standard among containers and everybody could have implemented it differently.
0
 

Author Comment

by:mikesung99
ID: 21858187
For the unencrypted code, memory is consumed when the pages are first requested but after that for subsequent requests there is no significant change in the memory usage and the memory usage is stable. Re-designing may be an option later down the line but for the time being, the current encrypt/decrypt logic will have to be used.

I've consdiered your suggestion, rrz but the JSP logic contains logic to incrment some stats file and requesting it more than once will throw out the stats for the application.

Eventhough it may affect performance, is there a way to tell tomcat not to keep the servlet instances in memory but to destory it after it has finished? if this is possible, I would like to test.
0
 
LVL 27

Expert Comment

by:rrz
ID: 21858613
> is there a way to tell tomcat not to keep the servlet instances in memory but to destory it after it has finished?  
I don't know for sure but I don't think so.  
There used to  be this method
public java.util.Enumeration getServlets()  
that perhaps could have given a reference to the object. But it is deprecated. See  
http://tomcat.apache.org/tomcat-5.5-doc/servletapi/index.html  
Maybe a solution could be found using the following API ( which is available to a JSP)
http://tomcat.apache.org/tomcat-5.5-doc/catalina/docs/api/index.html  
But I could not find a way to do it.  
One possibility is to have two web apps.  One master and slave.  The client requests are sent to the master and the master asks the slave to do the work. After the slave does the work, the master unloads the slave web app( maybe using Tomcat's manager).  But the cost undeploying and redeploying a web app will have to be considered.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

This is a guide to setting up a new WHM/cPanel Server to be used for web hosting accounts. It is intended for web hosting company administrators and dedicated server owners. For under $99 per month (considering normal rate of Big Data Cetnters like …
One of the typical problems I have experienced is when you have to move a web server from one hosting site to another. You normally prepare all on the new host, transfer the site, change DNS and cross your fingers hoping all will be ok on new server…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now