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.
_______________________