-1

I have a class which has variables that are instances of classes such as vector, hashtable etc.

Code to serialize:

CRC32 checksum = new CRC32();
try {
    // serialize the object tree to a byteArray so we can get a checksum
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(this);
    checksum.update(baos.toByteArray());

    oos.close();
    baos.close();

Code to deserialize:

ByteArrayInputStream fis = new ByteArrayInputStream(serFile);
List<Class<?>> safeClasses = Arrays.asList(AdHocReportDefinition.class,
                                           TrustAdHocReportDefinition.class,
                                           Hashtable.class,
                                           SimpleReportField.class,
                                           ReportField.class,
                                           Date.class,
                                           Vector.class,
                                           SplittableSQLSimpleExpression.class,
                                           Expression.class,
                                           ArrayList.class);
reptDef = safeReadObject(AdHocReportDefinition.class, safeClasses, fis);

private static AdHocReportDefinition safeReadObject(Class<?> type,
                                                    List<Class<?>> safeClasses,
                                                    InputStream in) throws
                                                       IOException,
                                                       ClassNotFoundException {
    return (AdHocReportDefinition) new ObjectInputStream(in) {
        @Override
        protected Class<?> resolveClass(ObjectStreamClass d) throws IOException,
                                                                    ClassNotFoundException {
            Class<?> clazz = super.resolveClass(d);
            if (validationCondition(type, safeClasses, clazz)) {
                return clazz;
            }

            // Not throwing an exception here as it will lead to functionality fail for any
            // new class reference that added in TrustAdHocReportDefinition.
            Logger.warn(LoggerCategories.ADHOC_REPORTING,
                        "Attempt to deserialize unauthorized " + clazz);
            return clazz;
        }

        private boolean validationCondition(Class<?> type,
                                            List<Class<?>> safeClasses,
                                            Class<?> clazz) {
            return clazz.isArray()                      ||
                   clazz.isPrimitive()                  ||
                   clazz.equals(type)                   ||
                   clazz.equals(String.class)           ||
                   Number.class.isAssignableFrom(clazz) ||
                   safeClasses.contains(clazz);
        }
    }.readObject();
}

SimpleReportField#readObject method:

private void readObject(ObjectInputStream in) throws IOException,
                                                     ClassNotFoundException {
    in.defaultReadObject();
    DBTable table = DBTable.forName(dbTableName, dbIndicator);
    dbField = table.getField(dbFieldName);
}

Exception stack trace while deserializing by reading the serialized byte array from database:

java.io.EOFException
    at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2905)
    at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUTFBody(ObjectInputStream.java:3678)
    at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:3470)
    at java.base/java.io.ObjectInputStream.readString(ObjectInputStream.java:2058)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1663)
    at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2490)
    at java.base/java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:629)
    at com.xxx.trust.trustadhoc.reporting.adhoc.SimpleReportField.readObject(SimpleReportField.java:150)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1175)
    at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2351)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2222)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1681)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:493)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:451)
    at java.base/java.util.Hashtable.readHashtable(Hashtable.java:1315)
    at java.base/java.util.Hashtable.readObject(Hashtable.java:1259)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1175)
    at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2351)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2222)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1681)
    at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2490)
    at java.base/java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:629)
    at com.xxx.trust.trustadhoc.reporting.adhoc.AdHocReportDefinition.readObject(AdHocReportDefinition.java:814)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1175)
    at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2351)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2222)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1681)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:493)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:451)
    at com.xxx.trust.trustadhoc.reporting.adhoc.AdHocReportDefinition.safeReadObject(AdHocReportDefinition.java:479)
    at com.xxx.trust.trustadhoc.reporting.adhoc.AdHocReportDefinition.forName(AdHocReportDefinition.java:426)
    at com.xxx.trust.trustadhoc.display.AdHocCustomizeProcess.doProcess(AdHocCustomizeProcess.java:70)
    at com.xxx.trust.dispatch.DispatcherServlet.dispatch(DispatcherServlet.java:60)
    at com.xxx.trust.trustadhoc.display.TrustAdHocDispatcher.dispatch(TrustAdHocDispatcher.java:50)
    at com.xxx.trust.dispatch.DispatcherServlet.doPost(DispatcherServlet.java:192)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
    at com.xxx.trust.dispatch.SecureServlet.service(SecureServlet.java:91)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at com.xxx.trust.trustadhoc.util.appFilter.doFilter(appFilter.java:42)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:359)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1735)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:829)

Hashtable has SimpleReportField as its value - that is where the error comes from.

Code works fine with less data selected in the application - so less number of fields to serialize/deserialize. Checked the memory issue by analyzing heap dump - there does not seem to be any memory related issue.

If someone can tell me how to troubleshoot this issue e.g. how to check whether all the instance variables of the class in question have been serialized properly - that will also be helpful. Thanks in advance.

Edit

Made code changes as per comments by Louis Wasserman but result is same. Still getting same error.

Here are those code changes:

CRC32 checksum = new CRC32(); 
try { 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(this); 
oos.close(); 
byte[] bOutArray = baos.toByteArray() ; baos.close(); 
checksum.update(bOutArray);
Abra
  • 19,142
  • 7
  • 29
  • 41
Jitesh
  • 232
  • 2
  • 9
  • 2
    Closing an ObjectOutputStream will generate further bytes, and those certainly aren't included in your checksum. I can't tell if they're included in the rest of your serialization. (Although -- you're using Hashtable and Vector? How old is this code? Those classes have been pretty much replaced by better versions for over 20 years.) – Louis Wasserman Aug 13 '23 at 20:19
  • Code is very old - at least 15 years old. We got it in legacy. Do you think checksum is causing issues - code is working fine for small set of data though. Should we replace vector and Hashtable classes? How can I troubleshoot this issue to locate the exact root cause? – Jitesh Aug 14 '23 at 00:08
  • You should update the checksum after closing the `ObjectOutputStream`, as @LouisWasserman recommended, and retest. You should not change anything else. Don't dig a bigger hole. – user207421 Aug 14 '23 at 00:55
  • Still getting same error. – Jitesh Aug 14 '23 at 05:45
  • I suggest that you post a [mcve] rather than a few lines of code where you think the problem is. In the stack trace that you posted, there are references to code written by you that does not appear in your question, for example: `com.xxx.trust.trustadhoc.reporting.adhoc.SimpleReportField.readObject(SimpleReportField.java:150)` – Abra Aug 14 '23 at 09:22
  • readObject method of SimpleReportField class is posted in question. Line number 150 is the first line of the method (in.defaultReadObject()). – Jitesh Aug 14 '23 at 09:34
  • Great. Now format it properly so we can read it, which is, after all, the actual objective. – user207421 Aug 14 '23 at 09:48

0 Answers0