代码之家  ›  专栏  ›  技术社区  ›  Simon at The Access Group

ObjectSave导致java.io.UTFDataFormatException

  •  1
  • Simon at The Access Group  · 技术社区  · 11 年前

    与Railo一起作为bug引发 https://issues.jboss.org/browse/RAILO-2698 -这个问题应该结束

    我目前正在尝试对一个相当复杂的Struct进行ObjectSave(),该Struct包含一些CFC的实例以及使用以下cfscript的其他数据(这是我为重现问题而编写的测试脚本)

    <cfscript>
        thisState = session.objBasket.getState();
        writedump(thisState); // dumps the object successfully
        ObjectSave(thisState); // causes java.io.UTFDataFormatException
    </cfscript>
    

    我收到以下错误 java.io.UTFDataFormatException (后面是堆栈跟踪)。有人知道解决这个问题的方法吗?还是只是试图在工作中使用错误的工具?

    发生错误的Railo版本

    • Railo 4.1.1.009最终版本(Java 1.7.0_45)
    • Railo 4.1.1.009最终版本(Java 1.7.0_17)
    • Railo 4.1.2.001最终版本(Java 1.7.0_45)(预览版)

    未发生错误的Railo版本

    • Railo 4.0.4.001最终版本(Java 1.7.0_45)

    错误的堆栈跟踪

    java.io.UTFDataFormatException位于 java.io.ObjectOutputStream$BlockDataOutputStream.writeUTF(ObjectOutputStream.java:2163):2163 在 java.io.ObjectOutputStream$BlockDataOutputStream.writeUTF(ObjectOutputStream.java:2006):2006 在 java.io.ObjectOutputStream.writeUTF(ObjectOutputStream.java:868):868 在 railo.runtime.ComponentImpl.writeExternal(ComponentImpl.java:1975):1975 在 java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1458):1458 在 java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429):1429 在 java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177):1177 在 java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347):347 位于java.util.HashMap.writeObject(HashMap.java:1133):1133 sun.reflect.GeneratedMethodAccessor62.invoke(未知源):-1位于 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43):43 在java.lang.reflect.Method.ioke(Method.java:606):606在 java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988):988 在 java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495):1495 在 java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431):1431 在 java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177):1177 在 java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347):347 在 railo.commons.collection.AbstractMapPro.writeExternal(AbstractMapPro.java:49):49 在 java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1458):1458 在 java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429):1429 在 java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177):1177 在 java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547):1547 在 java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508):1508 在 java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431):1431 在 java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177):1177 在 java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347):347 位于java.util.HashMap.writeObject(HashMap.java:1133):1133 sun.reflect.GeneratedMethodAccessor62.invoke(未知源):-1位于 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43):43 在java.lang.reflect.Method.ioke(Method.java:606):606在 java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988):988 在 java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495):1495 在 java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431):1431 在 java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177):1177 在 java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347):347 在 railo.commons.collection.AbstractMapPro.writeExternal(AbstractMapPro.java:49):49 在 java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1458):1458 在 java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429):1429 在 java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177):1177 在 java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547):1547 在 java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508):1508 在 java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431):1431 在 java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177):1177 在 java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347):347 在 railo.runtime.converter.JavaConverter.serialize(JavaConverter.java:67):67 在 railo.runtime.functions.other.ObjectSave.call(ObjectSave.java:31):31 在 railo.runtime.functions.other.ObjectSave.call(ObjectSave.java:22):22 在 mso.clientobject_cfc$cf._3(/var/www/html/www/wsimon.test/mso/clientobject.cfc:476):476 在 mso.clientobject_cfc$cf.udfCall(/var/www/html/www/wsimon.test/mso/clientobject.cfc):-1 在railo.runtime.type.UDFImpl.implementation(UDFImpl.java:94):94处 railo.runtime.type.UDFImpl._call(UDFImpl.java:307):307在 railo.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:198):198 在 railo.runtime.type.scope.UndefinedImpl.callWithNamedValues(UndefinedImpl.java:709):709 在 railo.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:738):738 在 railo.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1513):1513 在 mso.clientobject_cfc$cf._3(/var/www/html/www/wsimon.test/mso/clientobject.cfc:437):437 在 mso.clientobject_cfc$cf.udfCall(/var/www/html/www/wsimon.test/mso/clientobject.cfc):-1 在railo.runtime.type.UDFImpl.implementation(UDFImpl.java:94):94处 railo.runtime.type.UDFImpl._call(UDFImpl.java:307):307在 railo.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:198):198 在railo.runtime.ComponentImpl._call(ComponentImpl.java:617):617在 railo.runtime.ComponentImpl._call(ComponentImpl.java:499):499在 railo.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:1732):1732 在 railo.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:738):738 在 railo.runtime.PageContextImpl.getFunctionWithNamedValues(PageContextImpl.java:1513):1513 在 mso.proxyclientobject_cfm$cf._1(/var/www/html/www/wsimon.test/mso/proxyclientobject.cfm:19):19 在 mso.proxyclientobject_cfm$cf.udfCall(/var/www/html/www/wsimon.test/mso/proxyclientobject.cfm):-1 在railo.runtime.type.UDFImpl.implementation(UDFImpl.java:94):94处 railo.runtime.type.UDFImpl._call(UDFImpl.java:307):307在 railo.runtime.type.UDFImpl.call(UDFImpl.java:211):211在 railo.runtime.ComponentImpl._call(ComponentImpl.java:616):616在 railo.runtime.ComponentImpl._call(ComponentImpl.java:499):499在 railo.runtime.ComponentImpl.call(ComponentImpl.java:1715):1715在 railo.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:712):712 在 railo.runtime.PageContextImpl.getFunction(PageContextImpl.java:1503):1503 在 preparecast_cfm$cf.call(/var/www/html/www/wsimon.test/preparecast.cfm:24):24 在 railo.runtime.PageContextImpl.doInclude(PageContextImpl.java:834):834 在 railo.runtime.PageContextImpl.doInclude(PageContextImpl.java:781):781 在 application_cfc$参考_1(/var/www/html/www/wsimon.test/Application.cfc:177):177 在 application_cfc$cf.udfCall(/var/www/html/www/wsimon.test/application.cfc):-1 在railo.runtime.type.UDFImpl.implementation(UDFImpl.java:94):94处 railo.runtime.type.UDFImpl._call(UDFImpl.java:307):307在 railo.runtime.type.UDFImpl.call(UDFImpl.java:211):211在 railo.runtime.ComponentImpl._call(ComponentImpl.java:616):616在 railo.runtime.ComponentImpl._call(ComponentImpl.java:499):499在 railo.runtime.ComponentImpl.call(ComponentImpl.java:1715):1715在 railo.runtime.relister.ModernAppListener.call(ModernAppLister.java:388):388 在 railo.runtime.relister.ModernAppListener._onRequest(ModernAppLister.java:204):204 在 railo.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:18):18 在 railo.runtime.PageContextImpl.execute(PageContextImpl.java:2167):2167 在 railo.runtime.PageContextImpl.execute(PageContextImpl.java:2134):2134 在 railo.runtime.engine.CMMLEngineImpl.serviceCFML(CFMLngineImpl.java:335):335 在railo.loader.servlet.CMLServlet.service(CFMLServlet.java:29):29 javax.servlet.http.HttpServlet服务(HttpServlet.java:728):728位于 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305):305 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210):210 在 org.apache.catalina.core.StandardWrapperValv.invoke(StandardWrapperValve.java:222):222 在 org.apache.catalina.core.StandardContextValv.invoke(StandardContextValv.java:123):123 在 org.apache.catalina.authenticator.AuthenticatorBase.ioke(AuthenticatorBase.java:472):472 在 org.apache.catalina.core.StandardHostValv.invoke(StandardHostValv.java:171):171 在 org.apache.catalina.vals.ErrorReportValve.ioke(ErrorReportValve.java:99):99 在 org.apache.catalina.core.StandardEngineValv.invoke(StandardEngineValv.java:118):118 在 org.apache.catalina.connecter.CoyoteAdapter.service(Coyotedapter.java:407):407 在 org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:200):200 在 org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589):589 在 org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310):310 在 java.util.concurrent.ThreadPoolExecutor.runWorker(线程池执行器.java:1145):1145 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615):615 在java.lang.Thread.run(线程.java:744):744

    单元测试+可用于复制的附带cfc

    java错误测试.cfc (单元测试)

    component extends='mxunit.framework.TestCase' {
        public void function trySavingLargeNestedStruct() {
            // Prove that it doesn't happen with nested structures
            var nestedStruct = {};
            var nestInMe = nestedStruct;
            // Make a big struct
            var nestedStruct = {};
            var v = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
            for (var i in v) {
                for (var j in v) {
                    for (var k in v) {
                        for (var l in v) {
                            nestedStruct[i][j][k][l] = {};
                        }
                    }
    
                }
            }
            debug('Nested struct len = '&len(serialize(nestedStruct)));
            ObjectSave(nestedStruct);
            debug('Nested struct saved without error');
        }
        public void function triggerUTFDataFormatException() {
            // Prove that it happens with objects nested deeply
            var previousLength = 0;
            for (var i=600;i<700;i++) {
                objTest = new TestObject( levels = i );
                var strSerialized = serialize(objTest);
                try {
                    ObjectSave(objTest);
                } catch (java.io.UTFDataFormatException e) {
                    // Expected place of java.io.UTFDataFormatException
                    debug('Levels = '&i-1&' has serialize() length = '&previousLength);
                    debug('Levels = '&i&' has serialize() length = '&Len(strSerialized));
                    debug(strSerialized);
                    debug(e);
                    fail('java.io.UTFDataFormatException (expected) error thrown');
                } catch (any e) {
                    debug(e);
                    fail('Error thrown, not not the expected one');
                }   
                previousLength = Len(strSerialized);
            }
        }
    }
    

    测试对象.cfc (用于失败测试)

    component {
        public TestObject function init(
            required numeric levels = 0
        ) {
            variables.a = (arguments.levels > 0)?new TestObject( levels = arguments.levels - 1 ):{};
            return this;
        }
    }
    
    2 回复  |  直到 11 年前
        1
  •  3
  •   user207421    11 年前

    看看堆栈跟踪。它回答了你所有的问题。

    java.io.UTFDataFormatException at java.io.ObjectOutputStream$BlockDataOutputStream.writeUTF(ObjectOutputStream.java:2163):2163 at java.io.ObjectOutputStream$BlockDataOutputStream.writeUTF(ObjectOutputStream.java:2006):2006 
    

    看一眼Javadoc就会发现这个异常是由 writeUTF() 如果要写入的数据大于65535字节。

    railo.runtime.ComponentImpl.writeExternal(ComponentImpl.java:1975):1975
    

    这是调用的代码 writeUTF(). 因此,它似乎是 railo.runtime.ComponentImpl 班它不应该打电话 写入UTF() 为了这么长的绳子。

        2
  •  1
  •   Simon at The Access Group    11 年前

    在纠正Railo错误之前,我使用以下两种方法来代替ObjectSave和ObjectLoad。它的功能似乎达到了相当复杂的程度。

    // Replaces ObjectSave
    private binary function serializeState(
        required struct inState
    ) {
        var strSerialized = serialize(arguments.inState);
        return strSerialized.GetBytes();
    }
    
    // Replaces ObjectLoad
    private struct function deserializeState(
        required binary inState
    ) {
        var strSerialized = ToString(arguments.inState);
        var stcDeserialized = evaluate(strSerialized);
        return stcDeserialized;
    }