This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

invocation interface


Quoth Per Bothner on , 14 May:
: I'm taking a look at a working Java invocation interface,

I've hacked an invokation scheme, which is closely linked with my app,
and hasn't been tested (and so will change when I test today).
I'd rather use a real invokation API.  If there's anything I
can do to help, please tap me.  I don't understand the thread
model in gcj yet, however (one of the reasons why I expect
my code to require changes).

I'll append my code, in case it is of any use or interest.

Template for invokation:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>

#include <sys/types.h>

#include <java-props.h>
#include <jvm.h>

#include <java/lang/Throwable.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/OutOfMemoryError.h>

#include <java/lang/Runtime.h>
#include <gnu/gcj/runtime/FileDeleter.h>

#include <java/lang/Thread.h>
#include <java/lang/ThreadGroup.h>
#include <gnu/gcj/runtime/FirstThread.h>

#include "gcj-invoke.h"

//
// globals
//

property_pair *_Jv_Environment_Properties = 0;

static char * _Jv_execName = 0;

const char **_Jv_argv = 0;
int _Jv_argc = 0;


void
jvm_shutdown() {
  _Jv_ThreadWait ();

  int status = (int) java::lang::ThreadGroup::had_uncaught_exception;
    
  java::lang::Runtime *rt = java::lang::Runtime::getRuntime();
  rt->_exit(status);
  rt->runFinalization();
  gnu::gcj::runtime::FileDeleter::deleteOnExitNow();
}


static char *
next_property_key (char *s, size_t *length)
{
  size_t l = 0;

  while (isspace (*s)) s++;

  if (*s == 0 || *s == ':' || *s == '=')
    return 0;

  while (s[l] != 0 && ! isspace (s[l]) && s[l] != ':' && s[l] != '=') {
    if (s[l] == '\\' && s[l+1] != 0)
      l++;
    l++;
  }

  *length = l;

  return s;
}

static char *
next_property_value (char *s, size_t *length)
{
  size_t l = 0;

  while (isspace (*s)) s++;

  if (*s == ':' || *s == '=')
    s++;

  while (isspace (*s)) s++;

  if (*s == 0)
    return 0;

  while (s[l] != 0 && ! isspace (s[l]) && s[l] != ':' && s[l] != '=') {
    if (s[l] == '\\'
	&& s[l+1] != 0)
      l += 2;
    else
      l++;
  }

  *length = l;

  return s;
}

static void
get_env_properties(const char *varname) {
  if (!varname)
    return;

  char *props = getenv(varname);

  if (!props)
    return;

  char *p = props;
  size_t length;
  size_t property_count = 0;

  // count property values.
  while (p && (p = next_property_key (p, &length))) {
    p += length;
    p = next_property_value (p, &length);
    if (p)
      p += length;
    property_count++;
  }

  // Allocate an array of property value/key pairs.
  _Jv_Environment_Properties = 
    (property_pair *) malloc(sizeof(property_pair) * (property_count + 1));
  
  // initialize _Jv_Properties
  p = props;
  property_count = 0;
  while (p && (p = next_property_key (p, &length))) {
    _Jv_Environment_Properties[property_count].key = p;
    _Jv_Environment_Properties[property_count].key_length = length;
    
    // Skip to the end of the key
    p += length;
    p = next_property_value (p, &length);
      
    _Jv_Environment_Properties[property_count].value = p;
    _Jv_Environment_Properties[property_count].value_length = length;
    
    if (p)
      p += length;
    
    property_count++;
  }

  memset ((void *) &_Jv_Environment_Properties[property_count], 0, sizeof (property_pair));

  size_t i = 0;

  // Null terminate the strings.
  while (_Jv_Environment_Properties[i].key) {
    _Jv_Environment_Properties[i].key[_Jv_Environment_Properties[i].key_length] = 0;
    _Jv_Environment_Properties[i++].value[_Jv_Environment_Properties[i].value_length] = 0;
  }
}


static java::lang::NullPointerException *nullp;
static java::lang::OutOfMemoryError *no_memory;

#ifndef WIN32

static void
catch_segv(int _dummy) {
  java::lang::Throwable *throwable = (java::lang::Throwable *)nullp;
  throwable->fillInStackTrace ();
  _Jv_Throw (throwable);
}

#else

extern "C" int* win32_get_restart_frame (void *);

LONG CALLBACK
win32_exception_handler (LPEXCEPTION_POINTERS e)
{
  int* setjmp_buf;
  if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)   
    setjmp_buf = win32_get_restart_frame (nullp);
  else
    return EXCEPTION_CONTINUE_SEARCH;

  e->ContextRecord->Ebp = setjmp_buf[0];
  e->ContextRecord->Eip = setjmp_buf[1];
  e->ContextRecord->Esp = setjmp_buf[2];

  return EXCEPTION_CONTINUE_EXECUTION;
}

