Hi David,

thanks! Sorry, I guess I left out some details in my original post, so here
is a bit more background:

We support a lot of platforms as well as JDK releases, so I wanted to keep
this testlauncher as platform neutral as possible and also it had to run
with older JDKs, so unfortunately JLI was not an option.

Right now the testlauncher works across all our Unices, it is very simple
portable C, just MacOS gave me a bit of a headache.

I think I do already what you suggest:
- I include jni.h (depending on whose jni.h I use, the platform dependent
include path for jni_md.h is sometimes needed, sometimes not.)
- create a new thread because on some platforms VM cannot run on primordial
thread
- load libjvm via dlopen(), resolve JNI_createJavaVM via dlsym()
- call JNI_createJavaVM()
- Load the main class, invoke the main method with the parameters given.

I link against libdl and libpthread and, on MacOS, against the framework
"ApplicationServices" (see below why). I do not link against any other
framework, nor against the libjvm itself.

On almost all platforms that worked nicely. On MacOS however I got two
errors:

1) first I ran into a SIGTRAP when dlopen()'ing the libjvm.dylib. When
debugging, I found that it happened when the libjvm.dylib loads the
libjava.dylib. The libjava.dylib needs the ApplicationServices framework,
but was not linked against it, so it was not self-contained. I guess that
is an error, but I was lazy and instead of fixing that, I linked the
launcher itself against that framework, even if the launcher does not need
it, and now the dlopen() worked.

2) Now, the libjvm.dylib was successfully loaded, and we called
JNI_CreateJavaVM. That caused the error mentioned in my first post ("No
Java runtime present, requesting install"). I googled and found that the
error message stems from Apple's JavaRuntimeSupport framework. There is a
nice summary by Gerard Ziemski in the comments section of JDK-7131356
<https://bugs.openjdk.java.net/browse/JDK-7131356> .

Apple suggests deferring load of the JavaRuntimeServices framework after
JNI_MemAlloc(). I could not do that but I could provide local variants of
JNI_MemAlloc() (very simple, just added "void* JNI_MemAlloc(size_t s) {
return malloc(s); }" to my testlauncher). My local variants of
JNI_MemAlloc() and JNI_MemFree() do the same as the JDK variants, so even
if they are intermixed no harm is done.

This worked - the error disappeared - so I guess the JavaRuntimeServices
framework tries to fish this symbol out of the air to see if it is running
within a valid Java VM process. Now my testlauncher worked on MacOS, I ran
a number of java programs with it and all is well.

But still, it is quite ugly, hence my original questions: do you know a
better workaround for this bug? And how far is the work on getting rid of
this dependency on the JavaRuntimeServices framework altogether? Is that
still the plan?

Thanks for your time!

Kind Regards, Thomas


On Thu, Nov 20, 2014 at 6:31 PM, David DeHaven <david.deha...@oracle.com>
wrote:

>
> Are you linking against JavaVM.framework? If you just need the JNI
> headers, it's better to use those provided in the JDK (the headers are even
> correct these days...). You shouldn't need to link anything to just open
> and use libjvm. This is generally true for JNI libraries too since native
> methods are dynamically looked up by symbol name. So, instead of
> "-framework JavaVM" use "-I${JDK_HOME}/include
> -I${JDK_HOME}/include/darwin" and it will find jni.h (assuming JDK_HOME is
> defined and correct).
>
> JLI (libjli) is a much more robust option for 7 and beyond, but the
> documentation around it is sparse. All of our launchers are just wrappers
> around JLI_Launch, it takes a lot of the hassle out of working with libjvm.
> Look in jdk/src/java.base/share/native/launcher/main.c (OpenJDK 9) for an
> example. You will still need to dlopen libjli.dylib and use dlsym to get
> JLI_Launch, it will handle opening libjvm for you.
>
>
> You could also try the Java Packager, which will go a step further and
> create a native .app bundle for you.
>
> -DrD-
>
> > Hi all,
> >
> > I tried to build a very simple launcher (simple c program) for a customer
> > to show how to build a java launcher; launcher loads libjvm.dylib using
> > dlopen() and resolves JNI_CreateJavaVM via dlsym().
> >
> > On MacOS, when running, in JNI_CreateJavaVM I get the same error as
> > mentioned in JDK-7131356
> > <https://bugs.openjdk.java.net/browse/JDK-7131356> ("No
> > Java runtime present, requesting install").
> >
> > I was able to work around the issue by locally providing implementations
> > for "JLI_MemAlloc" (and, for balance, realloc and free too) and exporting
> > them, even though the functions make no sense in the launcher. This
> symbol
> > seems to be a trigger for Apples JavaRuntimeServices framework to stop
> > complaining about missing java runtime. I am not even sure this function
> is
> > even called by the Apple framework.
> >
> > So my questions are:
> > - does anyone know a better workaround?
> > - can we hope for a fix?
> >
> > Thanks! and Kind Regards,
> >
> > Thomas Stüfe
>
>

Reply via email to