Class not found exception on hadoop local job tracker mode, and a patch for it

36 views
Skip to first unread message

Jung-gun Lim

unread,
Nov 13, 2009, 1:51:40 AM11/13/09
to cascading-user
Here is the error case:

try to run a cascading application with hadoop in local job tracker
mode;

$HADOOP_HOME/bin/hadoop jar my_app.jar my.cacascading.AppMain

with mapred.job.tracker set to 'local'.

-----


During running hadoop in local job tracker mode, hadoop RunJar
utility loads my_app.jar and registeres all the classeses on the
thread context classloader.


Since ObjectInputStream, which cascading.util.Util.deserializeBase64
method creates and uses, only uses the defining class loader of
cascading.util.Util, it cannot deserialize classes defined in
my_app.jar. It makes org.apache.hadoop.util.ReflectionUtils.setJobConf
fail.

You may think that this is not a common case; if I want to test a
cacading application in local, I can run it without hadoop RunJar. But
in the case that I want to switch the running mode between local mode
and distributed mode at runtime, I need to run my local jobs in this
way.

This patch, which makes ObjectInputStream try using thread context
classloader once, will make things all right and make cascading users
happy, including me.

can be applied on cascading 1.0.17-hadoop-0.19.1+ version:


--- cascading-1.0.17.old/src/core/cascading/util/Util.java 2009-11-08
06:19:53.000000000 +0900
+++ cascading-1.0.17.new/src/core/cascading/util/Util.java 2009-11-13
15:16:37.000000000 +0900
@@ -26,6 +26,7 @@
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
@@ -91,7 +92,21 @@
try
{
ByteArrayInputStream bytes = new ByteArrayInputStream
( Base64.decodeBase64( string.getBytes() ) );
- ObjectInputStream in = new ObjectInputStream( bytes );
+ ObjectInputStream in = new ObjectInputStream( bytes ) {
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException
+ {
+ String name = desc.getName();
+ try
+ {
+ return Class.forName(name, false, Thread.currentThread
().getContextClassLoader());
+ }
+ catch (ClassNotFoundException ex)
+ {
+ return super.resolveClass(desc);
+ }
+ }
+ };

return in.readObject();
}

Chris K Wensel

unread,
Nov 13, 2009, 6:55:56 PM11/13/09
to cascadi...@googlegroups.com
Cascading works great in 'local' mode. from the console and inside IDEs.

Are you sure you don't have something else going on?

ckw
> --
>
> You received this message because you are subscribed to the Google
> Groups "cascading-user" group.
> To post to this group, send email to cascadi...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/cascading-user?hl=
> .
>
>

--
Chris K Wensel
ch...@concurrentinc.com
http://www.concurrentinc.com

Jung-gun Lim

unread,
Nov 13, 2009, 8:25:13 PM11/13/09
to cascading-user
It works great inside IDEs, and from the console if I launch the
program directly:

java -classpath my_app.jar MyMainClass.main

But if I run the program with hadoop RunJar, in local mode:

hadoop jar my_app.jar MyMainClass.main

(mapred.job.tracker set to 'local' in runtime, or by mapred-site.xml)

The problem occurs.
> > For more options, visit this group athttp://groups.google.com/group/cascading-user?hl=

Chris K Wensel

unread,
Nov 13, 2009, 8:46:25 PM11/13/09
to cascadi...@googlegroups.com
What version of Hadoop?
>>> To post to this group, send email to cascading-
>>> us...@googlegroups.com.
>>> For more options, visit this group athttp://groups.google.com/group/cascading-user?hl=
>>> .
>>
>> --
>> Chris K Wensel
>> ch...@concurrentinc.comhttp://www.concurrentinc.com
>
> --
>
> You received this message because you are subscribed to the Google
> Groups "cascading-user" group.
> To post to this group, send email to cascadi...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/cascading-user?hl=

Jung-gun Lim

unread,
Nov 13, 2009, 9:20:23 PM11/13/09
to cascading-user
I was using hadoop-0.20.0, and I put cascading-core-1.0.17.jar into
$HADOOP_HOME/lib directory to be loaded on hadoop startup, not in
my_app.jar, to save spaces.

I made my custom input format and scheme classes and they were in
my_app.jar. They were unable to be deserialized through
ObjectInputStream while running FlowStep configuration, since they
were defined in Thread.currentThread().getContextClassLoader(), not in
the ObjectInputStream defining class loader
( ObjectInputStream.getClass().getClassLoader() ).

Chris K Wensel

unread,
Nov 14, 2009, 12:12:00 PM11/14/09
to cascadi...@googlegroups.com
I typically recommend against putting Cascading in the global classpath.

let me see if I can support this.

ckw
> For more options, visit this group at http://groups.google.com/group/cascading-user?hl=

Chris K Wensel

unread,
Nov 14, 2009, 6:36:44 PM11/14/09
to cascadi...@googlegroups.com
check out wip-1.0.18 and see if that works for you.

On Nov 13, 2009, at 6:20 PM, Jung-gun Lim wrote:

> For more options, visit this group at http://groups.google.com/group/cascading-user?hl=

Jung-gun Lim

unread,
Nov 16, 2009, 2:51:56 AM11/16/09
to cascading-user
works perfectly. thank you!
Reply all
Reply to author
Forward
0 new messages