#endif


void
jvm_run(jclass klass, int argc, const char **argv)
{
  get_env_properties("PROPERTIES");

  _Jv_argv = argv;
  _Jv_argc = argc;

  // Turn stack trace generation off while creating exception objects.
  _Jv_InitClass (&java::lang::Throwable::class$);

  java::lang::Throwable::trace_enabled = 0;
  
  nullp = new java::lang::NullPointerException ();
  no_memory = new java::lang::OutOfMemoryError;

  java::lang::Throwable::trace_enabled = 1;

#ifndef WIN32

  signal(SIGPIPE, SIG_IGN);
  signal(SIGSEGV, catch_segv);

#else

  WSADATA data;
  if (WSAStartup (MAKEWORD (1, 1), &data)) {
    // MessageBox (NULL, "Error initialising winsock library.", "Error", MB_OK | MB_ICONEXCLAMATION);
    fprintf(stderr,"Winsock initialization error in JVM\n");
    fflush(stderr);
  }

  // Install exception handler
  SetUnhandledExceptionFilter (win32_exception_handler);

#endif /* USE_WIN32_SIGNALLING */

  _Jv_JNI_Init ();
  _Jv_ThisExecutable (argv[0]);

  jobject arg_vec = JvConvertArgv(argc-1,argv+1);
  java::lang::Thread *main_thread = new gnu::gcj::runtime::FirstThread (klass, arg_vec);

  main_thread->start();
}


typedef struct class_association {
  char *name;
  int *addr;
} class_association_t;

#include "classtable_decl.h"

static class_association_t classtable[] = {
#include "classtable_defn.i"
  { 0, 0, },
};

static jclass 
classtable_lookup(const std::string& class_name) {
  const char *cmp = class_name.c_str();
  class_association_t *ptr = &classtable[0];

  if (!cmp || !*cmp)
    return 0;

  while (ptr->name != 0) {
    if (!strcmp(cmp,ptr->name))
      return (jclass)(ptr->addr);
  }

  return 0;
}


int 
jvm_invoke(const std::string & class_name, const std::list<std::string> & arglist) {

  // locate the class object
  jclass klass = classtable_lookup(class_name);
  if (!klass )
    return -1;

  // copy arg list
  int argc = arglist.size();
  const char **argv = (const char **)malloc(sizeof(char *)*argc);
  int i = 0;
  std::list<std::string>::const_iterator iter = arglist.begin();
  while (i<argc) {
    argv[i++] = strdup(iter->c_str());
    iter++;
  }
  
  // invoke the class main
  jvm_run(klass,argc,argv);

  // free the arg list
  while (argc--) 
    free((void *)argv[argc]);
  free(argv);

  return 0;
}

generated includes:

extern int _ZN3com9swarmcast10bareserver10BareServer6class$E ;
extern int _ZN3com9swarmcast10bareclient10BareClient6class$E ;
extern int _ZN3com9swarmcast8protocol16CommandConverter6class$E ;
extern int _ZN3com9swarmcast4mesh8MetaInfo6class$E ;
extern int _ZN3com9swarmcast6client14AbstractClient6class$E ;
extern int _ZN3com9swarmcast4util8RangeSet6class$E ;
extern int _ZN3com9swarmcast4util17RandomPermutation6class$E ;
extern int _ZN3com9swarmcast4util17FilteringIterator6class$E ;
{ "com.swarmcast.bareserver.BareServer", &_ZN3com9swarmcast10bareserver10BareServer6class$E, },
{ "com.swarmcast.bareclient.BareClient", &_ZN3com9swarmcast10bareclient10BareClient6class$E, },
{ "com.swarmcast.protocol.CommandConverter", &_ZN3com9swarmcast8protocol16CommandConverter6class$E, },
{ "com.swarmcast.mesh.MetaInfo", &_ZN3com9swarmcast4mesh8MetaInfo6class$E, },
{ "com.swarmcast.client.AbstractClient", &_ZN3com9swarmcast6client14AbstractClient6class$E, },
{ "com.swarmcast.util.RangeSet", &_ZN3com9swarmcast4util8RangeSet6class$E, },
{ "com.swarmcast.util.RandomPermutation", &_ZN3com9swarmcast4util17RandomPermutation6class$E, },
{ "com.swarmcast.util.FilteringIterator", &_ZN3com9swarmcast4util17FilteringIterator6class$E, },

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]