我如何找出我的会话试图序列化的对象?

How do I figure out what object my session is trying to serialize?

我最近升级到 Spring Security 4.2.3.RELEASE。我也在使用 spymemcached v 2.8.4。我 运行 遇到这种情况,出于某种原因 Spring 正在尝试序列化服务实现 classes。我不知道这是从哪里来的。我的异常所指的代码行是

Set<Session> userSessions = (Set<Session>) memcachedClient.get(userId);
...
memcachedClient.set(userId, sessionTimeoutInSeconds.intValue(), userSessions); // dies here

带有神秘错误("java.io.NotSerializableException: org.mainco.subco.ecom.service.ContractServiceImpl" 被埋在其中)...

09:06:47,771 ERROR [io.undertow.request] (default task-58) UT005023: Exception handling request to /myproject/registration/save: java.lang.IllegalArgumentException: Non-serializable object
    at net.spy.memcached.transcoders.BaseSerializingTranscoder.serialize(BaseSerializingTranscoder.java:110)
    at net.spy.memcached.transcoders.SerializingTranscoder.encode(SerializingTranscoder.java:162)
    at net.spy.memcached.MemcachedClient.asyncStore(MemcachedClient.java:282)
    at net.spy.memcached.MemcachedClient.set(MemcachedClient.java:733)
    at net.spy.memcached.MemcachedClient.set(MemcachedClient.java:126)
    at org.mainco.subco.session.service.MemcachedSessionService.associateUser(MemcachedSessionService.java:365)
    at org.mainco.subco.session.service.MemcachedSessionService.setSessionSecurityContext(MemcachedSessionService.java:288)
    at org.mainco.subco.core.security.SubcoSecurityContextRepository.saveContext(subcoSecurityContextRepository.java:116)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:114)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
    at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
    at io.undertow.servlet.handlers.ServletInitialHandler.access[=11=]0(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:174)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:198)
    at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:784)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.NotSerializableException: org.mainco.subco.ecom.service.ContractServiceImpl
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)

如何找出内存缓存正在尝试序列化的对象,从而弄清楚它是如何引用服务 class 进行序列化的?

这个问题的重点不是我如何使我的服务 class 可序列化,而是为什么我的会话首先要尝试序列化它。

I'm running into this situation where for some reason Spring is trying to serialize service implementation classes.

spring 不要尝试序列化实现。

当你这样做时看起来很苗条

memcachedClient.set(userId, sessionTimeoutInSeconds.intValue(), userSessions);

Serializable object 是预期的,但 userSessions 不是。

Set is not serializable ,然后输入你得到的

(Set) memcachedClient.get(userId);

未序列化为。检查您是否可以将 memcachedClient.get(userId) 转换为可序列化的东西,例如 HashSets 或 TreeSet ....

最糟糕的是你可以尝试但你可能会得到 CastException

memcachedClient.set(userId, sessionTimeoutInSeconds.intValue(), (Serializable)userSessions);


您可以迭代设置并进行简单检查:

int count=0;
for(Session session: userSessions ){
    log....
    boolean isSerializable = checkIfSerializable(session);
    count=isSerializable ? count+1 : count;
    log 
}

private static boolean checkIfSerializable(Object value) throws IllegalAccessException {
    try {
        ByteArrayOutputStream bf = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bf);
        oos.writeObject(value);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bf.toByteArray()));
        Object o = ois.readObject();
        return true;

    } catch (Exception e) {
        System.out.println("----->>>> Not exactly Serializable : " + value);
    }
        return false;
}

那么org.mainco.subco.ecom.service.ContractServiceImpl呢?这是spring豆子吗?

我猜它有 scope="session",因此它作为其属性之一绑定到您的会话。如果你想序列化你的会话 - 它的所有属性都必须是可序列化的。

为什么不尝试枚举会话和属性,然后 java 将它们序列化为虚拟输出流,直到失败为止?失败时打印属性名称和值 class.

我想 sessionorg.apache.catalina.Session。在您的代码中添加:

for(Session x : userSessions) checkSerializable(x.getSession());

checkSerializable:

 private static void checkSerializable(HttpSession s) {
        Enumeration e = s.getAttributeNames();
        while (e.hasMoreElements()) {
            String name = (String) e.nextElement();
            Object value = s.getAttribute(name);
            try
            {
                ObjectOutputStream out=new ObjectOutputStream(new ByteArrayOutputStream());
                out.writeObject(value);
            }
            catch(NotSerializableException ex)
            {
                ex.printStackTrace();
                System.out.println(name + " is not serializable, class is: " + value.getClass().getName());
            }
            catch(IOException e2)
            {
                throw new RuntimeException("Unexpected", e2);
            }

        }

    }