Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JRuby does not follow ObjectInputStream casting convention #2226

Closed
tbruce opened this issue Nov 23, 2014 · 4 comments
Closed

JRuby does not follow ObjectInputStream casting convention #2226

tbruce opened this issue Nov 23, 2014 · 4 comments

Comments

@tbruce
Copy link

tbruce commented Nov 23, 2014

(insert not-a-Java-programmer disclaimer here).

This code:

ObjectInputStream ois = ObjectInputStream.new(FileInputStream(f));
myDeserializedBlahObject = (Blah) ois.readObject;

seems to be an idiom; the cast invokes the use of a private Blah.readObject method to pull complex objects off the stream . JRuby, on the other hand, appears to try to cast the first non-primitive object in the stream to type Blah, and can't.

@headius
Copy link
Member

headius commented Nov 23, 2014

The cast here (in Java) actually does nothing special other than confirm the object is of type Blah and cause subsequent bytecode to see it as a Blah. The results of calling ObjectInputStream#readObject would be unchanged.

Can you show a runnable example that fails?

@tbruce
Copy link
Author

tbruce commented Nov 24, 2014

I can try. It would require a lot of setup, but I'll try to put together the most slimmed-down version I can. The Java side is extensive, and not mine. (thanks for looking, though)

@tbruce
Copy link
Author

tbruce commented Nov 24, 2014

This won't be runnable without a bunch of other stuff and a fairly lengthy setup. Perhaps you'll get an idea just by looking at the source (there's a fair chance of dumb rookie errors on my part). I don't know if it's noteworthy or not, but InstanceList does not appear directly as a class in either the serialization or deserialization methods, but it could be embedded in another object (not clear to me from the source whether it might be, but if it is, it's probably in the first ArrayList read by ParallelTopicModel::readObject.

JRuby side

class JCaseTagger
  def initialize(tmodel_fn = DEFAULT_TRAINED_MODEL_FN)
    myfile = java.io.File.new(tmodel_fn)
    @model = Java::CcMalletTopics::ParallelTopicModel::read(myfile)
  end
end

Java side

public static ParallelTopicModel read (File f) throws Exception {

        ParallelTopicModel topicModel = null;

        ObjectInputStream ois = new ObjectInputStream (new FileInputStream(f));
        topicModel = (ParallelTopicModel) ois.readObject();
        ois.close();

        topicModel.initializeHistograms();

        return topicModel;
    }

    private void readObject (ObjectInputStream in) throws IOException, ClassNotFoundException {

        int version = in.readInt ();

        data = (ArrayList<TopicAssignment>) in.readObject ();
        alphabet = (Alphabet) in.readObject();
        topicAlphabet = (LabelAlphabet) in.readObject();
        /* ... many more reads of primitive objects follow, included for completeness*/
              numTopics = in.readInt();

        topicMask = in.readInt();
        topicBits = in.readInt();

        numTypes = in.readInt();

        alpha = (double[]) in.readObject();
        alphaSum = in.readDouble();
        beta = in.readDouble();
        betaSum = in.readDouble();

        typeTopicCounts = (int[][]) in.readObject();
        tokensPerTopic = (int[]) in.readObject();

        docLengthCounts = (int[]) in.readObject();
        topicDocCounts = (int[][]) in.readObject();

        numIterations = in.readInt();
        burninPeriod = in.readInt();
        saveSampleInterval = in.readInt();
        optimizeInterval = in.readInt();
        showTopicsInterval = in.readInt();
        wordsPerTopic = in.readInt();

        saveStateInterval = in.readInt();
        stateFilename = (String) in.readObject();

        saveModelInterval = in.readInt();
        modelFilename = (String) in.readObject();

        randomSeed = in.readInt();
        formatter = (NumberFormat) in.readObject();
        printLogLikelihood = in.readBoolean();

        numThreads = in.readInt();
       }

Stack trace from IDE

Fast Debugger (ruby-debug-ide 0.4.23.beta1, ruby-debug-base 0.10.5.rc9) listens on 127.0.0.1:56510
cc/mallet/topics/ParallelTopicModel.java:1659:in `read': java.lang.ClassCastException: cc.mallet.types.InstanceList cannot be cast to cc.mallet.topics.ParallelTopicModel
    from java/lang/reflect/Method.java:606:in `invoke'
    from /Users/tom/RubymineProjects/CaseTagger/baby-jruby.rb:44:in `initialize'
    from /Users/tom/RubymineProjects/CaseTagger/baby-jruby.rb:68:in `(root)'
    from org/jruby/debug/RubyDebugger.java:204:in `debug_load'
    from /Users/tom/.rvm/gems/jruby-1.7.16.1/gems/ruby-debug-ide-0.4.23.beta1/lib/ruby-debug-ide.rb:1:in `(root)'
    from /Users/tom/.rvm/gems/jruby-1.7.16.1/gems/ruby-debug-ide-0.4.23.beta1/lib/ruby-debug-ide.rb:86:in `debug_program'
    from org/jruby/RubyKernel.java:1081:in `load'
    from /Users/tom/.rvm/gems/jruby-1.7.16.1/gems/ruby-debug-ide-0.4.23.beta1/bin/rdebug-ide:110:in `(root)'

@tbruce
Copy link
Author

tbruce commented Nov 25, 2014

This turned out to be something entirely stupid. Let the ridicule commence.

@tbruce tbruce closed this as completed Nov 25, 2014
@enebo enebo added this to the Invalid or Duplicate milestone Dec 8, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants