extern"C"void JNICALL abort_handler()
{ // If we are within JNI_CreateJavaVM then we jump back into getJavaVM if( g_bInGetJavaVM != 0 )
{
SAL_WARN("jfw", "JavaVM: JNI_CreateJavaVM called os::abort(), caught by abort_handler");
longjmp( jmp_jvm_abort, 0);
}
}
#ifndef ANDROID int createJvm(
JNI_CreateVM_Type * pCreateJavaVM, JavaVM ** pJavaVM, JNIEnv ** ppEnv, JavaVMInitArgs * vm_args)
{ /* We set a global flag which is used by the abort handler in order to determinewhetheritisshoulduselongjmptogetbackintothisfunction. Thatis,theaborthandlerdeterminesifitisonthesamestackasthisfunction andthenjumpsbackintothisfunction.
*/
g_bInGetJavaVM = 1;
jint err;
memset( jmp_jvm_abort, 0, sizeof(jmp_jvm_abort)); /* If the setjmp return value is not "0" then this point was reached by a longjmp in the abort_handler,whichwascalledindirectlybyJNI_CreateVM.
*/ if( setjmp( jmp_jvm_abort ) == 0)
{ //returns negative number on failure
err= pCreateJavaVM(pJavaVM, ppEnv, vm_args);
g_bInGetJavaVM = 0;
} else // set err to a positive number, so as or recognize that an abort (longjmp) //occurred
err= 1; return err;
} #endif
/** helper function to check Java version requirements
*/
javaPluginError checkJavaVersionRequirements(
rtl::Reference<VendorBase> const & aVendorInfo,
OUString const& sMinVersion,
OUString const& sMaxVersion,
std::vector<OUString> const & arExcludeList)
{ if (!aVendorInfo->isValidArch())
{ return javaPluginError::WrongArch;
} if (!sMinVersion.isEmpty())
{ try
{ if (aVendorInfo->compareVersions(sMinVersion) < 0) return javaPluginError::FailedVersion;
} catch (MalformedVersionException&)
{ //The minVersion was not recognized as valid for this vendor.
JFW_ENSURE( false, "[Java framework]sunjavaplugin does not know version: "
+ sMinVersion + " for vendor: " + aVendorInfo->getVendor()
+ " .Check minimum Version." ); return javaPluginError::WrongVersionFormat;
}
}
if (!sMaxVersion.isEmpty())
{ try
{ if (aVendorInfo->compareVersions(sMaxVersion) > 0) return javaPluginError::FailedVersion;
} catch (MalformedVersionException&)
{ //The maxVersion was not recognized as valid for this vendor.
JFW_ENSURE( false, "[Java framework]sunjavaplugin does not know version: "
+ sMaxVersion + " for vendor: " + aVendorInfo->getVendor()
+ " .Check maximum Version." ); return javaPluginError::WrongVersionFormat;
}
}
for (autoconst & sExVer: arExcludeList) { try
{ if (aVendorInfo->compareVersions(sExVer) == 0) return javaPluginError::FailedVersion;
} catch (MalformedVersionException&)
{ //The excluded version was not recognized as valid for this vendor.
JFW_ENSURE( false, "[Java framework]sunjavaplugin does not know version: "
+ sExVer + " for vendor: " + aVendorInfo->getVendor()
+ " .Check excluded versions." ); return javaPluginError::WrongVersionFormat;
}
}
vecVerifiedInfos.push_back(vecInfo);
} //Now vecVerifiedInfos contains all those JREs which meet the version requirements //Transfer them into the array that is passed out.
parJavaInfo->clear(); for (autoconst& vecVerifiedInfo : vecVerifiedInfos)
{
parJavaInfo->push_back(createJavaInfo(vecVerifiedInfo));
}
// copy infos of JREs that meet version requirements to vecVerifiedInfos for (autoconst& infosFromPath : vecInfosFromPath)
{ autoconst versionInfo = vendorSettings.getVersionInformation(infosFromPath->getVendor()); if (checkJavaVersionRequirements(
infosFromPath,
versionInfo.sMinVersion,
versionInfo.sMaxVersion,
versionInfo.vecExcludeVersions)
== javaPluginError::NONE)
{
vecVerifiedInfos.push_back(createJavaInfo(infosFromPath));
}
}
if (vecVerifiedInfos.empty()) return javaPluginError::NoJre;
javaInfosFromPath = std::move(vecVerifiedInfos);
return javaPluginError::NONE;
}
#ifdefined(_WIN32)
// Load msvcr71.dll using an explicit full path from where it is // present as bundled with the JRE. In case it is not found where we // think it should be, do nothing, and just let the implicit loading // that happens when loading the JVM take care of it.
staticvoid load_msvcr(std::u16string_view jvm_dll, std::u16string_view msvcr)
{ // First check if msvcr71.dll is in the same folder as jvm.dll. It // normally isn't, at least up to 1.6.0_22, but who knows if it // might be in the future.
std::size_t slash = jvm_dll.rfind('\\');
if (LoadLibraryW(
o3tl::toW(OUString(OUString::Concat(jvm_dll.substr(0, slash+1)) + msvcr).getStr()))) return;
// Then check if msvcr71.dll is in the parent folder of where // jvm.dll is. That is currently (1.6.0_22) as far as I know the // normal case.
slash = jvm_dll.substr(0, slash).rfind('\\');
// Check if the jvm DLL imports msvcr71.dll, and in that case try // loading it explicitly. In case something goes wrong, do nothing, // and just let the implicit loading try to take care of it. staticvoid do_msvcr_magic(OUString const &jvm_dll)
{ struct stat st;
#ifndef ANDROID // On linux we load jvm with RTLD_GLOBAL. This is necessary for debugging, because // libjdwp.so need a symbol (fork1) from libjvm which it only gets if the jvm is loaded // with RTLD_GLOBAL. On Solaris libjdwp.so is correctly linked with libjvm.so
osl::Module moduleRt; #ifdefined(LINUX) if (!moduleRt.load(sRuntimeLib, SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_NOW)) #elifdefined MACOSX // Must be SAL_LOADMODULE_GLOBAL when e.g. specifying a // -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 option to // JDK 1.8.0_121 at least, as JNI_CreateJavaVM -> Threads::create_vm -> // JvmtiExport::post_vm_initialized -> cbEarlyVMInit -> initialize -> // util_initialize -> sun.misc.VMSupport.getAgentProperties -> // Java_sun_misc_VMSupport_initAgentProperties -> // JDK_FindJvmEntry("JVM_INitAgentProperties") -> // dlsym(RTLD_DEFAULT, "JVM_INitAgentProperties"): if (!moduleRt.load(sRuntimeLib, SAL_LOADMODULE_GLOBAL)) #else #ifdefined(_WIN32)
do_msvcr_magic(sRuntimeLib); #endif if (!moduleRt.load(sRuntimeLib)) #endif
{
JFW_ENSURE(false, "[Java framework]sunjavaplugin" SAL_DLLEXTENSION " could not load Java runtime library: \n"
+ sRuntimeLib + "\n");
JFW_TRACE0("Could not load Java runtime library: " << sRuntimeLib); return javaPluginError::VmCreationFailed;
}
#ifdefined UNX && !defined MACOSX //Setting the JAVA_HOME is needed for awt
OUString sPathLocation;
osl::FileBase::getSystemPathFromFileURL(pInfo->sLocation, sPathLocation);
osl_setEnvironment(u"JAVA_HOME"_ustr.pData, sPathLocation.pData); #endif
// Valgrind typically emits many false errors when executing JIT'ed JVM // code, so force the JVM into interpreted mode: bool addForceInterpreted = FORCE_INTERPRETED > 0;
// Some testing with Java 1.4 showed that JavaVMOption.optionString has to // be encoded with the system encoding (i.e., osl_getThreadTextEncoding):
JavaVMInitArgs vm_args;
// We set an abort handler which is called when the VM calls _exit during // JNI_CreateJavaVM. This happens when the LD_LIBRARY_PATH does not contain // all some directories of the Java installation. This is necessary for // all versions below 1.5.1
options.emplace_back("abort", reinterpret_cast<void*>(abort_handler)); bool hasStackSize = false; #ifdef UNX // Until java 1.5 we need to put a plugin.jar or javaplugin.jar (<1.4.2) // in the class path in order to have applet support:
OString sAddPath = getPluginJarPath(pInfo->sVendor, pInfo->sLocation,pInfo->sVersion); #endif for (int i = 0; i < cOptions; i++)
{
OString opt(arOptions[i].optionString); #ifdef UNX if (opt.startsWith("-Djava.class.path="))
{ if (!sAddPath.isEmpty())
{
opt += OStringChar(SAL_PATHSEPARATOR) + sAddPath;
sAddPath.clear();
}
} #endif if (opt == "-Xint") {
addForceInterpreted = false;
} if (opt.startsWith("-Xss")) {
hasStackSize = true;
}
options.emplace_back(opt, arOptions[i].extraInfo);
} if (addForceInterpreted) {
options.emplace_back("-Xint", nullptr);
} if (!hasStackSize) { #ifdefined LINUX && (defined X86 || defined X86_64) // At least OpenJDK 1.8.0's os::workaround_expand_exec_shield_cs_limit // (hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp) can mmap an rwx // page into the area that the main stack can grow down to according to // "ulimit -s", as os::init_2's (hotspot/src/os/linux/vm/os_linux.cpp) // call to // // Linux::capture_initial_stack(JavaThread::stack_size_at_create()); // // caps _initial_thread_stack_size at threadStackSizeInBytes ,i.e., // -Xss, which appears to default to only 327680, whereas "ulimit -s" // defaults to 8192 * 1024 at least on Fedora 20; so attempt to pass in // a useful -Xss argument:
rlimit l; if (getrlimit(RLIMIT_STACK, &l) == 0) { if (l.rlim_cur == RLIM_INFINITY) {
SAL_INFO("jfw", "RLIMIT_STACK RLIM_INFINITY -> 8192K");
l.rlim_cur = 8192 * 1024;
} elseif (l.rlim_cur > 512 * 1024 * 1024) {
SAL_INFO( "jfw", "huge RLIMIT_STACK " << l.rlim_cur << " -> 8192K");
l.rlim_cur = 8192 * 1024;
}
options.emplace_back("-Xss" + OString::number(l.rlim_cur), nullptr);
} else { int e = errno;
SAL_WARN("jfw", "getrlimit(RLIMIT_STACK) failed with errno " << e);
} #endif
} #ifdef UNX if (!sAddPath.isEmpty()) {
options.emplace_back("-Djava.class.path=" + sAddPath, nullptr);
} #endif
if(err != 0)
{ if( err < 0)
{
SAL_WARN("jfw", "Can not create Java Virtual Machine, " << err);
errorcode = javaPluginError::VmCreationFailed;
} elseif( err > 0)
{
SAL_WARN("jfw", "Can not create JavaVirtualMachine, abort handler was called");
errorcode = javaPluginError::VmCreationFailed;
}
} else
{
*ppVm = pJavaVM;
JFW_TRACE2("JVM created");
} #else
(void) arOptions;
(void) cOptions;
(void) ppEnv; // On Android we always have a Java VM as we only expect this code // to be run in an Android app anyway.
*ppVm = lo_get_javavm(); #endif
javaPluginError ret = javaPluginError::NONE;
OUString sLocation(pInfo->sLocation);
if (sLocation.isEmpty()) return javaPluginError::InvalidArg;
::osl::DirectoryItem item;
::osl::File::RC rc_item = ::osl::DirectoryItem::get(sLocation, item); if (::osl::File::E_None == rc_item)
{
*exist = true;
} elseif (::osl::File::E_NOENT == rc_item)
{
*exist = false;
} else
{
ret = javaPluginError::Error;
} //We can have the situation that the JavaVM runtime library is not //contained within JAVA_HOME. Then the check for JAVA_HOME would return //true although the runtime library may not be loadable. //Or the JAVA_HOME directory of a deinstalled JRE left behind. if (ret == javaPluginError::NONE && *exist)
{
OUString sRuntimeLib = getRuntimeLib(pInfo->arVendorData);
JFW_TRACE2("Checking existence of Java runtime library");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.