1 Reply Latest reply: Sep 23, 2010 10:18 PM by 843829 RSS

    invoking main from another class with the same jvm

    843829
      Is there a way to run the public static main(String args[]) method of another class?

      I'm trying to write a wrapper for java services on windows.

      I could just call something like
      Runtime.getRuntime().exec("java MyClass");
      but I want to use the environment I already have and not waste resources.

      Is there for example a way to invoke the main method on any class given the fq class name as a string?

      I realise this is a bit left of field, but there is a genuine need and the standard service loaders around have multiple problems.

      More specifically, I'm using a battery of HornetQ JMS standalone as well as other java message producer and consumer programs.
      I want to be able to run these as a Windows service run-as a network user.

      The solution I have uses .net to call a batch file which runs a jvm. This is not only wasteful but makes it impossible to reliably stop the correct jvm when it blocks on a network socket.
      It also suffers from a problem where the java process details are not locally accessible by jps or jconsole and causes jvisualvm to crash.

      Can anyone point me in the right direction?
        • 1. Re: invoking main from another class with the same jvm
          843829
          I used reflection like this:
              try {
                Method mainMethod = Class.forName(args[0])
                        .getDeclaredMethod("main", String[].class);
                 // Make sure that the method is public and static
                int modifiers = mainMethod.getModifiers();
                if ( !( Modifier.isPublic( modifiers )
                        && Modifier.isStatic( modifiers ) ) ) {
                  throw new ServiceException("The main method in class " + args[0]
                        + " must be declared public and static.");
                }
               // Build the application args array
                String[] appArgs = new String[args.length - 1];
                System.arraycopy(args, 1, appArgs, 0, appArgs.length);
                mainMethod.invoke(null, new Object[] { appArgs });
          
              } catch (ClassNotFoundException e) {
                throw new ServiceException(e);
              } catch (NoSuchMethodException e) {
                throw new ServiceException(e);
              } catch (IllegalAccessException e) {
                throw new ServiceException(e);
              } catch (InvocationTargetException e) {
                throw new ServiceException(e);
              }
          It's a little weak in the security area, but I could always run invoke inside a doPrivileged block with the same security manager permissions as the jar.
          Mind you, jps and jconsole still can't see the process if it's runAs a system user.
          Windblows it the flakiest piece of dog .... I've ever seen.