4

I need to create an instances an instance of java.lang.Class that is otherwise identical to classOf[MyClass] but also has a SerialVersionUID, which MyClass does not have. MyClass is a Scala-2.10 class. One problem is that in Java SerialVersionUID is a static final while in Scala SerialVersionUID since Scala does not have statics.

If MyClass was a Java class I think I would be able do this using Javassist:

  val ctclass = javassist.ClassPool.getDefault().get("mypackagage.MyClass")
  val field = javassist.CtField.make(
      "private static final long serialVersionUID = 1L;",
      ctclass)
  ctclass.addField(field)
  val cls = ctclass.toClass()

However, this does not quiet work for Scala classes. I tried to use this in a ClassLoader for de-serialization. there were no compile or run time errors during deserialization, but the deserialized object is incomplete, so there must be some more subtle problem. The gory details are described here. Presumably the problem comes from how static final fields are dealt with in Scala and the fact that Javassist only understands Java. How can I do it so it is 100% correct for Scala classes using either Javassist or any other means.

Community
  • 1
  • 1
Daniel Mahler
  • 7,653
  • 5
  • 51
  • 90
  • Hello, could you elaborate on which tool you're using for de/serializing and in what ways your class is incomplete? Just a guess, but if the necessary info isn't in the bytecode, then isn't the only other place it could be is in the pickled Scala signature annotation [link](http://stackoverflow.com/questions/16456931/where-does-scala-store-information-that-cannot-be-represented-in-java)? Maybe you're missing a the correct info in the pickled Scala signature? (I solved a similar problem by writing my own Scala signature, and I'd like to see if that approach works more generally) – Julian Peeters Sep 14 '13 at 16:20
  • @Julian Peeters, I am using plain Java serialization. I know MyClass did not have a `serialVersionUID` specified in the source, so it is using the default hash based one. The problem was that the class was moved between packages in the library, which also changed it's default serialVersionUID even though the source for the class remained textually identical. I would be interested to see the problem & solution you refer to. – Daniel Mahler Sep 15 '13 at 01:02
  • My problem was that I was weary of transcribing large json schemas into Scala case classes and I solved it by defining and loading case classes at runtime to be instantiated w/ reflection [(under constr'n)](http://bit.ly/192xjUp). I used objectWeb's ASMifier and a whole lotta 'diff -y', but couldn't serialize the generated class until I gave it a proper Scala signature annotation. I was serializing with Salat which specifically mines the Scala sig, so maybe I'm just "looking for nails", but as a long shot I thought perhaps "incomplete" somehow means "missing the correct info in the Scala sig". – Julian Peeters Sep 15 '13 at 04:11
  • Were that a solution for you, currently I the tool is severely limited to case classes with only 1 field because of an [encoding issue](http://bit.ly/17XT5M8)(but might still work if your class is not a case class and is small), and only the pickle-maker is tested. And as of now it can't define `def`s dynamically, but it wouldn't be too terrible to add any 'def's by hand. – Julian Peeters Sep 15 '13 at 04:27
  • PS I'm fairly new at this, so please don't hesitate to advise. I'm new to Java serialization for example; [this](http://bit.ly/1eQyht3) seems to work for me (i.e. I'm not sure what is missing?) – Julian Peeters Sep 15 '13 at 04:28

1 Answers1

2

If I compile the following class:

@SerialVersionUID(1L)
object MyClass {
}

$ scalac MyCLass.scala

$ javap -cp MyClass$

Compiled from "MyClass.scala"
public final class MyClass$ {
  public static final MyClass$ MODULE$;
  public static final long serialVersionUID;
  public static {};
}

I'm not familiar with javaassist, but this shows where you need to put the additional field, FWIW.

philwalk
  • 634
  • 1
  • 7
  • 15