1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 # include <sys/stat.h>
24 # if !defined WIN32_LEAN_AND_MEAN
25 # define WIN32_LEAN_AND_MEAN
41 #include <config_options.h>
42 #include <osl/diagnose.h>
43 #include <rtl/ustring.hxx>
44 #include <rtl/ustrbuf.hxx>
45 #include <osl/module.hxx>
46 #include <osl/mutex.hxx>
47 #include <osl/process.h>
48 #include <osl/thread.hxx>
49 #include <osl/file.hxx>
50 #include <rtl/instance.hxx>
51 #include <sal/log.hxx>
52 #include <osl/getglobalmutex.hxx>
53 #include <o3tl/char16_t2wchar_t.hxx>
59 #include <rtl/byteseq.hxx>
60 #include <fwkbase.hxx>
61 #include <vendorplugin.hxx>
63 #include "sunversion.hxx"
64 #include "vendorlist.hxx"
65 #include "diagnostics.h"
68 #include "util_cocoa.hxx"
72 #include <osl/detail/android-bootstrap.h>
74 #if !ENABLE_RUNTIME_OPTIMIZATIONS
75 #define FORCE_INTERPRETED 1
76 #elif defined HAVE_VALGRIND_HEADERS
77 #include <valgrind/valgrind.h>
78 #define FORCE_INTERPRETED RUNNING_ON_VALGRIND
80 #define FORCE_INTERPRETED 0
84 #if defined LINUX && (defined X86 || defined X86_64)
85 #include <sys/resource.h>
90 using namespace jfw_plugin
;
95 struct PluginMutex
: public ::rtl::Static
<osl::Mutex
, PluginMutex
> {};
97 #if defined(UNX) && !defined(ANDROID)
98 OString
getPluginJarPath(
99 const OUString
& sVendor
,
100 const OUString
& sLocation
,
101 const OUString
& sVersion
)
104 OUString
sName1("javaplugin.jar");
105 OUString
sName2("plugin.jar");
107 if ( sVendor
== "Sun Microsystems Inc." )
109 SunVersion
ver142("1.4.2-ea");
110 SunVersion
ver150("1.5.0-ea");
111 SunVersion
ver(sVersion
);
112 OSL_ASSERT(ver142
&& ver150
&& ver
);
119 else if (ver
< ver150
)
120 {//this will cause ea, beta etc. to have plugin.jar in path.
121 //but this does not harm. 1.5.0-beta < 1.5.0
124 if (!sName
.isEmpty())
126 sName
= sLocation
+ "/lib/" + sName
;
128 osl_getSystemPathFromFileURL(sName
.pData
, & sPath
.pData
)
134 OUString
sName(sLocation
+ "/lib/" + sName1
);
137 if (osl_getSystemPathFromFileURL(sName
.pData
, & sPath1
.pData
)
140 sName
= sLocation
+ "/lib/" + sName2
;
141 if (osl_getSystemPathFromFileURL(sName
.pData
, & sPath2
.pData
)
144 sPath
= sPath1
+ OUStringLiteral1(SAL_PATHSEPARATOR
) + sPath2
;
147 OSL_ASSERT(!sPath
.isEmpty());
149 ret
= OUStringToOString(sPath
, osl_getThreadTextEncoding());
156 std::unique_ptr
<JavaInfo
> createJavaInfo(
157 const rtl::Reference
<VendorBase
> & info
)
159 OUStringBuffer
buf(1024);
160 buf
.append(info
->getRuntimeLibrary());
161 if (!info
->getLibraryPath().isEmpty())
164 buf
.append(info
->getLibraryPath());
167 OUString sVendorData
= buf
.makeStringAndClear();
168 return std::unique_ptr
<JavaInfo
>(
170 info
->getVendor(), info
->getHome(), info
->getVersion(),
171 sal_uInt64(info
->supportsAccessibility() ? 1 : 0),
172 sal_uInt64(info
->needsRestart() ? JFW_REQUIRE_NEEDRESTART
: 0),
174 reinterpret_cast<sal_Int8
*>(sVendorData
.pData
->buffer
),
175 sVendorData
.getLength() * sizeof(sal_Unicode
))});
178 OUString
getRuntimeLib(const rtl::ByteSequence
& data
)
180 const sal_Unicode
* chars
= reinterpret_cast<sal_Unicode
const *>(data
.getConstArray());
181 sal_Int32 len
= data
.getLength();
182 OUString
sData(chars
, len
/ 2);
183 //the runtime lib is on the first line
185 OUString aToken
= sData
.getToken( 0, '\n', index
);
190 jmp_buf jmp_jvm_abort
;
191 sig_atomic_t g_bInGetJavaVM
= 0;
193 extern "C" void JNICALL
abort_handler()
195 // If we are within JNI_CreateJavaVM then we jump back into getJavaVM
196 if( g_bInGetJavaVM
!= 0 )
198 fprintf(stderr
, "JavaVM: JNI_CreateJavaVM called os::abort(), caught by abort_handler in javavm.cxx\n");
199 longjmp( jmp_jvm_abort
, 0);
203 /** helper function to check Java version requirements
205 This function checks if the Java version of the given VendorBase
206 meets the given Java version requirements.
209 [in] the object to be inspected whether it meets the version requirements
211 [in] represents the minimum version of a JRE. The string can be empty.
213 [in] represents the maximum version of a JRE. The string can be empty.
215 [in] contains a list of "bad" versions. JREs which have one of these
216 versions must not be returned by this function.
219 javaPluginError::NONE the function ran successfully and the version requirements are met
220 javaPluginError::FailedVersion at least one of the version requirements (minVersion,
221 maxVersion, excludeVersions) was violated
222 javaPluginError::WrongVersionFormat the version strings in
223 <code>sMinVersion,sMaxVersion,arExcludeList</code> are not recognized as valid
227 javaPluginError
checkJavaVersionRequirements(
228 rtl::Reference
<VendorBase
> const & aVendorInfo
,
229 OUString
const& sMinVersion
,
230 OUString
const& sMaxVersion
,
231 std::vector
<OUString
> const & arExcludeList
)
233 if (!aVendorInfo
->isValidArch())
235 return javaPluginError::WrongArch
;
237 if (!sMinVersion
.isEmpty())
241 if (aVendorInfo
->compareVersions(sMinVersion
) < 0)
242 return javaPluginError::FailedVersion
;
244 catch (MalformedVersionException
&)
246 //The minVersion was not recognized as valid for this vendor.
249 "[Java framework]sunjavaplugin does not know version: "
250 + sMinVersion
+ " for vendor: " + aVendorInfo
->getVendor()
251 + " .Check minimum Version." );
252 return javaPluginError::WrongVersionFormat
;
256 if (!sMaxVersion
.isEmpty())
260 if (aVendorInfo
->compareVersions(sMaxVersion
) > 0)
261 return javaPluginError::FailedVersion
;
263 catch (MalformedVersionException
&)
265 //The maxVersion was not recognized as valid for this vendor.
268 "[Java framework]sunjavaplugin does not know version: "
269 + sMaxVersion
+ " for vendor: " + aVendorInfo
->getVendor()
270 + " .Check maximum Version." );
271 return javaPluginError::WrongVersionFormat
;
275 for (auto const & sExVer
: arExcludeList
) {
278 if (aVendorInfo
->compareVersions(sExVer
) == 0)
279 return javaPluginError::FailedVersion
;
281 catch (MalformedVersionException
&)
283 //The excluded version was not recognized as valid for this vendor.
286 "[Java framework]sunjavaplugin does not know version: "
287 + sExVer
+ " for vendor: " + aVendorInfo
->getVendor()
288 + " .Check excluded versions." );
289 return javaPluginError::WrongVersionFormat
;
293 return javaPluginError::NONE
;
298 javaPluginError
jfw_plugin_getAllJavaInfos(
299 bool checkJavaHomeAndPath
,
300 jfw::VendorSettings
const & vendorSettings
,
301 std::vector
<std::unique_ptr
<JavaInfo
>>* parJavaInfo
,
302 std::vector
<rtl::Reference
<jfw_plugin::VendorBase
>> & infos
)
307 vector
<rtl::Reference
<VendorBase
> > vecInfos
=
308 addAllJREInfos(checkJavaHomeAndPath
, infos
);
309 vector
<rtl::Reference
<VendorBase
> > vecVerifiedInfos
;
311 for (auto const& vecInfo
: vecInfos
)
313 if (auto const versionInfo
= vendorSettings
.getVersionInformation(vecInfo
->getVendor()))
315 javaPluginError err
= checkJavaVersionRequirements(
316 vecInfo
, versionInfo
->sMinVersion
, versionInfo
->sMaxVersion
, versionInfo
->vecExcludeVersions
);
318 if (err
== javaPluginError::FailedVersion
|| err
== javaPluginError::WrongArch
)
320 else if (err
== javaPluginError::WrongVersionFormat
)
324 vecVerifiedInfos
.push_back(vecInfo
);
326 //Now vecVerifiedInfos contains all those JREs which meet the version requirements
327 //Transfer them into the array that is passed out.
328 parJavaInfo
->clear();
329 for (auto const& vecVerifiedInfo
: vecVerifiedInfos
)
331 parJavaInfo
->push_back(createJavaInfo(vecVerifiedInfo
));
334 return javaPluginError::NONE
;
337 javaPluginError
jfw_plugin_getJavaInfoByPath(
338 OUString
const& sPath
,
339 jfw::VendorSettings
const & vendorSettings
,
340 std::unique_ptr
<JavaInfo
> * ppInfo
)
342 assert(ppInfo
!= nullptr);
343 OSL_ASSERT(!sPath
.isEmpty());
345 return javaPluginError::InvalidArg
;
347 rtl::Reference
<VendorBase
> aVendorInfo
= getJREInfoByPath(sPath
);
348 if (!aVendorInfo
.is())
349 return javaPluginError::NoJre
;
351 //Check if the detected JRE matches the version requirements
352 javaPluginError errorcode
= javaPluginError::NONE
;
353 if (auto const versionInfo
= vendorSettings
.getVersionInformation(aVendorInfo
->getVendor()))
355 errorcode
= checkJavaVersionRequirements(
356 aVendorInfo
, versionInfo
->sMinVersion
, versionInfo
->sMaxVersion
, versionInfo
->vecExcludeVersions
);
359 if (errorcode
== javaPluginError::NONE
)
360 *ppInfo
= createJavaInfo(aVendorInfo
);
365 javaPluginError
jfw_plugin_getJavaInfoFromJavaHome(
366 jfw::VendorSettings
const & vendorSettings
,
367 std::unique_ptr
<JavaInfo
> * ppInfo
,
368 std::vector
<rtl::Reference
<VendorBase
>> & infos
)
372 std::vector
<rtl::Reference
<VendorBase
>> infoJavaHome
;
373 addJavaInfoFromJavaHome(infos
, infoJavaHome
);
375 if (infoJavaHome
.empty())
376 return javaPluginError::NoJre
;
377 assert(infoJavaHome
.size() == 1);
379 //Check if the detected JRE matches the version requirements
380 auto const versionInfo
= vendorSettings
.getVersionInformation(infoJavaHome
[0]->getVendor());
382 || (checkJavaVersionRequirements(
384 versionInfo
->sMinVersion
,
385 versionInfo
->sMaxVersion
,
386 versionInfo
->vecExcludeVersions
)
387 == javaPluginError::NONE
))
389 *ppInfo
= createJavaInfo(infoJavaHome
[0]);
390 return javaPluginError::NONE
;
393 return javaPluginError::NoJre
;
396 javaPluginError
jfw_plugin_getJavaInfosFromPath(
397 jfw::VendorSettings
const & vendorSettings
,
398 std::vector
<std::unique_ptr
<JavaInfo
>> & javaInfosFromPath
,
399 std::vector
<rtl::Reference
<jfw_plugin::VendorBase
>> & infos
)
401 // find JREs from PATH
402 vector
<rtl::Reference
<VendorBase
>> vecInfosFromPath
;
403 addJavaInfosFromPath(infos
, vecInfosFromPath
);
405 vector
<std::unique_ptr
<JavaInfo
>> vecVerifiedInfos
;
407 // copy infos of JREs that meet version requirements to vecVerifiedInfos
408 for (auto const& infosFromPath
: vecInfosFromPath
)
410 auto const versionInfo
= vendorSettings
.getVersionInformation(infosFromPath
->getVendor());
412 || (checkJavaVersionRequirements(
414 versionInfo
->sMinVersion
,
415 versionInfo
->sMaxVersion
,
416 versionInfo
->vecExcludeVersions
)
417 == javaPluginError::NONE
))
419 vecVerifiedInfos
.push_back(createJavaInfo(infosFromPath
));
423 if (vecVerifiedInfos
.empty())
424 return javaPluginError::NoJre
;
426 javaInfosFromPath
= std::move(vecVerifiedInfos
);
428 return javaPluginError::NONE
;
434 // Load msvcr71.dll using an explicit full path from where it is
435 // present as bundled with the JRE. In case it is not found where we
436 // think it should be, do nothing, and just let the implicit loading
437 // that happens when loading the JVM take care of it.
439 static void load_msvcr(OUString
const & jvm_dll
, OUStringLiteral msvcr
)
441 // First check if msvcr71.dll is in the same folder as jvm.dll. It
442 // normally isn't, at least up to 1.6.0_22, but who knows if it
443 // might be in the future.
444 sal_Int32 slash
= jvm_dll
.lastIndexOf('\\');
448 // Huh, weird path to jvm.dll. Oh well.
449 SAL_WARN("jfw", "JVM pathname <" + jvm_dll
+ "> w/o backslash");
454 o3tl::toW(OUString(jvm_dll
.copy(0, slash
+1) + msvcr
).getStr())))
457 // Then check if msvcr71.dll is in the parent folder of where
458 // jvm.dll is. That is currently (1.6.0_22) as far as I know the
460 slash
= jvm_dll
.lastIndexOf('\\', slash
);
466 o3tl::toW(OUString(jvm_dll
.copy(0, slash
+1) + msvcr
).getStr()));
469 // Check if the jvm DLL imports msvcr71.dll, and in that case try
470 // loading it explicitly. In case something goes wrong, do nothing,
471 // and just let the implicit loading try to take care of it.
472 static void do_msvcr_magic(OUString
const &jvm_dll
)
477 osl::FileBase::RC nError
= osl::FileBase::getSystemPathFromFileURL(
480 if ( osl::FileBase::E_None
!= nError
)
483 "jfw", "getSystemPathFromFileURL(" << jvm_dll
<< "): " << +nError
);
487 FILE *f
= _wfopen(o3tl::toW(Module
.getStr()), L
"rb");
491 SAL_WARN("jfw", "_wfopen(" << Module
<< ") failed");
495 if (fstat(fileno(f
), &st
) == -1)
497 SAL_WARN("jfw", "fstat(" << Module
<< ") failed");
502 PIMAGE_DOS_HEADER dos_hdr
= static_cast<PIMAGE_DOS_HEADER
>(malloc(st
.st_size
));
504 if (fread(dos_hdr
, st
.st_size
, 1, f
) != 1 ||
505 memcmp(dos_hdr
, "MZ", 2) != 0 ||
506 dos_hdr
->e_lfanew
< 0 ||
507 dos_hdr
->e_lfanew
> static_cast<LONG
>(st
.st_size
- sizeof(IMAGE_NT_HEADERS
)))
509 SAL_WARN("jfw", "analyzing <" << Module
<< "> failed");
517 IMAGE_NT_HEADERS
*nt_hdr
= reinterpret_cast<IMAGE_NT_HEADERS
*>(reinterpret_cast<char *>(dos_hdr
) + dos_hdr
->e_lfanew
);
519 DWORD importsVA
= nt_hdr
->OptionalHeader
520 .DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
;
521 // first determine Virtual-to-File-address mapping for the section
522 // that contains the import directory
523 IMAGE_SECTION_HEADER
*sections
= IMAGE_FIRST_SECTION(nt_hdr
);
524 ptrdiff_t VAtoPhys
= -1;
525 for (int i
= 0; i
< nt_hdr
->FileHeader
.NumberOfSections
; ++i
)
527 if (sections
->VirtualAddress
<= importsVA
&&
528 importsVA
< sections
->VirtualAddress
+ sections
->SizeOfRawData
)
530 VAtoPhys
= static_cast<size_t>(sections
->PointerToRawData
) - static_cast<size_t>(sections
->VirtualAddress
);
535 if (-1 == VAtoPhys
) // not found?
537 SAL_WARN("jfw", "analyzing <" << Module
<< "> failed");
541 IMAGE_IMPORT_DESCRIPTOR
*imports
=
542 reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR
*>(reinterpret_cast<char *>(dos_hdr
) + importsVA
+ VAtoPhys
);
544 while (imports
<= reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR
*>(reinterpret_cast<char *>(dos_hdr
) + st
.st_size
- sizeof (IMAGE_IMPORT_DESCRIPTOR
)) &&
545 imports
->Name
!= 0 &&
546 imports
->Name
+ VAtoPhys
< static_cast<DWORD
>(st
.st_size
))
548 static OUStringLiteral msvcrts
[] =
553 char const* importName
= reinterpret_cast<char *>(dos_hdr
) + imports
->Name
+ VAtoPhys
;
554 sal_Int32 importNameLen
= rtl_str_getLength(importName
);
555 for (size_t i
= 0; i
< SAL_N_ELEMENTS(msvcrts
); ++i
)
557 if (0 == rtl_str_compareIgnoreAsciiCase_WithLength(
558 importName
, importNameLen
,
559 msvcrts
[i
].data
, msvcrts
[i
].size
))
561 load_msvcr(Module
, msvcrts
[i
]);
574 /** starts a Java Virtual Machine.
576 The function shall ensure, that the VM does not abort the process
577 during instantiation.
580 javaPluginError
jfw_plugin_startJavaVirtualMachine(
581 const JavaInfo
*pInfo
,
582 const JavaVMOption
* arOptions
,
587 assert(pInfo
!= nullptr);
588 assert(ppVm
!= nullptr);
589 assert(ppEnv
!= nullptr);
590 // unless guard is volatile the following warning occurs on gcc:
591 // warning: variable 't' might be clobbered by `longjmp' or `vfork'
592 volatile osl::MutexGuard
guard(PluginMutex::get());
593 // unless errorcode is volatile the following warning occurs on gcc:
594 // warning: variable 'errorcode' might be clobbered by `longjmp' or `vfork'
595 volatile javaPluginError errorcode
= javaPluginError::NONE
;
597 rtl::Reference
<VendorBase
> aVendorInfo
= getJREInfoByPath( pInfo
->sLocation
);
598 if ( !aVendorInfo
.is() || aVendorInfo
->compareVersions( pInfo
->sVersion
) < 0 )
599 return javaPluginError::VmCreationFailed
;
601 OUString sRuntimeLib
= getRuntimeLib(pInfo
->arVendorData
);
603 if ( !JvmfwkUtil_isLoadableJVM( sRuntimeLib
) )
604 return javaPluginError::VmCreationFailed
;
606 JFW_TRACE2("Using Java runtime library: " << sRuntimeLib
);
609 // On linux we load jvm with RTLD_GLOBAL. This is necessary for debugging, because
610 // libjdwp.so need a symbol (fork1) from libjvm which it only gets if the jvm is loaded
611 // with RTLD_GLOBAL. On Solaris libjdwp.so is correctly linked with libjvm.so
612 osl::Module moduleRt
;
614 if (!moduleRt
.load(sRuntimeLib
, SAL_LOADMODULE_GLOBAL
| SAL_LOADMODULE_NOW
))
616 // Must be SAL_LOADMODULE_GLOBAL when e.g. specifying a
617 // -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 option to
618 // JDK 1.8.0_121 at least, as JNI_CreateJavaVM -> Threads::create_vm ->
619 // JvmtiExport::post_vm_initialized -> cbEarlyVMInit -> initialize ->
620 // util_initialize -> sun.misc.VMSupport.getAgentProperties ->
621 // Java_sun_misc_VMSupport_initAgentProperties ->
622 // JDK_FindJvmEntry("JVM_INitAgentProperties") ->
623 // dlsym(RTLD_DEFAULT, "JVM_INitAgentProperties"):
624 if (!moduleRt
.load(sRuntimeLib
, SAL_LOADMODULE_GLOBAL
))
627 do_msvcr_magic(sRuntimeLib
);
629 if (!moduleRt
.load(sRuntimeLib
))
633 "[Java framework]sunjavaplugin" SAL_DLLEXTENSION
634 " could not load Java runtime library: \n"
635 + sRuntimeLib
+ "\n");
636 JFW_TRACE0("Could not load Java runtime library: " << sRuntimeLib
);
637 return javaPluginError::VmCreationFailed
;
640 #if defined UNX && !defined MACOSX
641 //Setting the JAVA_HOME is needed for awt
642 OUString sPathLocation
;
643 osl::FileBase::getSystemPathFromFileURL(pInfo
->sLocation
, sPathLocation
);
644 osl_setEnvironment(OUString("JAVA_HOME").pData
, sPathLocation
.pData
);
647 typedef jint JNICALL
JNI_CreateVM_Type(JavaVM
**, JNIEnv
**, void *);
648 OUString
sSymbolCreateJava("JNI_CreateJavaVM");
650 JNI_CreateVM_Type
* pCreateJavaVM
=
651 reinterpret_cast<JNI_CreateVM_Type
*>(moduleRt
.getFunctionSymbol(sSymbolCreateJava
));
655 OString sLib
= OUStringToOString(
656 sRuntimeLib
, osl_getThreadTextEncoding());
657 OString sSymbol
= OUStringToOString(
658 sSymbolCreateJava
, osl_getThreadTextEncoding());
659 fprintf(stderr
,"[Java framework]sunjavaplugin" SAL_DLLEXTENSION
660 "Java runtime library: %s does not export symbol %s !\n",
661 sLib
.getStr(), sSymbol
.getStr());
662 return javaPluginError::VmCreationFailed
;
666 // Valgrind typically emits many false errors when executing JIT'ed JVM
667 // code, so force the JVM into interpreted mode:
668 bool addForceInterpreted
= FORCE_INTERPRETED
> 0;
670 // Some testing with Java 1.4 showed that JavaVMOption.optionString has to
671 // be encoded with the system encoding (i.e., osl_getThreadTextEncoding):
672 JavaVMInitArgs vm_args
;
675 Option(OString
const & theOptionString
, void * theExtraInfo
):
676 optionString(theOptionString
), extraInfo(theExtraInfo
)
679 OString optionString
;
682 std::vector
<Option
> options
;
684 // We set an abort handler which is called when the VM calls _exit during
685 // JNI_CreateJavaVM. This happens when the LD_LIBRARY_PATH does not contain
686 // all some directories of the Java installation. This is necessary for
687 // all versions below 1.5.1
688 options
.emplace_back("abort", reinterpret_cast<void*>(abort_handler
));
689 bool hasStackSize
= false;
690 for (int i
= 0; i
< cOptions
; i
++)
692 OString
opt(arOptions
[i
].optionString
);
694 // Until java 1.5 we need to put a plugin.jar or javaplugin.jar (<1.4.2)
695 // in the class path in order to have applet support:
696 if (opt
.startsWith("-Djava.class.path="))
698 OString sAddPath
= getPluginJarPath(pInfo
->sVendor
, pInfo
->sLocation
,pInfo
->sVersion
);
699 if (!sAddPath
.isEmpty())
700 opt
+= OString(SAL_PATHSEPARATOR
) + sAddPath
;
703 if (opt
== "-Xint") {
704 addForceInterpreted
= false;
706 if (opt
.startsWith("-Xss")) {
709 options
.emplace_back(opt
, arOptions
[i
].extraInfo
);
711 if (addForceInterpreted
) {
712 options
.emplace_back("-Xint", nullptr);
715 #if defined LINUX && (defined X86 || defined X86_64)
716 // At least OpenJDK 1.8.0's os::workaround_expand_exec_shield_cs_limit
717 // (hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp) can mmap an rwx
718 // page into the area that the main stack can grow down to according to
719 // "ulimit -s", as os::init_2's (hotspot/src/os/linux/vm/os_linux.cpp)
722 // Linux::capture_initial_stack(JavaThread::stack_size_at_create());
724 // caps _initial_thread_stack_size at threadStackSizeInBytes ,i.e.,
725 // -Xss, which appears to default to only 327680, whereas "ulimit -s"
726 // defaults to 8192 * 1024 at least on Fedora 20; so attempt to pass in
727 // a useful -Xss argument:
729 if (getrlimit(RLIMIT_STACK
, &l
) == 0) {
730 if (l
.rlim_cur
== RLIM_INFINITY
) {
731 SAL_INFO("jfw", "RLIMIT_STACK RLIM_INFINITY -> 8192K");
732 l
.rlim_cur
= 8192 * 1024;
733 } else if (l
.rlim_cur
> 512 * 1024 * 1024) {
735 "jfw", "huge RLIMIT_STACK " << l
.rlim_cur
<< " -> 8192K");
736 l
.rlim_cur
= 8192 * 1024;
738 options
.emplace_back("-Xss" + OString::number(l
.rlim_cur
), nullptr);
741 SAL_WARN("jfw", "getrlimit(RLIMIT_STACK) failed with errno " << e
);
746 std::unique_ptr
<JavaVMOption
[]> sarOptions(new JavaVMOption
[options
.size()]);
747 for (std::vector
<Option
>::size_type i
= 0; i
!= options
.size(); ++i
) {
750 "VM option \"" << options
[i
].optionString
<< "\" "
751 << options
[i
].extraInfo
);
752 sarOptions
[i
].optionString
= const_cast<char *>(
753 options
[i
].optionString
.getStr());
754 sarOptions
[i
].extraInfo
= options
[i
].extraInfo
;
758 vm_args
.version
= JNI_VERSION_1_4
; // issue 88987
760 vm_args
.version
= JNI_VERSION_1_2
;
762 vm_args
.options
= sarOptions
.get();
763 vm_args
.nOptions
= options
.size(); //TODO overflow
764 vm_args
.ignoreUnrecognized
= JNI_TRUE
;
766 /* We set a global flag which is used by the abort handler in order to
767 determine whether it is should use longjmp to get back into this function.
768 That is, the abort handler determines if it is on the same stack as this function
769 and then jumps back into this function.
773 JavaVM
* pJavaVM
= nullptr;
774 memset( jmp_jvm_abort
, 0, sizeof(jmp_jvm_abort
));
775 int jmpval
= setjmp( jmp_jvm_abort
);
776 /* If jmpval is not "0" then this point was reached by a longjmp in the
777 abort_handler, which was called indirectly by JNI_CreateVM.
781 //returns negative number on failure
782 err
= pCreateJavaVM(&pJavaVM
, ppEnv
, &vm_args
);
786 // set err to a positive number, so as or recognize that an abort (longjmp)
794 fprintf(stderr
,"[Java framework] sunjavaplugin" SAL_DLLEXTENSION
795 "Can not create Java Virtual Machine, %" SAL_PRIdINT32
"\n", sal_Int32(err
));
796 errorcode
= javaPluginError::VmCreationFailed
;
800 fprintf(stderr
,"[Java framework] sunjavaplugin" SAL_DLLEXTENSION
801 "Can not create JavaVirtualMachine, abort handler was called.\n");
802 errorcode
= javaPluginError::VmCreationFailed
;
808 JFW_TRACE2("JVM created");
814 // On Android we always have a Java VM as we only expect this code
815 // to be run in an Android app anyway.
816 *ppVm
= lo_get_javavm();
817 fprintf(stderr
, "lo_get_javavm returns %p", *ppVm
);
821 #if defined __GNUC__ && __GNUC__ == 7 && !defined __clang__
822 #pragma GCC diagnostic push
823 #pragma GCC diagnostic ignored "-Wclobbered"
826 #if defined __GNUC__ && __GNUC__ == 7 && !defined __clang__
827 #pragma GCC diagnostic pop
830 javaPluginError
jfw_plugin_existJRE(const JavaInfo
*pInfo
, bool *exist
)
832 assert(pInfo
!= nullptr);
833 assert(exist
!= nullptr);
835 javaPluginError ret
= javaPluginError::NONE
;
836 OUString
sLocation(pInfo
->sLocation
);
838 if (sLocation
.isEmpty())
839 return javaPluginError::InvalidArg
;
840 ::osl::DirectoryItem item
;
841 ::osl::File::RC rc_item
= ::osl::DirectoryItem::get(sLocation
, item
);
842 if (::osl::File::E_None
== rc_item
)
846 else if (::osl::File::E_NOENT
== rc_item
)
852 ret
= javaPluginError::Error
;
854 //We can have the situation that the JavaVM runtime library is not
855 //contained within JAVA_HOME. Then the check for JAVA_HOME would return
856 //true although the runtime library may not be loadable.
857 //Or the JAVA_HOME directory of a deinstalled JRE left behind.
858 if (ret
== javaPluginError::NONE
&& *exist
)
860 OUString sRuntimeLib
= getRuntimeLib(pInfo
->arVendorData
);
861 JFW_TRACE2("Checking existence of Java runtime library");
863 ::osl::DirectoryItem itemRt
;
864 ::osl::File::RC rc_itemRt
= ::osl::DirectoryItem::get(sRuntimeLib
, itemRt
);
865 if (::osl::File::E_None
== rc_itemRt
)
868 JFW_TRACE2("Java runtime library exist: " << sRuntimeLib
);
871 else if (::osl::File::E_NOENT
== rc_itemRt
)
874 JFW_TRACE2("Java runtime library does not exist: " << sRuntimeLib
);
878 ret
= javaPluginError::Error
;
879 JFW_TRACE2("Error while looking for Java runtime library: " << sRuntimeLib
);
886 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */