Kryo.newInstance with constructor arguments

306 views
Skip to first unread message

mongonix

unread,
Jun 8, 2012, 12:00:29 PM6/8/12
to kryo-...@googlegroups.com
Hi Nate,

Question:
Currently, Kryo only has newInstance which does not allow for non-zero-arg constructors. But for zero-arg constructors it works nicely and caches them.

Would it be possible to add support non-zero-arg constructors? I know that I can simply derive my class from Kryo and add/modify such a method. But I'm wondering if it is of a general interest.

The concrete use-case is like this:
Scala has two sorted collections called TreeSet and TreeMap. To be able to sort they need an ordering object as a constructor parameter. There is no other way to provide it to those objects.

Currently I implemented it by doing manual lookup of a corresponding constructor. It works, but it is slow, because it does not cache this constructor. I can implement caching without problems. But when I look at my code I see that I'd essentially (re)implement Kryo.newInstance() with its caching mechanism + support for constructor arguments. So, I thought I'd ask you what you think about it.

-Leo

Nate

unread,
Jun 8, 2012, 2:26:34 PM6/8/12
to kryo-...@googlegroups.com
On Fri, Jun 8, 2012 at 9:00 AM, mongonix <romi...@gmail.com> wrote:
Hi Nate,

Question:
Currently, Kryo only has newInstance which does not allow for non-zero-arg constructors. But for zero-arg constructors it works nicely and caches them.

Would it be possible to add support non-zero-arg constructors? I know that I can simply derive my class from Kryo and add/modify such a method. But I'm wondering if it is of a general interest.

It is supported through Objenesis (with caveats):
https://code.google.com/p/kryo/#Object_creation
 

The concrete use-case is like this:
Scala has two sorted collections called TreeSet and TreeMap. To be able to sort they need an ordering object as a constructor parameter. There is no other way to provide it to those objects.

Currently I implemented it by doing manual lookup of a corresponding constructor. It works, but it is slow, because it does not cache this constructor. I can implement caching without problems. But when I look at my code I see that I'd essentially (re)implement Kryo.newInstance() with its caching mechanism + support for constructor arguments. So, I thought I'd ask you what you think about it.

You could write a serializer for these classes. You can extend CollectionSerializer or MapSerializer and override create() to construct your objects. Note these methods were added recently to match FieldSerializer in SVN revision 270.

-Nate

mongonix

unread,
Jun 8, 2012, 3:07:58 PM6/8/12
to kryo-...@googlegroups.com

On Friday, June 8, 2012 8:26:34 PM UTC+2, Nate wrote:
On Fri, Jun 8, 2012 at 9:00 AM, mongonix  wrote:
Hi Nate,

Question:
Currently, Kryo only has newInstance which does not allow for non-zero-arg constructors. But for zero-arg constructors it works nicely and caches them.

Would it be possible to add support non-zero-arg constructors? I know that I can simply derive my class from Kryo and add/modify such a method. But I'm wondering if it is of a general interest.

It is supported through Objenesis (with caveats):
https://code.google.com/p/kryo/#Object_creation
 

Yes. I'm aware of it.
 

The concrete use-case is like this:
Scala has two sorted collections called TreeSet and TreeMap. To be able to sort they need an ordering object as a constructor parameter. There is no other way to provide it to those objects.

Currently I implemented it by doing manual lookup of a corresponding constructor. It works, but it is slow, because it does not cache this constructor. I can implement caching without problems. But when I look at my code I see that I'd essentially (re)implement Kryo.newInstance() with its caching mechanism + support for constructor arguments. So, I thought I'd ask you what you think about it.

You could write a serializer for these classes. You can extend CollectionSerializer or MapSerializer and override create() to construct your objects. Note these methods were added recently to match FieldSerializer in SVN revision 270.

Create is nice. But it doesn't take any arguments at the moment. How am I supposed to pass them? Via fields of my serializer instance?

Another observation:
Kryo.newInstance has all the machinery (e.g. caching of instantiators, etc) required for invocation of no-arg constructors. It would be nice to be able to reuse it, instead of implementing my own copy of such a mechanism. This is why I asked if Kryo.newInstance should be extended directly. Then all serializers could re-use the machinery. By extending it mean something like:
- allow to provide varargs arguments, to indicate which constructor you have in mind
- Instantiators may now refer to constructors with arguments, i.e. they cache constructor and number (and types?) of arguments
- instantiators are invoked with passed arguments

-Leo

Nate

unread,
Jun 8, 2012, 3:39:11 PM6/8/12
to kryo-...@googlegroups.com
On Fri, Jun 8, 2012 at 12:07 PM, mongonix <romi...@gmail.com> wrote:

The concrete use-case is like this:
Scala has two sorted collections called TreeSet and TreeMap. To be able to sort they need an ordering object as a constructor parameter. There is no other way to provide it to those objects.

Currently I implemented it by doing manual lookup of a corresponding constructor. It works, but it is slow, because it does not cache this constructor. I can implement caching without problems. But when I look at my code I see that I'd essentially (re)implement Kryo.newInstance() with its caching mechanism + support for constructor arguments. So, I thought I'd ask you what you think about it.

You could write a serializer for these classes. You can extend CollectionSerializer or MapSerializer and override create() to construct your objects. Note these methods were added recently to match FieldSerializer in SVN revision 270.

Create is nice. But it doesn't take any arguments at the moment. How am I supposed to pass them? Via fields of my serializer instance?

The arguments have to come from somewhere. Either read them from the input or make them available to your serializer somehow.
 

Another observation:
Kryo.newInstance has all the machinery (e.g. caching of instantiators, etc) required for invocation of no-arg constructors. It would be nice to be able to reuse it, instead of implementing my own copy of such a mechanism. This is why I asked if Kryo.newInstance should be extended directly. Then all serializers could re-use the machinery. By extending it mean something like:
- allow to provide varargs arguments, to indicate which constructor you have in mind
- Instantiators may now refer to constructors with arguments, i.e. they cache constructor and number (and types?) of arguments
- instantiators are invoked with passed arguments

If you know which constructor you want, do you really need reflection? I'm having trouble envisioning your use case.

Kryo#newInstance doesn't do anything except use the ObjectInstantiator on the Registration. You can use Registration#setInstantiator to customize how a type is constructed, without extending a serializer. If an instantiator isn't set explicitly, it gets one from Kryo#newInstantiator, which can be overridden. You can also subclass Registration and use Kryo#register(Registration) to store extra state per type.

-Nate

Reply all
Reply to author
Forward
0 new messages