This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
invocation interface
- To: per at bothner dot com
- Subject: invocation interface
- From: Tony Kimball <alk at pobox dot com>
- Date: Mon, 14 May 2001 16:01:55 -0500
- Cc: java at gcc dot gnu dot org
- References: <m2r8xs2b0r.fsf@kelso.bothner.com>
- Reply-To: alk at pobox dot com
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, },