Is there any reason why you can't just fork a process and do an exec from your
C program?  The parent can get the pid of it's child and stick that in
jboss.pid.

-vince

 On Wed, 20 Sep 2000, you wrote: > In bash, at least, there's an
environment variable that holds the > PID of the last process.  So you can
start jBoss and then echo the PID to > a file.  I'm not sure how standard this
is across shells. >     We should also implement a "quit" command like the
"stop" command, > which would solve the problem quite nicely.  However, I'm
waiting for > Rickard's input on how to stop the JVM from within...  This would
make it > quite easy too.  Don't kill yourself with ClassLoaders and JNI!
> 
> Aaron
> 
> On Wed, 20 Sep 2000, Ken Jenks wrote:
> > I'm trying to get jBoss to run every time Linux starts, and it's been quite 
> > an adventure.
> > 
> > We've worked out a script for use in /etc/rc.d/init.d/jboss, but launching 
> > a Java application this way has a big problem: you can't shut it down 
> > because you can't keep track of the PID.
> > 
> > So I wrote a C program wrapper that uses JNI to call jBoss, with the idea 
> > that killing the C program will kill the JVM it creates and hence kill off 
> > jBoss. It didn't work right away because JNI creates a null ClassLoader, 
> > and jBoss uses the ClassLoader to locate its resources.
> > 
> > So I had the C program use JNI to call another Java application, 
> > jbossd.java, which creates a ClassLoader then uses the new 
> > JbossdClassLoader to launch jBoss. But it doesn't work, it doesn't return 
> > an error message, and I'm stuck in ClassLoader Hell.
> > 
> > 
> > Here are the three parts, the startup script, the C program, and the Java 
> > program.
> > 
> > First, the startup script, /etc/rc.d/init.d/jboss:
> > 
> > #!/bin/sh
> > #
> > # chkconfig: 4 85 15
> > # description: jbossd is the Jboss daemon
> > # processname: jbossd
> > # pidfile: /var/run/jbossd.pid
> > 
> > # Source function library.
> > . /etc/rc.d/init.d/functions
> > 
> > # See how we were called.
> > case "$1" in
> >   start)
> >         # Start daemons.
> >         echo "jbossd"
> >         PATH=$PATH:/usr/java/jdk1.3/bin
> >         export PATH
> > 
> >         
>CLASSPATH=/usr/java/jdk1.3/lib:/usr/local/jboss/bin:/usr/local/jboss/bin/run.jar
> >         export CLASSPATH
> >         /usr/local/jboss/bin/jbossd &
> >         pidof jbossd > /var/run/jbossd.pid
> >         touch /var/lock/subsys/jbossd
> >         ;;
> >   stop)
> >         # Stop daemons.
> >         echo -n "Shutting down jbossd: "
> >         kill -USR1 `cat /var/run/jbossd.pid`
> >         rm -f /var/lock/subsys/jbossd
> >         ;;
> >   status)
> >          status jbossd
> >          ;;
> >   restart|reload)
> >          $0 stop
> >          $0 start
> >          ;;
> >   *)
> >         echo "Usage: jbossd {start|stop|restart|reload|status}"
> >         exit 1
> > esac
> > 
> > 
> > 
> > Here's the JNI wrapper, /usr/local/jboss/bin/jbossd.c:
> > 
> > #include <jni.h>
> > #include <sys/types.h>
> > #include <sys/stat.h>
> > #include <sys/wait.h>
> > #include <errno.h>
> > #include <fcntl.h>
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <string.h>
> > #include <syslog.h>
> > #include <unistd.h>
> > 
> > /* The jbossd daemon launches jBoss, a Java application. When the daemon is
> >   * killed, jBoss is shut down as well.
> >   *
> >   * Based on invoke.c from
> >   * <http://java.sun.com/docs/books/tutorial/native1.1/invoking/invo.html>
> >   *
> >   * Compile with:
> >   *  gcc -lpthread \
> > -I /usr/java/jdk1.3/include \
> > -I /usr/java/jdk1.3/include/linux \
> > -o jbossd \
> > jbossd.c \
> > /usr/java/jdk1.3/jre/lib/i386/classic/libjvm.so \
> > /usr/java/jdk1.3/jre/lib/i386/libjava.so \
> > /usr/java/jdk1.3/jre/lib/i386/libverify.so \
> > /usr/java/jdk1.3/jre/lib/i386/native_threads/libhpi.so
> >   *
> >   * Then to run the daemon, edit the file "/etc/ld.so.conf" and add the
> >   * following lines:
> > 
> > /usr/java/jdk1.3/jre/lib/i386/classic
> > /usr/java/jdk1.3/jre/lib/i386
> > /usr/java/jdk1.3/jre/lib/i386/native_threads
> > 
> >   * Then run the command "ldconfig".
> >   *
> >   */
> > 
> > #ifdef _WIN32
> > #define PATH_SEPARATOR ';'
> > #else /* UNIX */
> > #define PATH_SEPARATOR ':'
> > #endif
> > 
> > #define USER_CLASSPATH "/usr/local/jboss/bin:/usr/local/jboss/bin/run.jar" 
> > /* wh
> > ere jbossd.class is */
> > 
> > JavaVM *jvm;
> > 
> > int check_cla(int argc, char* argv[])
> > {
> >    if (argc != 1) {
> >      return -1;
> >    }
> > 
> >    return 0;
> > }
> > 
> > /*
> > int daemon_init(void)
> > {
> >    pid_t pid;
> > 
> >    pid = fork();
> >    if (pid < 0) {
> >      return -1;
> >    } else if (pid != 0) {
> >      exit(0); // parent exits
> >    }
> > 
> >    setsid();
> >    chdir("/");
> >    umask(0);
> > 
> >    return 0;
> > }
> > */
> > 
> > int main(int argc, char* argv[]) {
> > 
> >    JNIEnv *env;
> >    JDK1_1InitArgs vm_args;
> >    jint res;
> >    jclass cls;
> >    jmethodID mid;
> >    jstring jstr;
> >    jobjectArray args;
> >    char classpath[4096];
> > 
> >    if (check_cla(argc, argv)) {
> >      fprintf(stderr, "%s: Usage error\n", argv[0]);
> >      return -1;
> >    }
> > 
> > /*
> >    if (daemon_init()) {
> >      fprintf(stderr, "%s: Error initializing jBoss daemon\n", argv[0]);
> >      return -1;
> >    }
> > */
> > 
> >    vm_args.version = 0x00010001;
> > 
> >    JNI_GetDefaultJavaVMInitArgs(&vm_args);
> > 
> >    /* Append USER_CLASSPATH to the end of default system class path */
> >    sprintf(classpath, "%s%c%s",
> >      vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
> >    vm_args.classpath = classpath;
> > 
> >    /* Create the Java VM */
> >    res = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args);
> >    if (res < 0) {
> >      fprintf(stderr, "%s: Can't create Java VM\n", argv[0]);
> >      exit(1);
> >    }
> > 
> >    if (env == 0) {
> >      fprintf(stderr, "%s: Can't find Java environment\n", argv[0]);
> >      exit(3);
> >    }
> > 
> >    cls = (*env)->FindClass(env,"jbossd");
> > 
> >    if (cls == 0) {
> >      fprintf(stderr, "%s: Can't find class jbossd\n", argv[0]);
> >      exit(4);
> >    }
> > 
> >    mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
> >    if (mid == 0) {
> >      fprintf(stderr, "%s: Can't find static method jbossd.main\n", argv[0]);
> >      exit(5);
> >    }
> > 
> >    jstr = (*env)->NewStringUTF(env, "");
> >    if (jstr == 0) {
> >      fprintf(stderr, "%s: Can't create jstr\n",argv[0]);
> >      exit(6);
> >    }
> > 
> >    args = (*env)->NewObjectArray(env, 1,
> >      (*env)->FindClass(env, "java/lang/String"), jstr);
> >    if (args == 0) {
> >      fprintf(stderr, "%s: Can't create args array\n",argv[0]);
> >      exit(7);
> >    }
> > 
> >    // Finally, call the main method of class jbossd
> > 
> >    (*env)->CallStaticVoidMethod(env, cls, mid, args);
> > 
> >    //(*jvm)->DestroyJavaVM(jvm);
> > 
> >    return 0;
> > }
> > 
> > 
> > 
> > Here's the Java application that creates a ClassLoader and launches jBoss, 
> > /usr/local/jboss/bin/jbossd.java:
> > 
> > // jbossd.java
> > //
> > // Launches jBoss. Called using JNI from jbossd.c.
> > //
> > // Compile with:
> > //  javac -classpath run.jar jbossd.java
> > //
> > 
> > import java.util.Hashtable;
> > 
> > public class jbossd {
> >    jbossd() {
> > 
> >      // The args passed in from JNI are screwy. We don't need them
> >      // anyway, so we'll invent our own set of blank args and send
> >      // them along.
> > 
> >      String newArgs[] = new String[1];
> >      newArgs[0] = new String("");
> > 
> >      try {
> >        System.err.println("jbossd: Starting");
> > 
> >        // This didn't work:
> >        //   org.jboss.Main m = new org.jboss.Main();
> >        // When I tried it, jBoss started, but it died when org.jboss.Main
> >        // tried to use its ClassLoader. It turns out that JNI has a null
> >        // ClassLoader. So here's my attempt to create a classloader.
> > 
> >        JbossdClassLoader loader = new JbossdClassLoader();
> >        org.jboss.Main m = 
> > (org.jboss.Main)loader.findClass("org.jboss.Main").newI
> > nstance();
> > 
> >        m.main(newArgs);
> >        System.err.println("jbossd: Launched.");
> >      } catch (java.lang.Exception e) {
> >        System.err.println("jbossd: Exception: " + e);
> >        e.printStackTrace();
> >      }
> >    }
> > 
> >    public static void main(String[] args) {
> >      jbossd j = new jbossd();
> >    }
> > 
> >    class JbossdClassLoader extends ClassLoader {
> >      public JbossdClassLoader() {
> >        super();
> >      }
> > 
> >      public Class findClass(String name) throws ClassNotFoundException {
> >        return loadClass(name, true );
> >      }
> > 
> >      protected Class loadClass(String name, boolean resolve)
> >        throws ClassNotFoundException {
> > 
> >        Object o = cache.get(name);
> >        if (o != null) {
> >          if (o instanceof Class) {
> >            return (Class) o;
> >          }
> >        }
> > 
> >        Class c = findSystemClass(name);
> >        cache.put(name, c);
> >        if (resolve) {
> >          resolveClass(c);
> >        }
> >        return c;
> >      }
> > 
> >      private Hashtable cache = new Hashtable();
> >    }
> > }
> > 
> > Help!
> > 
> > -- Ken Jenks, http://abiblion.com/
> > 
> >     Tools for reading.
> > 
> >
-- 
_______________________
Vincent Sheffer
Director of Operations
Telkel, Inc.
_______________________

Reply via email to