Subject | Re: [Firebird-Architect] Re: Java Stored Procedures |
---|---|
Author | Jim Starkey |
Post date | 2005-10-21T14:19:08Z |
Roman Rokytskyy wrote:
load classes on demand, i.e the first actual reference. If a class is
referenced in code that has been executed, the class won't be loaded.
To do it any other way would impose a miserable startup cost as every
class in creation would have to be loaded before execution. Java was
designed from the beginning to load classes incrementally on an
as-needed basis.
specification requires any different behavior. If you have any doubts,
use a JVM the lists classes as they're loaded.
reserved, and is explicitly not open source.) When it doesn't find an
entrypoint, the stuff at the end dumps out function declarations and
skeletons into a file for inclusion in my JavaNativeMethods.cpp file.
Here's the class load code:
void JavaMethod::resolveEntrypoint(ENV_DCL)
{
char fullName [1024], *p = fullName;
for (char *q = "Java_"; *q;)
*p++ = *q++;
WCHAR *w = javaClass->className->string;
WCHAR *end;
for (end = w + javaClass->className->length; w < end; ++w)
*p++ = (*w == '/') ? '_' : (char) *w;
w = methodName->string;
*p++ = '_';
for (end = w + methodName->length; w < end;)
*p++ = (char) *w++;
*p = 0;
// Try to resolve name internally
if (nativeMethod = findNativeMethod (fullName))
return;
// Try to resolve it against known libraries
if (nativeMethod = (NativeFn) javaClass->java->resolveEntrypoint
(fullName, numberArgs))
return;
// Expand name to include signature
*p++ = '_';
*p++ = '_';
for (w = descriptor->string, end = w + descriptor->length, ++w;
w < end && *w != ')';)
{
char c = (char) *w++;
if (c == '_')
{ *p++ = '_'; *p++ = '1'; }
else if (c == '_')
{ *p++ = ';'; *p++ = '2'; }
else if (c == '_')
{ *p++ = '['; *p++ = '3'; }
else
*p++ = c;
}
*p = 0;
if (nativeMethod = (NativeFn) javaClass->java->resolveEntrypoint
(fullName, numberArgs))
return;
// Not going so good. Generate a template for an internal
// implementation, just in case.
FILE *output = fopen ("foo.cpp", "w");
if (output)
{
fprintf (output, "\n/* %s */\n\n", (const char *) javaClass->name);
JavaGenNative::genNativeMethods (javaClass, output, genPrototypes);
fprintf (output, "\n/* %s */\n\n", (const char *) javaClass->name);
JavaGenNative::genNativeMethods (javaClass, output, genHeader);
fprintf (output, "\n/* %s */\n\n", (const char *) javaClass->name);
JavaGenNative::genNativeMethods (javaClass, output, genBody);
fclose (output);
}
thread->unsatisfiedLinkError (ENV, "method \"%s\" (%s) of class \"%s\"",
(const char*) methodName->getString(),
(const char*) descriptor->getString(),
(const char*)
javaClass->className->getString());
}
NativeFn findNativeMethod (const char *name)
{
for (NativeMethod *method = hashTable [JString::hash (name, HASH_SIZE)];
method; method = method->collision)
if (!strcmp (name, method->name))
return method->fn;
return NULL;
}
--
Jim Starkey
Netfrastructure, Inc.
978 526-1376
>>Sure. The classloader loads stuff on demand. There is no way toI've never seen a class loader that loaded all referenced classes. JVMs
>>force it to load all dependencies of a class.
>>
>>
>
>Can you explain this a bit more? JVM specification requires the
>implementation to follow the strict class initialization procedure.
>Java applications rely on this late binding behavior. But that does
>not mean that particular classloader cannot cache binary definitions
>in memory to avoid disk access.
>
>
load classes on demand, i.e the first actual reference. If a class is
referenced in code that has been executed, the class won't be loaded.
To do it any other way would impose a miserable startup cost as every
class in creation would have to be loaded before execution. Java was
designed from the beginning to load classes incrementally on an
as-needed basis.
>So, do you simply load .class files into memory from the disk, or doLike all other JVMs, I load classes on demand. Nothing the in JVM
>you fully initialize the loaded classes before JVM asks you to do
>this? If later, then this violates the JVM specification.
>
>
specification requires any different behavior. If you have any doubts,
use a JVM the lists classes as they're loaded.
>>How do you catch native calls back into the engine? I suppose youI'll append the code at the end. (The code is copyrighted, all rights
>>could put the whole thing, JVM and all, into a shared library and
>>have a base class do a loadLibrary on itself, but that means that
>>JVM can't be statically linked in. On refection, maybe that's a
>>good thing.
>>
>>
reserved, and is explicitly not open source.) When it doesn't find an
entrypoint, the stuff at the end dumps out function declarations and
skeletons into a file for inclusion in my JavaNativeMethods.cpp file.
>Good enough. You don't need me to tell you that it works.
>In our case JVM is not statically bound but dynamically loaded using
>shared library specified in the config. This allows us to load any
>compliant JVM. And yes, the callback goes via
>loadLibrary("javaespudf") which contains all needed entrypoints.
>
>
>
Here's the class load code:
void JavaMethod::resolveEntrypoint(ENV_DCL)
{
char fullName [1024], *p = fullName;
for (char *q = "Java_"; *q;)
*p++ = *q++;
WCHAR *w = javaClass->className->string;
WCHAR *end;
for (end = w + javaClass->className->length; w < end; ++w)
*p++ = (*w == '/') ? '_' : (char) *w;
w = methodName->string;
*p++ = '_';
for (end = w + methodName->length; w < end;)
*p++ = (char) *w++;
*p = 0;
// Try to resolve name internally
if (nativeMethod = findNativeMethod (fullName))
return;
// Try to resolve it against known libraries
if (nativeMethod = (NativeFn) javaClass->java->resolveEntrypoint
(fullName, numberArgs))
return;
// Expand name to include signature
*p++ = '_';
*p++ = '_';
for (w = descriptor->string, end = w + descriptor->length, ++w;
w < end && *w != ')';)
{
char c = (char) *w++;
if (c == '_')
{ *p++ = '_'; *p++ = '1'; }
else if (c == '_')
{ *p++ = ';'; *p++ = '2'; }
else if (c == '_')
{ *p++ = '['; *p++ = '3'; }
else
*p++ = c;
}
*p = 0;
if (nativeMethod = (NativeFn) javaClass->java->resolveEntrypoint
(fullName, numberArgs))
return;
// Not going so good. Generate a template for an internal
// implementation, just in case.
FILE *output = fopen ("foo.cpp", "w");
if (output)
{
fprintf (output, "\n/* %s */\n\n", (const char *) javaClass->name);
JavaGenNative::genNativeMethods (javaClass, output, genPrototypes);
fprintf (output, "\n/* %s */\n\n", (const char *) javaClass->name);
JavaGenNative::genNativeMethods (javaClass, output, genHeader);
fprintf (output, "\n/* %s */\n\n", (const char *) javaClass->name);
JavaGenNative::genNativeMethods (javaClass, output, genBody);
fclose (output);
}
thread->unsatisfiedLinkError (ENV, "method \"%s\" (%s) of class \"%s\"",
(const char*) methodName->getString(),
(const char*) descriptor->getString(),
(const char*)
javaClass->className->getString());
}
NativeFn findNativeMethod (const char *name)
{
for (NativeMethod *method = hashTable [JString::hash (name, HASH_SIZE)];
method; method = method->collision)
if (!strcmp (name, method->name))
return method->fn;
return NULL;
}
--
Jim Starkey
Netfrastructure, Inc.
978 526-1376