Re: Session serialization uses wrapper objects instead of primitives
-BEGIN PGP SIGNED MESSAGE- Hash: SHA256 Konstantin, On 5/15/20 07:36, Konstantin Kolinko wrote: > чт, 14 мая 2020 г. в 18:48, Christopher Schultz > : >> >> All, >> >> I'm interested in the history of the >> StandardSession.writeObjectData method. I've been looking at it >> lately because I'm interested in possibly (optionally) encrypting >> the sessions in the backend session store. But this isn't about >> encryption at all. >> >> The code for StandardSession.doWriteObject(ObjectOutputStream >> stream) looks like this: >> >> >> // Write the scalar instance variables (except Manager) >> stream.writeObject(Long.valueOf(creationTime)); >> stream.writeObject(Long.valueOf(lastAccessedTime)); >> stream.writeObject(Integer.valueOf(maxInactiveInterval)); >> stream.writeObject(Boolean.valueOf(isNew)); >> stream.writeObject(Boolean.valueOf(isValid)); >> stream.writeObject(Long.valueOf(thisAccessedTime)); > > If I understand correctly, with objects you can read them with the > same 'readObject()' object method and decide what to do with the > received value. With primitives you have to decide upfront what > reading method you are going to call, and calling a wrong one will > result in a fatal failure where the rest of the data cannot be read > at all. > > For example, StandardSession.doReadObject has the following code: > > // The next object read could either be the number of attributes > (Integer) or the session's // authType followed by a Principal > object (not an Integer) Object nextObject = stream.readObject(); if > (!(nextObject instanceof Integer)) { This is true: changing from objects to primitives means that no changes can be made in the future such as re-ordering, changing the data type, etc. without breaking backward-compatibility. The metadata at the "beginning" of the stream is fairly stable, so I think it's safe to make this change. We could always write a version-number to the storage if we wanted. If we want to get really crazy, we can go full protobuf[1]. - -chris [1] https://developers.google.com/protocol-buffers/ -BEGIN PGP SIGNATURE- Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/ iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl6+pIYACgkQHPApP6U8 pFiRhRAAyCgUGymuV5dlYqVEYPkHtiOUHlmbxrcoeTGU9KfEDnKPZ0frOtdit1X8 POiBEelQooQYwC2AuYxQy0IbdZhCjtZwTX/voi1ieTTH0SQXADVVkD94jkbd2qVQ Izzn5aWc2KN0/+tDA0iPQtzntP7NhBJ3eCziz7cPxXbPcJCTSLAJr2OZJC7qPvGv Tit35FLpVyoMD0XE83tnZmEtczTSgKXC2qTHVtOP4/yObl/+JkAG7cUroKINv510 0bAvkqZ1BQnM6ocrKjUcA3GHOw8wPlnwu4B5g2sVXlfbm/Yg0VK9J8r5nUb/KOeZ iHwPop/FUammNIFJUHGwoVps8pvYHRn4GC2dFotIodrmi62P8B/7NiDW6fXfK/0E DCJoPdK29Kwy6r9CvMBRy9lbYx/0FcYv3Gb1m9nknAdJgaql55RCVSEUPSZ7J5on 6cnmIFNxKZw0evpBbTMzfuSu+3uGwSnp1VzRN4wCM8d8Ram8pt/3GmK0tt41ADDw VS8nbzeEmG1G/6MwCj5W1u11I1KLQl6bVcoLHLrREQQyS0X5+1Spg4v1av+kU7N9 uccb2sv6480LiaZvr+oWv5V1QlWKdSZgfekAsv5zWtaBIdw7MLwuY+0vvOYB682u xpUs2PBLWQHHHrHQRqLtYLBsa3l5imP4w2h1z3F5pwZTQfoJXwk= =UE1r -END PGP SIGNATURE- - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Re: Session serialization uses wrapper objects instead of primitives
чт, 14 мая 2020 г. в 18:48, Christopher Schultz : > > All, > > I'm interested in the history of the StandardSession.writeObjectData > method. I've been looking at it lately because I'm interested in > possibly (optionally) encrypting the sessions in the backend session > store. But this isn't about encryption at all. > > The code for StandardSession.doWriteObject(ObjectOutputStream stream) > looks like this: > > > // Write the scalar instance variables (except Manager) > stream.writeObject(Long.valueOf(creationTime)); > stream.writeObject(Long.valueOf(lastAccessedTime)); > stream.writeObject(Integer.valueOf(maxInactiveInterval)); > stream.writeObject(Boolean.valueOf(isNew)); > stream.writeObject(Boolean.valueOf(isValid)); > stream.writeObject(Long.valueOf(thisAccessedTime)); If I understand correctly, with objects you can read them with the same 'readObject()' object method and decide what to do with the received value. With primitives you have to decide upfront what reading method you are going to call, and calling a wrong one will result in a fatal failure where the rest of the data cannot be read at all. For example, StandardSession.doReadObject has the following code: // The next object read could either be the number of attributes (Integer) or the session's // authType followed by a Principal object (not an Integer) Object nextObject = stream.readObject(); if (!(nextObject instanceof Integer)) { Best regards, Konstantin Kolinko - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Re: Session serialization uses wrapper objects instead of primitives
On Fri, May 15, 2020 at 1:00 AM Christopher Schultz < ch...@christopherschultz.net> wrote: > -BEGIN PGP SIGNED MESSAGE- > Hash: SHA256 > > Mark, > > On 5/14/20 14:21, Mark Thomas wrote: > > On 14/05/2020 18:41, Christopher Schultz wrote: > >> Mark, > >> > >> On 5/14/20 12:53, Mark Thomas wrote: > >>> On 14/05/2020 17:46, Mark Thomas wrote: > On 14/05/2020 16:48, Christopher Schultz wrote: > > All, > > > > I'm interested in the history of the > > StandardSession.writeObjectData method. I've been looking > > at it lately because I'm interested in possibly > > (optionally) encrypting the sessions in the backend session > > store. But this isn't about encryption at all. > > > > The code for > > StandardSession.doWriteObject(ObjectOutputStream stream) > > looks like this: > > > > > > // Write the scalar instance variables (except Manager) > > stream.writeObject(Long.valueOf(creationTime)); > > stream.writeObject(Long.valueOf(lastAccessedTime)); > > stream.writeObject(Integer.valueOf(maxInactiveInterval)); > > stream.writeObject(Boolean.valueOf(isNew)); > > stream.writeObject(Boolean.valueOf(isValid)); > > stream.writeObject(Long.valueOf(thisAccessedTime)); > > > > > > Is there any reason we are writing object wrappers for > > these primitive members instead of just writing the > > primitives directly? > > That code goes all the way back to at least Tomcat 3.1.x > (20+ years ago). > > > It turns out that the byte stream is identical whether one > > uses objects or primitives, > > That surprises me. Looking at the JRE source code it really > surprises me. So much that I am going to go and try it for > myself. > >> > >>> My testing shows the opposite. There is a significant > >>> difference between writing primitives and writing objects. > >> > >> Hmm. I did a micro-test with just writing a single > >> Long.valueOf() value and a (primitive) long alone to an > >> ObjectOutputStream. I didn't test the StandardSession itself. > > > > I performed the same micro-test. > > > >>> Given backwards compatibility requirements we can't change this > >>> in 9.0.x and earlier. > >> > >> Agreed. > >> > One reason we might want to stick with writing objects is to > support sessionAttributeValueClassNameFilter. I'm only going > from reading the source so I could easily have missed > something but it looks like that will only work if we > write/read objects. > >> > >>> We only care about this for session attributes. We know our > >>> internal attributes are safe so we could switch to primitives > >>> in 10.0.x. > >> > >> I'll have to play-around a bit to see what was wrong with my > >> initial tes t. > > So my test was bunk, the data on-the-wire (so to speak) is very > different, and there is no way at all to make them compatible. :/ > > Perhaps a rewindable input stream would work, but it's just not really > that important. > > I think it's okay to make a breaking change at 10.0, but only if > anyone really cares. It saves a couple of bytes which can add up. > > In my microtest, I wrote a java.lang.Long value and a (primitive) long > to two separate files. The object-file was 82 bytes and the > primitive-file was 14 bytes. It looks like after the 2-byte header and > 2-byte version identifier, the primitive long is written as "block > data" with a 1-byte length (8) and then the 8 bytes of the long. The > object flavor is ... more verbose. > > So we get almost 90% savings for a single long value. On the other > hand, the primitive only values going into sessions are the metadata > and not the attributes, which will dominate the bulk of the data (or > should, anyway). > > I still think this is worth doing. > > Any objections? > No objections! > > - -chris > -BEGIN PGP SIGNATURE- > Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/ > > iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl69sXYACgkQHPApP6U8 > pFi6pg/9ExBQhRRlUv4QPUVDJEhJ8pN6KfBIoHgd/UWw2zYxjeifhDrN+biK2lLG > GHWmJuF+wEAFz9xtYqN46q1QqSKIQcWTAqI05NchNlqFd29JHwj+9QZV00VTd0eK > My4MTCVY4dSObJrePyw14tEHyRVcFl539bDhtez7fnjOGkq4EGNXvr7ep9L3w5GB > ckwKAp1OuFYz5/0ZCCDEVdRiSpoXAac06B5v0FUQb3TBn06gdavUJb9q0HM57RjI > 0FkQHPyZ1ibfWOOLldBrCgA+7SygGiD6LO2nMo5Fgy1A4l5W/uekkhW96FXBKHng > /ocXJRQSkeDoanpQmu5pC/Ru1S0bNjZCIo9OMS0de6iEMEO3wPtvuLYhINYydk6E > 3ZNx+EPZEFPoZuB1K0peWNDgFsE3ar5gL+y6cvztNoZtT1WymoDS6uQ4OvGXcXNL > 61SOSe3CmqHF0dQTlD/Xikakumz4Kefny5QGw/XlchPVNCqUmvgxUwYPb965kwz3 > Vt/3nib0QgKxbR0j54InFIRkG7gPuGyUaL0kwtMbFEdOTw+PqAEyIPSqIRtmkhVG > Mzf6ikh+TOToYi+OIJXUMloaVL8xafAo6hKTc7lbu2hAUv9bE47X6uVyQmD7Yxqu > R3LQGo3OYX9+GBdKBhgvbZB9bEkUImMbsgIXKIUScGaMH4RdtBE= > =AZle > -END PGP SIGNATURE- > > - > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > For additional commands, e-mail:
Re: Session serialization uses wrapper objects instead of primitives
On Fri, May 15, 2020 at 12:00 AM Christopher Schultz < ch...@christopherschultz.net> wrote: > -BEGIN PGP SIGNED MESSAGE- > Hash: SHA256 > > Mark, > > On 5/14/20 14:21, Mark Thomas wrote: > > On 14/05/2020 18:41, Christopher Schultz wrote: > >> Mark, > >> > >> On 5/14/20 12:53, Mark Thomas wrote: > >>> On 14/05/2020 17:46, Mark Thomas wrote: > On 14/05/2020 16:48, Christopher Schultz wrote: > > All, > > > > I'm interested in the history of the > > StandardSession.writeObjectData method. I've been looking > > at it lately because I'm interested in possibly > > (optionally) encrypting the sessions in the backend session > > store. But this isn't about encryption at all. > > > > The code for > > StandardSession.doWriteObject(ObjectOutputStream stream) > > looks like this: > > > > > > // Write the scalar instance variables (except Manager) > > stream.writeObject(Long.valueOf(creationTime)); > > stream.writeObject(Long.valueOf(lastAccessedTime)); > > stream.writeObject(Integer.valueOf(maxInactiveInterval)); > > stream.writeObject(Boolean.valueOf(isNew)); > > stream.writeObject(Boolean.valueOf(isValid)); > > stream.writeObject(Long.valueOf(thisAccessedTime)); > > > > > > Is there any reason we are writing object wrappers for > > these primitive members instead of just writing the > > primitives directly? > > That code goes all the way back to at least Tomcat 3.1.x > (20+ years ago). > > > It turns out that the byte stream is identical whether one > > uses objects or primitives, > > That surprises me. Looking at the JRE source code it really > surprises me. So much that I am going to go and try it for > myself. > >> > >>> My testing shows the opposite. There is a significant > >>> difference between writing primitives and writing objects. > >> > >> Hmm. I did a micro-test with just writing a single > >> Long.valueOf() value and a (primitive) long alone to an > >> ObjectOutputStream. I didn't test the StandardSession itself. > > > > I performed the same micro-test. > > > >>> Given backwards compatibility requirements we can't change this > >>> in 9.0.x and earlier. > >> > >> Agreed. > >> > One reason we might want to stick with writing objects is to > support sessionAttributeValueClassNameFilter. I'm only going > from reading the source so I could easily have missed > something but it looks like that will only work if we > write/read objects. > >> > >>> We only care about this for session attributes. We know our > >>> internal attributes are safe so we could switch to primitives > >>> in 10.0.x. > >> > >> I'll have to play-around a bit to see what was wrong with my > >> initial tes t. > > So my test was bunk, the data on-the-wire (so to speak) is very > different, and there is no way at all to make them compatible. :/ > > Perhaps a rewindable input stream would work, but it's just not really > that important. > > I think it's okay to make a breaking change at 10.0, but only if > anyone really cares. It saves a couple of bytes which can add up. > > In my microtest, I wrote a java.lang.Long value and a (primitive) long > to two separate files. The object-file was 82 bytes and the > primitive-file was 14 bytes. It looks like after the 2-byte header and > 2-byte version identifier, the primitive long is written as "block > data" with a 1-byte length (8) and then the 8 bytes of the long. The > object flavor is ... more verbose. > > So we get almost 90% savings for a single long value. On the other > hand, the primitive only values going into sessions are the metadata > and not the attributes, which will dominate the bulk of the data (or > should, anyway). > > I still think this is worth doing. > > Any objections? > Ok. Rémy > > - -chris > -BEGIN PGP SIGNATURE- > Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/ > > iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl69sXYACgkQHPApP6U8 > pFi6pg/9ExBQhRRlUv4QPUVDJEhJ8pN6KfBIoHgd/UWw2zYxjeifhDrN+biK2lLG > GHWmJuF+wEAFz9xtYqN46q1QqSKIQcWTAqI05NchNlqFd29JHwj+9QZV00VTd0eK > My4MTCVY4dSObJrePyw14tEHyRVcFl539bDhtez7fnjOGkq4EGNXvr7ep9L3w5GB > ckwKAp1OuFYz5/0ZCCDEVdRiSpoXAac06B5v0FUQb3TBn06gdavUJb9q0HM57RjI > 0FkQHPyZ1ibfWOOLldBrCgA+7SygGiD6LO2nMo5Fgy1A4l5W/uekkhW96FXBKHng > /ocXJRQSkeDoanpQmu5pC/Ru1S0bNjZCIo9OMS0de6iEMEO3wPtvuLYhINYydk6E > 3ZNx+EPZEFPoZuB1K0peWNDgFsE3ar5gL+y6cvztNoZtT1WymoDS6uQ4OvGXcXNL > 61SOSe3CmqHF0dQTlD/Xikakumz4Kefny5QGw/XlchPVNCqUmvgxUwYPb965kwz3 > Vt/3nib0QgKxbR0j54InFIRkG7gPuGyUaL0kwtMbFEdOTw+PqAEyIPSqIRtmkhVG > Mzf6ikh+TOToYi+OIJXUMloaVL8xafAo6hKTc7lbu2hAUv9bE47X6uVyQmD7Yxqu > R3LQGo3OYX9+GBdKBhgvbZB9bEkUImMbsgIXKIUScGaMH4RdtBE= > =AZle > -END PGP SIGNATURE- > > - > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > For additional commands, e-mail:
Re: Session serialization uses wrapper objects instead of primitives
-BEGIN PGP SIGNED MESSAGE- Hash: SHA256 Mark, On 5/14/20 14:21, Mark Thomas wrote: > On 14/05/2020 18:41, Christopher Schultz wrote: >> Mark, >> >> On 5/14/20 12:53, Mark Thomas wrote: >>> On 14/05/2020 17:46, Mark Thomas wrote: On 14/05/2020 16:48, Christopher Schultz wrote: > All, > > I'm interested in the history of the > StandardSession.writeObjectData method. I've been looking > at it lately because I'm interested in possibly > (optionally) encrypting the sessions in the backend session > store. But this isn't about encryption at all. > > The code for > StandardSession.doWriteObject(ObjectOutputStream stream) > looks like this: > > > // Write the scalar instance variables (except Manager) > stream.writeObject(Long.valueOf(creationTime)); > stream.writeObject(Long.valueOf(lastAccessedTime)); > stream.writeObject(Integer.valueOf(maxInactiveInterval)); > stream.writeObject(Boolean.valueOf(isNew)); > stream.writeObject(Boolean.valueOf(isValid)); > stream.writeObject(Long.valueOf(thisAccessedTime)); > > > Is there any reason we are writing object wrappers for > these primitive members instead of just writing the > primitives directly? That code goes all the way back to at least Tomcat 3.1.x (20+ years ago). > It turns out that the byte stream is identical whether one > uses objects or primitives, That surprises me. Looking at the JRE source code it really surprises me. So much that I am going to go and try it for myself. >> >>> My testing shows the opposite. There is a significant >>> difference between writing primitives and writing objects. >> >> Hmm. I did a micro-test with just writing a single >> Long.valueOf() value and a (primitive) long alone to an >> ObjectOutputStream. I didn't test the StandardSession itself. > > I performed the same micro-test. > >>> Given backwards compatibility requirements we can't change this >>> in 9.0.x and earlier. >> >> Agreed. >> One reason we might want to stick with writing objects is to support sessionAttributeValueClassNameFilter. I'm only going from reading the source so I could easily have missed something but it looks like that will only work if we write/read objects. >> >>> We only care about this for session attributes. We know our >>> internal attributes are safe so we could switch to primitives >>> in 10.0.x. >> >> I'll have to play-around a bit to see what was wrong with my >> initial tes t. So my test was bunk, the data on-the-wire (so to speak) is very different, and there is no way at all to make them compatible. :/ Perhaps a rewindable input stream would work, but it's just not really that important. I think it's okay to make a breaking change at 10.0, but only if anyone really cares. It saves a couple of bytes which can add up. In my microtest, I wrote a java.lang.Long value and a (primitive) long to two separate files. The object-file was 82 bytes and the primitive-file was 14 bytes. It looks like after the 2-byte header and 2-byte version identifier, the primitive long is written as "block data" with a 1-byte length (8) and then the 8 bytes of the long. The object flavor is ... more verbose. So we get almost 90% savings for a single long value. On the other hand, the primitive only values going into sessions are the metadata and not the attributes, which will dominate the bulk of the data (or should, anyway). I still think this is worth doing. Any objections? - -chris -BEGIN PGP SIGNATURE- Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/ iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl69sXYACgkQHPApP6U8 pFi6pg/9ExBQhRRlUv4QPUVDJEhJ8pN6KfBIoHgd/UWw2zYxjeifhDrN+biK2lLG GHWmJuF+wEAFz9xtYqN46q1QqSKIQcWTAqI05NchNlqFd29JHwj+9QZV00VTd0eK My4MTCVY4dSObJrePyw14tEHyRVcFl539bDhtez7fnjOGkq4EGNXvr7ep9L3w5GB ckwKAp1OuFYz5/0ZCCDEVdRiSpoXAac06B5v0FUQb3TBn06gdavUJb9q0HM57RjI 0FkQHPyZ1ibfWOOLldBrCgA+7SygGiD6LO2nMo5Fgy1A4l5W/uekkhW96FXBKHng /ocXJRQSkeDoanpQmu5pC/Ru1S0bNjZCIo9OMS0de6iEMEO3wPtvuLYhINYydk6E 3ZNx+EPZEFPoZuB1K0peWNDgFsE3ar5gL+y6cvztNoZtT1WymoDS6uQ4OvGXcXNL 61SOSe3CmqHF0dQTlD/Xikakumz4Kefny5QGw/XlchPVNCqUmvgxUwYPb965kwz3 Vt/3nib0QgKxbR0j54InFIRkG7gPuGyUaL0kwtMbFEdOTw+PqAEyIPSqIRtmkhVG Mzf6ikh+TOToYi+OIJXUMloaVL8xafAo6hKTc7lbu2hAUv9bE47X6uVyQmD7Yxqu R3LQGo3OYX9+GBdKBhgvbZB9bEkUImMbsgIXKIUScGaMH4RdtBE= =AZle -END PGP SIGNATURE- - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Re: Session serialization uses wrapper objects instead of primitives
-BEGIN PGP SIGNED MESSAGE- Hash: SHA256 Mark, On 5/14/20 14:21, Mark Thomas wrote: > On 14/05/2020 18:41, Christopher Schultz wrote: >> Mark, >> >> On 5/14/20 12:53, Mark Thomas wrote: >>> On 14/05/2020 17:46, Mark Thomas wrote: On 14/05/2020 16:48, Christopher Schultz wrote: > All, > > I'm interested in the history of the > StandardSession.writeObjectData method. I've been looking > at it lately because I'm interested in possibly > (optionally) encrypting the sessions in the backend session > store. But this isn't about encryption at all. > > The code for > StandardSession.doWriteObject(ObjectOutputStream stream) > looks like this: > > > // Write the scalar instance variables (except Manager) > stream.writeObject(Long.valueOf(creationTime)); > stream.writeObject(Long.valueOf(lastAccessedTime)); > stream.writeObject(Integer.valueOf(maxInactiveInterval)); > stream.writeObject(Boolean.valueOf(isNew)); > stream.writeObject(Boolean.valueOf(isValid)); > stream.writeObject(Long.valueOf(thisAccessedTime)); > > > Is there any reason we are writing object wrappers for > these primitive members instead of just writing the > primitives directly? That code goes all the way back to at least Tomcat 3.1.x (20+ years ago). > It turns out that the byte stream is identical whether one > uses objects or primitives, That surprises me. Looking at the JRE source code it really surprises me. So much that I am going to go and try it for myself. >> >>> My testing shows the opposite. There is a significant >>> difference between writing primitives and writing objects. >> >> Hmm. I did a micro-test with just writing a single >> Long.valueOf() value and a (primitive) long alone to an >> ObjectOutputStream. I didn't test the StandardSession itself. > > I performed the same micro-test. > >>> Given backwards compatibility requirements we can't change this >>> in 9.0.x and earlier. >> >> Agreed. >> One reason we might want to stick with writing objects is to support sessionAttributeValueClassNameFilter. I'm only going from reading the source so I could easily have missed something but it looks like that will only work if we write/read objects. >> >>> We only care about this for session attributes. We know our >>> internal attributes are safe so we could switch to primitives >>> in 10.0.x. >> >> I'll have to play-around a bit to see what was wrong with my >> initial tes t. > > JRE version? I used a newish Java 8. Long value? I used 1000. I > did something stupid? Source code here: > > https://github.com/markt-asf/tomcat-bugs/blob/master/src/java/org/apac he/tomcat/ObjectStreams.java My > problem appears to be that I copy-pasted and didn't change one of the calls. *eyeroll* - -chris -BEGIN PGP SIGNATURE- Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/ iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl69rfEACgkQHPApP6U8 pFgO2w/+Mld4Akm77AOAOWRaqVQVi6BOXOUJE5uRGq8XlsTvx2U4GM6PTuT4F/Tp Ow9g9NdpK89kPxBDDK+wfZF2qDmwO7uXWqKUr6OQ24qJR2aEerTQsn90GvbKp3j3 SmqeKVGMK8TZJlLtsw7YiMguH0z8v38wulwovBFPdVBZsPTKETo0DjrTxR0oZhrD lZYKo5qwIF+LWd9NtdLSog9s/nMuC9jJoqwjD5azcRbmpAjYU9oIeQX8q3nqcOFh DFxXVCbzzLe6EQlkSg0Bpc0PU3FoK5qKPaAcMdjtaVP+L28nbTVkTCugDcxcwNou M2yi88gxtCk7OOknfum3ukNZI1gvRHvEHMQINdQaXmJ32oxy5QpdJ1ICew2Elo45 Hakms9os6i5QIz2XdF8BZ7ihqtuxkb3stzEi66KTtiTp41V6aHHTiAHIpsJfTsHZ ZTiaS9UPHZVAMnSE6/QvIAz68IkA3/cQvz9Ed+lClp6r4vqWDomkFsqKH1NDMQCX gCnTj/3zNXb4+FovhzFnEEM+Pbwe0c20y/I+piTe5S6U6Zcl958au4MNToBCr/t0 YXn0OkAlc24EJBOP37b3406SQEfmBDd4FP7z8fY9QTwT3cOBH3dvzaqYhL8mMBhF ToVs/lbO5KoBJG0xDC3gK/22r19oyNUaiLa1OlUC533IeMpmloc= =DHdr -END PGP SIGNATURE- - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Re: Session serialization uses wrapper objects instead of primitives
On 14/05/2020 18:41, Christopher Schultz wrote: > Mark, > > On 5/14/20 12:53, Mark Thomas wrote: >> On 14/05/2020 17:46, Mark Thomas wrote: >>> On 14/05/2020 16:48, Christopher Schultz wrote: All, I'm interested in the history of the StandardSession.writeObjectData method. I've been looking at it lately because I'm interested in possibly (optionally) encrypting the sessions in the backend session store. But this isn't about encryption at all. The code for StandardSession.doWriteObject(ObjectOutputStream stream) looks like this: // Write the scalar instance variables (except Manager) stream.writeObject(Long.valueOf(creationTime)); stream.writeObject(Long.valueOf(lastAccessedTime)); stream.writeObject(Integer.valueOf(maxInactiveInterval)); stream.writeObject(Boolean.valueOf(isNew)); stream.writeObject(Boolean.valueOf(isValid)); stream.writeObject(Long.valueOf(thisAccessedTime)); Is there any reason we are writing object wrappers for these primitive members instead of just writing the primitives directly? >>> >>> That code goes all the way back to at least Tomcat 3.1.x (20+ >>> years ago). >>> It turns out that the byte stream is identical whether one uses objects or primitives, >>> >>> That surprises me. Looking at the JRE source code it really >>> surprises me. So much that I am going to go and try it for >>> myself. > >> My testing shows the opposite. There is a significant difference >> between writing primitives and writing objects. > > Hmm. I did a micro-test with just writing a single Long.valueOf() > value and a (primitive) long alone to an ObjectOutputStream. I didn't > test the StandardSession itself. I performed the same micro-test. >> Given backwards compatibility requirements we can't change this in >> 9.0.x and earlier. > > Agreed. > >>> One reason we might want to stick with writing objects is to >>> support sessionAttributeValueClassNameFilter. I'm only going from >>> reading the source so I could easily have missed something but it >>> looks like that will only work if we write/read objects. > >> We only care about this for session attributes. We know our >> internal attributes are safe so we could switch to primitives in >> 10.0.x. > > I'll have to play-around a bit to see what was wrong with my initial tes > t. JRE version? I used a newish Java 8. Long value? I used 1000. I did something stupid? Source code here: https://github.com/markt-asf/tomcat-bugs/blob/master/src/java/org/apache/tomcat/ObjectStreams.java Mark - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Re: Session serialization uses wrapper objects instead of primitives
-BEGIN PGP SIGNED MESSAGE- Hash: SHA256 Mark, On 5/14/20 12:53, Mark Thomas wrote: > On 14/05/2020 17:46, Mark Thomas wrote: >> On 14/05/2020 16:48, Christopher Schultz wrote: >>> All, >>> >>> I'm interested in the history of the >>> StandardSession.writeObjectData method. I've been looking at it >>> lately because I'm interested in possibly (optionally) >>> encrypting the sessions in the backend session store. But this >>> isn't about encryption at all. >>> >>> The code for StandardSession.doWriteObject(ObjectOutputStream >>> stream) looks like this: >>> >>> >>> // Write the scalar instance variables (except Manager) >>> stream.writeObject(Long.valueOf(creationTime)); >>> stream.writeObject(Long.valueOf(lastAccessedTime)); >>> stream.writeObject(Integer.valueOf(maxInactiveInterval)); >>> stream.writeObject(Boolean.valueOf(isNew)); >>> stream.writeObject(Boolean.valueOf(isValid)); >>> stream.writeObject(Long.valueOf(thisAccessedTime)); >>> >>> >>> Is there any reason we are writing object wrappers for these >>> primitive members instead of just writing the primitives >>> directly? >> >> That code goes all the way back to at least Tomcat 3.1.x (20+ >> years ago). >> >>> It turns out that the byte stream is identical whether one >>> uses objects or primitives, >> >> That surprises me. Looking at the JRE source code it really >> surprises me. So much that I am going to go and try it for >> myself. > > My testing shows the opposite. There is a significant difference > between writing primitives and writing objects. Hmm. I did a micro-test with just writing a single Long.valueOf() value and a (primitive) long alone to an ObjectOutputStream. I didn't test the StandardSession itself. > Given backwards compatibility requirements we can't change this in > 9.0.x and earlier. Agreed. >> One reason we might want to stick with writing objects is to >> support sessionAttributeValueClassNameFilter. I'm only going from >> reading the source so I could easily have missed something but it >> looks like that will only work if we write/read objects. > > We only care about this for session attributes. We know our > internal attributes are safe so we could switch to primitives in > 10.0.x. I'll have to play-around a bit to see what was wrong with my initial tes t. - -chris -BEGIN PGP SIGNATURE- Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/ iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl69guMACgkQHPApP6U8 pFg40BAAowAyGeHKQAWyj4OjZVwuZJnZpNaBsK0Rthw2rmCPFVVzBb37IDV7svxk HjmYyvKSM3NxRke/ftSysfg7hnGAaK0gFuyk8XSqUp5ZXkJUzHoS/44Ite1Fsqux 8iwc+djveuybUEacxz9PGLH9+vmXVI9EhvYUHKXyWS5w5KKXBVghPcrnL9gjBbTs F7a92V6xiRUdnhDBpixOEBnwihfAisd1CS9XQjIAhVB2T0mkSsinZBFqzy5HZX4a ohMhX1aAFKyHEV9rHeNlV9mTzj1Wg+rgXEVW4hWnGzmt+iS3KdLxdRZRw+6v78O6 M4cYPclPYek//toB7mf+FFyrPtyfVMjG9lvqP3serXQ8Ujh7HvUNQX91/kgpC9mQ xWJQqpsR7CwkmleU/XFFcyz9Dp+N/SlZSomPneeLRj4+Epx+AX8WgXVZMZdJNXVf MN5IIix7K9ff+drbCgwFsC2Yf1M76Mf6VQSXKdNmxZ5AfXJy9Kzk8z2rukj63wMA wHs3CEjHjN7PevbgUbvQnA6Ze92ZRlzQqhrZl400/lriYzGeePQmqeVg5/mlAWLW 2YJQRsmaA8Q7QI63vZXkBYGBA1/lh6NDFF3mVqHCxAy3nUfSx3VNgwVZSk3aItqw eDgNxRJkhR43MLj1GDQTAVjHF+XrMw87xDp58cI0pxhgavGzlsI= =2xPi -END PGP SIGNATURE- - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Re: Session serialization uses wrapper objects instead of primitives
On 14/05/2020 17:46, Mark Thomas wrote: > On 14/05/2020 16:48, Christopher Schultz wrote: >> All, >> >> I'm interested in the history of the StandardSession.writeObjectData >> method. I've been looking at it lately because I'm interested in >> possibly (optionally) encrypting the sessions in the backend session >> store. But this isn't about encryption at all. >> >> The code for StandardSession.doWriteObject(ObjectOutputStream stream) >> looks like this: >> >> >> // Write the scalar instance variables (except Manager) >> stream.writeObject(Long.valueOf(creationTime)); >> stream.writeObject(Long.valueOf(lastAccessedTime)); >> stream.writeObject(Integer.valueOf(maxInactiveInterval)); >> stream.writeObject(Boolean.valueOf(isNew)); >> stream.writeObject(Boolean.valueOf(isValid)); >> stream.writeObject(Long.valueOf(thisAccessedTime)); >> >> >> Is there any reason we are writing object wrappers for these primitive >> members instead of just writing the primitives directly? > > That code goes all the way back to at least Tomcat 3.1.x (20+ years ago). > >> It turns out that the byte stream is identical whether one uses >> objects or primitives, > > That surprises me. Looking at the JRE source code it really surprises > me. So much that I am going to go and try it for myself. My testing shows the opposite. There is a significant difference between writing primitives and writing objects. Given backwards compatibility requirements we can't change this in 9.0.x and earlier. > One reason we might want to stick with writing objects is to support > sessionAttributeValueClassNameFilter. I'm only going from reading the > source so I could easily have missed something but it looks like that > will only work if we write/read objects. We only care about this for session attributes. We know our internal attributes are safe so we could switch to primitives in 10.0.x. Mark - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Re: Session serialization uses wrapper objects instead of primitives
On 14/05/2020 16:48, Christopher Schultz wrote: > All, > > I'm interested in the history of the StandardSession.writeObjectData > method. I've been looking at it lately because I'm interested in > possibly (optionally) encrypting the sessions in the backend session > store. But this isn't about encryption at all. > > The code for StandardSession.doWriteObject(ObjectOutputStream stream) > looks like this: > > > // Write the scalar instance variables (except Manager) > stream.writeObject(Long.valueOf(creationTime)); > stream.writeObject(Long.valueOf(lastAccessedTime)); > stream.writeObject(Integer.valueOf(maxInactiveInterval)); > stream.writeObject(Boolean.valueOf(isNew)); > stream.writeObject(Boolean.valueOf(isValid)); > stream.writeObject(Long.valueOf(thisAccessedTime)); > > > Is there any reason we are writing object wrappers for these primitive > members instead of just writing the primitives directly? That code goes all the way back to at least Tomcat 3.1.x (20+ years ago). > It turns out that the byte stream is identical whether one uses > objects or primitives, That surprises me. Looking at the JRE source code it really surprises me. So much that I am going to go and try it for myself. One reason we might want to stick with writing objects is to support sessionAttributeValueClassNameFilter. I'm only going from reading the source so I could easily have missed something but it looks like that will only work if we write/read objects. Mark - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Session serialization uses wrapper objects instead of primitives
-BEGIN PGP SIGNED MESSAGE- Hash: SHA256 All, I'm interested in the history of the StandardSession.writeObjectData method. I've been looking at it lately because I'm interested in possibly (optionally) encrypting the sessions in the backend session store. But this isn't about encryption at all. The code for StandardSession.doWriteObject(ObjectOutputStream stream) looks like this: // Write the scalar instance variables (except Manager) stream.writeObject(Long.valueOf(creationTime)); stream.writeObject(Long.valueOf(lastAccessedTime)); stream.writeObject(Integer.valueOf(maxInactiveInterval)); stream.writeObject(Boolean.valueOf(isNew)); stream.writeObject(Boolean.valueOf(isValid)); stream.writeObject(Long.valueOf(thisAccessedTime)); Is there any reason we are writing object wrappers for these primitive members instead of just writing the primitives directly? It turns out that the byte stream is identical whether one uses objects or primitives, but the code is a little more complicated, generates objects when none are necessary, etc. Here is the doReadObject code: creationTime = ((Long) stream.readObject()).longValue(); lastAccessedTime = ((Long) stream.readObject()).longValue(); maxInactiveInterval = ((Integer) stream.readObject()).intValue() ; isNew = ((Boolean) stream.readObject()).booleanValue(); isValid = ((Boolean) stream.readObject()).booleanValue(); thisAccessedTime = ((Long) stream.readObject()).longValue(); If using primitives, it would be: creationTime = stream.readLong(); lastAccessedTime = stream.readLong(); maxInactiveInterval = stream.readInt(); isNew = stream.readBoolean(); isValid = stream.readBoolean(); thisAccessedTime = stream.readLong(); I don't believe there is any benefit to using objects over primitives in this case. If the stream doesn't contain the right object types in the right order, the operation will fail so they are providing any e.g. type-safety that you might get by casting to (Number) and then pulling long value (to convert an int -> long, possibly). I think the code is easier to read and will generate less temporary garbage if the wrapper objects are removed. I think the change will also remain interoperable between versions since the byte-stream is unchanged. Any objections to making this change? - -chris -BEGIN PGP SIGNATURE- Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/ iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl69aFEACgkQHPApP6U8 pFiiGA/+OTShGMP1QvzP9rINT8hyrjhoiXTxCN6cfazQZ3Q8UUXAFA6514tLLkli 3FBfu6CWyAe1S8WvzgkeWg0UospfKjSi3pod/uVjF9Bo4JYyPAe39FV8k74Suotk HpQNbrrFMp7MeQowXdtns/ua8F+uo77JXTHrdc3eZIhBpfiyyyPQLaC73r/djMwf v/0iDF/SBAL98fTQsnTqeFVGJGBUkHS1Yvuhr1DQ+I6gpSRn+wUGlvUmrxaNF6J6 opYfBpU53L/2skjN7yC/DC5pnYbgRRzKdoNKzgrNbEbK9dyqEztr4N82+8VdIccj BJJA+7LqYDkVvrrTSCBL8hTlWr10P609rwX7t+/LHl0SzBVdsdiZurpBD/SRZXbQ nNU2n2DauAVUDUsKoLR/MvzpGVW3cNJNOqMX8mscA9RkLJwfWTnrohD7YFXtj6iv D03ekPpOBGSF1TX6JAjgDuciSPD2/Z9NV6wR1yKcfjm/rKkoAnv/orP/ccTsuXnq fggNFZQAmfp93QJFf2G3wntmR/3fCWjETVWT5CxyTxSdn/Zmj08P2lKiyRUriLd1 4kGnNxLSFgo/UWIgoFaPeITbkupmI9rGQq+LZM1UlnhoHxWj3vVOdCN/Zu+3OpLQ rFD5YTunZmHDBIcbtHbOmHeAGq7VU1BpvJ7V50jz9LW6OoX6GfQ= =vEuO -END PGP SIGNATURE- - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org