Hi all,
as I've a requirement to maintain long lived sessions (~120s) I'm
using tomcat's PersistentManager to avoid keeping lots of sessions in
memory, each one with its own lastPage. I'm observing, specially in a
heavy loaded production environment, permanent errors with a trace
like
Nov 19, 2008 1:56:20 AM org.apache.catalina.session.StoreBase processExpires
SEVERE: Session: 115F3CD5A33E7D941AF8971FA62DE270;
java.lang.IllegalArgumentException: Unknown object type null
at
org.apache.wicket.protocol.http.pagestore.DiskPageStore.restoreAfterSerialization(DiskPageStore.java:1214)
at
org.apache.wicket.protocol.http.SecondLevelCacheSessionStore$SecondLevelCachePageMap.readObject(SecondLevelCacheSessionStore.java:409)
at sun.reflect.GeneratedMethodAccessor85.invoke(Unknown Source)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at
org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1441)
at
org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:942)
at org.apache.catalina.session.FileStore.load(FileStore.java:296)
at
org.apache.catalina.session.StoreBase.processExpires(StoreBase.java:195)
at
org.apache.catalina.session.PersistentManagerBase.processExpires(PersistentManagerBase.java:553)
at
org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:667)
I've managed myself to reproduced this error in a more controlled
environment and I discovered that tomcat's manager background thread
is swapping out the
session at a moment where lastPage == null.
SecondLevelCacheSessionStore$SecondLevelCachePageMap [line: 380]
if (sessionId != null && store instanceof IClusteredPageStore == false)
{
Object page = lastPage;
if (store instanceof
ISerializationAwarePageStore) <---
conditional breakpoint if page == null
{
Daemon Thread [ContainerBackgroundProcessor[StandardEngine[Catalina]]]
(Suspended (breakpoint at line 380 in
SecondLevelCacheSessionStore$SecondLevelCachePageMap))
SecondLevelCacheSessionStore$SecondLevelCachePageMap.writeObject(ObjectOutputStream)
line: 380
GeneratedMethodAccessor139.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
ObjectStreamClass.invokeWriteObject(Object, ObjectOutputStream) line:
945
ObjectOutputStream.writeSerialData(Object, ObjectStreamClass) line:
1461
ObjectOutputStream.writeOrdinaryObject(Object, ObjectStreamClass,
boolean) line: 1392
ObjectOutputStream.writeObject0(Object, boolean) line: 1150
ObjectOutputStream.writeObject(Object) line: 326
StandardSession.writeObject(ObjectOutputStream) line: 1517
StandardSession.writeObjectData(ObjectOutputStream) line: 959
FileStore.save(Session) line: 372
PersistentManager(PersistentManagerBase).writeSession(Session) line:
868
PersistentManager(PersistentManagerBase).swapOut(Session) line: 839
PersistentManager(PersistentManagerBase).processMaxIdleSwaps() line:
1058
PersistentManager(PersistentManagerBase).processPersistenceChecks()
line: 570
PersistentManager(PersistentManagerBase).processExpires() line: 551
PersistentManager(ManagerBase).backgroundProcess() line: 667
StandardContext(ContainerBase).backgroundProcess() line: 1316
ContainerBase$ContainerBackgroundProcessor.processChildren(Container,
ClassLoader) line: 1601
ContainerBase$ContainerBackgroundProcessor.processChildren(Container,
ClassLoader) line: 1610
ContainerBase$ContainerBackgroundProcessor.processChildren(Container,
ClassLoader) line: 1610
ContainerBase$ContainerBackgroundProcessor.run() line: 1590
Thread.run() line: 619
I've configured a minIdleTime of 120 seconds so I don't think tomcat
swaps the session out while it's still being accessed, in an invalid
intermediate state. The code for processMaxIdleSwaps looks fine:
protected void processMaxIdleSwaps() {
if (!isStarted() || maxIdleSwap < 0)
return;
Session sessions[] = findSessions();
long timeNow = System.currentTimeMillis();
// Swap out all sessions idle longer than maxIdleSwap
if (maxIdleSwap >= 0) {
for (int i = 0; i < sessions.length; i++) {
StandardSession session = (StandardSession) sessions[i];
synchronized (session) {
if (!session.isValid())
continue;
int timeIdle = // Truncate, do not round up
(int) ((timeNow -
session.getLastAccessedTime()) / 1000L);
if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) {
if (log.isDebugEnabled())
log.debug(sm.getString
("persistentManager.swapMaxIdle",
session.getIdInternal(), new
Integer(timeIdle)));
try {
swapOut(session);
} catch (IOException e) {
; // This is logged in writeSession()
}
}
}
}
}
}
Do you have any idea why lastPage could be null so many times (as an
important percentage -about 10%- of the sessions throws the above
error) ? Take into account that a big number of bots and crawlers is
accessing the site.
Any help will be very appreciated, I've spent many hours and days
tracing this issue...
Best regards
-Carlos
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]