Dear all,

I wrote a plugin codes for Hadoop, which calls the interfaces
in Cpp-built .so library. The plugin codes are written in java,
so I prepared a JNI class to encapsulate the C interfaces.

The java codes can be executed successfully when I compiled
it and run it standalone. However, it does not work when I embedded
in Hadoop. The exception shown out is (found in Hadoop logs):


------------  screen dump  ---------------------

# grep myClass logs/* -r
logs/hadoop-hadoop-tasktracker-testbed0.container.org.out:Exception in
thread "JVM Runner jvm_200904261632_0001_m_-1217897050 spawned."
java.lang.UnsatisfiedLinkError:
org.apache.hadoop.mapred.myClass.myClassfsMount(Ljava/lang/String;)I
logs/hadoop-hadoop-tasktracker-testbed0.container.org.out:      at
org.apache.hadoop.mapred.myClass.myClassfsMount(Native Method)
logs/hadoop-hadoop-tasktracker-testbed0.container.org.out:Exception in
thread "JVM Runner jvm_200904261632_0001_m_-1887898624 spawned."
java.lang.UnsatisfiedLinkError:
org.apache.hadoop.mapred.myClass.myClassfsMount(Ljava/lang/String;)I
logs/hadoop-hadoop-tasktracker-testbed0.container.org.out:      at
org.apache.hadoop.mapred.myClass.myClassfsMount(Native Method)
...

--------------------------------------------------------

It seems the library can not be loaded in Hadoop. My codes
(myClass.java) is like:


---------------  myClass.java  ------------------

public class myClass
{

        public static final Log LOG =
                    LogFactory.getLog("org.apache.hadoop.mapred.myClass");


        public myClass()   {

                try {
                        //System.setProperty("java.library.path",
"/usr/local/lib");

                        /* The above line does not work, so I have to
do something
                         * like following line.
                         */
                        addDir(new String("/usr/local/lib"));
                        System.loadLibrary("myclass");
                }
                catch(UnsatisfiedLinkError e) {
                        LOG.info( "Cannot load library:\n " +
                                e.toString() );
                }
                catch(IOException ioe) {
                        LOG.info( "IO error:\n " +
                                ioe.toString() );
                }

        }

        /* Since the System.setProperty() does not work, I have to add the 
following
         * function to force the path is added in java.library.path
         */
        public static void addDir(String s) throws IOException {

            try {
                        Field field =
ClassLoader.class.getDeclaredField("usr_paths");
                         field.setAccessible(true);
                        String[] paths = (String[])field.get(null);
                        for (int i = 0; i < paths.length; i++) {
                            if (s.equals(paths[i])) {
                                return;
                            }
                        }
                        String[] tmp = new String[paths.length+1];
                        System.arraycopy(paths,0,tmp,0,paths.length);
                        tmp[paths.length] = s;

                        field.set(null,tmp);
                    } catch (IllegalAccessException e) {
                        throw new IOException("Failed to get
permissions to set library path");
                    } catch (NoSuchFieldException e) {
                        throw new IOException("Failed to get field
handle to set library path");
            }
        }

        public native int myClassfsMount(String subsys);
        public native int myClassfsUmount(String subsys);


}

--------------------------------------------------------


I don't know what missed in my codes and am wondering whether there are any
rules in Hadoop I should obey if I want to  achieve my target.

FYI, the myClassfsMount() and myClassfsUmount() will open a socket to call
services from a daemon. I would better if this design did not cause the fail in
my codes.


Any comments?


Thanks in advance,

Ian

Reply via email to