Services & Resources / Wolfram Forums
-----
 /
MathGroup Archive
2005
*January
*February
*March
*April
*May
*June
*July
*August
*September
*October
*November
*December
*Archive Index
*Ask about this page
*Print this page
*Give us feedback
*Sign up for the Wolfram Insider

MathGroup Archive 2005

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: JLink / java.io.ObjectInputStream.redObject[] - ClassNotFoundException

  • To: mathgroup at smc.vnet.net
  • Subject: [mg57677] Re: [mg57608] JLink / java.io.ObjectInputStream.redObject[] - ClassNotFoundException
  • From: Todd Gayley <tgayley at wolfram.com>
  • Date: Fri, 3 Jun 2005 05:35:10 -0400 (EDT)
  • Sender: owner-wri-mathgroup at wolfram.com

Felix,

You are correct about the casue of the problem. When Java deserializes an 
object, it tries to load the class of the object using the classloader that 
loaded the currently-running class. When you call ois@readObject[], the 
code that is performing this call is part of J/Link's internals. J/Link's 
own classes are loaded by the "application" classloader, whereas all 
classes loaded from CLASSPATH or J/Link-specific application directories 
are loaded by J/Link's special classloader, called JLinkClassLoader. The 
application classloader doesn't know about the classes that 
JLinkClassLoader knows about (like the WEKA classes), so it cannot find 
them when it tries to deserialize a WEKA object.

The solution is straightforward if you have followed the above line of 
reasoning. Simply ensure that the Java code that is calling readObject() is 
not part of J/Link itself, but is instead code that was loaded into J/Link 
from CLASSPATH or other user-level locations, so that it will be loaded by 
JLinkClassLoader. What this means is that you need to write a trivial class 
that calls readObject():

    public class Deserializer {
        public static Object readObject(java.io.ObjectInputStream ois) 
throws Exception {
            return ois.readObject();
        }
    }

Put this class onto your CLASSPATH or anywhere else J/Link looks for user 
classes (such as a Java application directory). Then do this:

    fis = JavaNew[ "java.io.FileInputStream", 
"C:\\work\\mlf_develop\\WEKA\\algorithm.mod" ];
    ois = JavaNew[ "java.io.ObjectInputStream", fis ];
    LoadJavaClass["Deserializer"]; (* Deserializer is now loaded by the 
same classloader that loads WEKA classes. *)
    algin = Deserializer`readObject[ois]

There might be another way to tell Java which classloader to use when 
deserializing your objects, but this trick of creating a J/Link-loaded 
utility class to do the job works nicely.

It is probably an oversight that such a utility class is not built into 
J/Link (of course, we would have to make sure that this class was loaded by 
JLinkClassLoader like user classes are, not like the other internal parts 
of J/Link). Perhaps this will be added in the future.


Todd Gayley
Wolfram Research


At 04:16 AM 6/2/2005, Felix Kossak wrote:
>Hi,
>
>I have a little trouble with reading a Java object from file which I
>have myself serialized before (from the Mathematica environment). It
>works when I write a respective Java class by hand and execute it from
>command line, but the same code does not work within Mathematica - it
>produces a ClassNotFoundException.
>
>Does anyone here have respective experience with serializing /
>deserializing objects using J/Link?
>
>The point seems to be that I use an extra Java library (WEKA), which
>works perfectly for every other code I have tried so far, including
>serializing, just not for deserializing. But it cannot be WEKA's fault
>(as it works in another environment) - the class loader used in J/Link
>seems to be the problem.
>
>Here is some of the context and code:
>-------------------------------------
>
>InstallJava[
>     CommandLine -> "C:\\Program Files\\Java\\j2re1.4.2\\bin\\java.exe
>        -Xmx400m",
>     ClassPath -> ".;C:\\Program Files\\Weka\\Weka-3-4\\weka.jar"
>];
>
>(Weka 3.4 provides the extra Java library I use)
>
>This, amongst others, works:
>----------------------------
>
>algorithm = JavaNew[
>     "weka.classifiers.functions.MultilayerPerceptron" ];
>algorithm@buildClassifier[ wekaDataSet ];
>
>...
>
>os = JavaNew[
>     "java.io.FileOutputStream",
>     "C:\\work\\mlf_develop\\WEKA\\algorithm.mod"
>];
>oos = JavaNew[ "java.io.ObjectOutputStream", os ];
>oos@writeObject[ algorithm ];
>oos@flush[];
>oos@close[];
>
>This, however, fails:
>=====================
>
>fis = JavaNew[
>     "java.io.FileInputStream",
>     "C:\\work\\mlf_develop\\WEKA\\algorithm.mod"
>];
>ois = JavaNew[ "java.io.ObjectInputStream", fis ];
>
>algin = ois@readObject[]
>
>It produces the following error messages:
>-----------------------------------------
>
>Java::excptn: A Java exception occurred: java.lang.ClassNotFoundException: \
>weka.classifiers.functions.MultilayerPerceptron
>         at java.net.URLClassLoader$1.run(Unknown Source)
>         at java.security.AccessController.doPrivileged(Native Method)
>         at java.net.URLClassLoader.findClass(Unknown Source)
>         at java.lang.ClassLoader.loadClass(Unknown Source)
>         at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
>         at java.lang.ClassLoader.loadClass(Unknown Source)
>         at java.lang.ClassLoader.loadClassInternal(Unknown Source)
>         at java.lang.Class.forName0(Native Method)
>         at java.lang.Class.forName(Unknown Source)
>         at java.io.ObjectInputStream.resolveClass(Unknown Source)
>         at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
>         at java.io.ObjectInputStream.readClassDesc(Unknown Source)
>         at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
>         at java.io.ObjectInputStream.readObject0(Unknown Source)
>         at java.io.ObjectInputStream.readObject(Unknown Source)
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
>         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source).
>
>$Failed
>
>I also tried to instantiate the variable 'algin' before reading:
>
>algin = JavaNew[ "weka.classifiers.functions.MultilayerPerceptron" ];
>
>but that doesn't help either.
>
>
>Thanks a lot for any help,
>Felix


  • Prev by Date: Re: Re: Re: Limit of list
  • Next by Date: Re: Re: Re: Limit of list
  • Previous by thread: JLink / java.io.ObjectInputStream.redObject[] - ClassNotFoundException
  • Next by thread: CellPrint with text, table and graphics