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