JDK-7131356 : (props) "No Java runtime present, requesting install" when creating VM from JNI [macosx]
  • Type: Sub-task
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 7,9
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: os_x
  • CPU: generic
  • Submitted: 2012-01-19
  • Updated: 2019-03-18
  • Resolved: 2016-06-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
8u152Fixed 9 b125Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
On some Mac OS machines, if one tries to create Java VM from native executable using JNI, they will get "No Java runtime present, requesting install." message and the program will simply exit. In graphical session, there will be a popup "To open JavaApplication, you need a Java runtime. Would you like to install one now?" "Not now" "Install". DYLD_LIBRARY_PATH is set correctly.

It seems to depend on whether default Mac OS Java is installed or not (running /usr/bin/java will get same message and popup). I suspect that accepting and installing system Java would fix the issue.

This is a problem: starting Java VM using another location (even from JNI) should not depend on system Java.

This change has broken the os.version property - see JDK-8160370

noreg-other: The primary issue of this bug, the failure to start up the VM from JNI in the absence of the default Mac Java, can be tested by re-enabling existing VM tests. noreg-hard: The Locale-related changes would be difficult to regtest, as they would require test machines to be setup set to particular languages.

If needed for future reference, an explanation of Apple's language and locale identifiers: https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html (BCP 47 allows 3-digit UN M.49 codes for the region, e.g. "es-419" for Latin American Spanish, though this possibility is not called out in the tables.)

Attached the code I uses to test locales. Also attached some basic C code to list the Preferred Languages (to list all available languages, one should add them to the "Preferred languages" list in the Language & Region system preference).

This seems to have languished. But we also seem to have moved past this on the VM side for testing purposes - can someone clarify that please.

Excluding these tests until the bug is fixed.

This is part of what will be a larger project to stop reliance on Apple's JavaVM frameworks (JDK-8024281). I've converted this bug to a subtask. We are too late in the 8 product cycle to sufficiently test all environments and locales to ensure a change to the code in question works correctly in all cases. Given this is not a new issue in 8, we're going to hold off on this until a later release.

This should be possible to work around. From a conversation with Dave: "you need to link libjli before JavaVM.framework (or any framework that pulls JavaVM in, like JNF/JRS), it will be loaded by the executable which will force dyld to use it's version of JNI_CreateJavaVM."

Brent - can you look at this one, it looks like it has been moved from another group to core-libs/java.lang. It looks like they are changing the properties initialization, this is code that you recently changed and not clear if we still have an issue or not.

I had Anthony and Artem review the proposed fix at https://sthinfra10.se.oracle.com/cru/CR-JDK7UCPU-92

Removing myself from the issue as this is not a hotspot, but jdk (globalization) issue, however, I will remain watching it in case anyone has questions for me.

Attaching a patch with a proposed fix.

Here is my understanding of the issue: The symptoms: On those OS X machines where the default system Java is not installed, any attempt to instantiate JVM from a local JDK (for example via JNI as shown in the bug) presents "No Java installed. Do you want to install Java?" dialog and refuses to run. Clearly, a valid local JDK should be able to run in this case. The problem: In jdk/java_props_macosx.c there is code that dynamically looks up 4 methods in JavaRuntimeSupport.framework (JRS) and calls into them to find out localized OS version, default locale and the preferred language, but JRS checks for a system available Java and refuses to run if none found. Background: JavaRuntimeSupport.framework (JRS) is a framework implemented and provided by Apple for a single client - ie. us, Java. It is a "black box" that wraps up those SPIs that are required by Apple provided implementation of JDK and exposes them to the JDK as APIs. Now that the JDK implementation ownership has changed from Apple to us, we are left with the following issue - we don't control the JRS implementation, yet rely on Apple to support it for our JDK to continue to run. According to Apple's own comments (file java_props_macosx.c): /* Don't rely on JRSCopyOSName because there's no guarantee the value will * remain the same, or even if the JRS functions will continue to be part of * Mac OS X. So hardcode os_name, and fill in os_version if we can. */ so apparently there is no guarantee that JRS will continue to be part of OS X (?), but even if it did, depending on a private framework provided by a third party (ie. Apple) just for us (JDK is the only official client allowed to call into JSR) for our code to continue to run doesn't seem like a good long term bet. Proposed solution (jdk/java_props_macosx.c): Apple has suggested that we change the initialization order of our JDK code so that any access to JSR happens only after JLI_MemAlloc symbol is available. I haven't looked into this suggestion, however, as I believe that a much better solution is to simply re-implement the JSR APIs in question and drop our reliance on JSR altogether: 1. We re-implement "setOSNameAndVersion" and instead of calling "JRSCopyOSVersion" we use CoreFoundation APIs to look up the OS version in similar way that Apple itself does (ie. see CFCopySystemVersionString in http://www.opensource.apple.com/source/CF/CF-744.19/CFUtilities.c) 2. In "getMacOSXLocale" we implement "JRSCopyPrimaryLanguage" using "CFLocaleCopyPreferredLanguages", which gives us the preferred language as set in "System Preferences", "Language & Text", "Language" in the form of "xx" (ie. just the language code - ex. "en", "fr", etc.) The original Apple's code then calls into "JRSCopyCanonicalLanguageForPrimaryLanguage" to map "language" into "language_REGION" (ex. "en"-->"en_US", "fr"-->"fr_FR", etc.) I have been unable to figure out the exact algorithm that matches the "xx" code into "xx_XX" one (it's not as trivial as it seems on the surface), but it seems that this is not actually necessary at this code level, as the region code gets added by the code implementation above it. I have verified this with all possible settings of the language that Mac OS X allows (see "All Mac OS X Preferred Languages List.txt" in the bug), though I would appreciate it if others (especially those living in countries other than the US) could try the "test" attached to the bug and make sure that the returned locales make sense. 3. In "setupMacOSXLocale" we simply drop the call to "JRSSetDefaultLocalization" for now as it appears to be a NOP. According to Apple, that API sets up native bundle locale, so that any access to native Cocoa UI (like FileOpenChooser) uses localized strings. My testing, however, shows that this does not seem to work even in Apple's own JDK (ie. JDK 6), so dropping the call to this SPI here does not result in regression, though, we will need to look into this to see whether this is an actual issue ot not - filed JDK-8024279 to track this (please see "JFileChooserTest" attached to the bug). Followup issues: JDK-8024279 Mac OS X: should CocoaUI elements (such as Dialog Chooser) use localized messages? JDK-8024280 Mac OS X: provide JDK framework for Mac developers JDK-8024281 Mac OS X: stop relaying on Apple's JavaRuntimeFramework

Note that there's a separate bug regarding the FileDialog l10n: JDK-8019464. I see that the above tests have been performed with the JFileChooser. Does the fix have any effect on the AWT FileDialog wrt. l10n?

Changed the component from "Hotspot" to "Globalization" - the actual file changed is in jdk7u/jdk/src/solaris/native/java/lang/java_props_macosx.c

I can't seem to be able to attach the list of available languages as an attachment because the system complains it might contain a malware, so I will include the list as a comment: "af", "af_ZA", "Afrikaans (South Africa)", "am", "am", "Amharic", "ar", "ar", "Arabic", "as", "as", "Assamese", "ay", "ay", "Aymara", "az-Cyrl", "az-Cyrl", "Azerbaijani (Cyrillic)", "az-Latn", "az", "Azerbaijani", "be", "be_BY", "Belarusian (Belarus)", "bg", "bg_BG", "Bulgarian (Bulgaria)", "bi", "bi", "Bislama", "bn", "bn", "Bengali", "bo", "bo", "Tibetan", "br", "br", "Breton", "bs", "bs", "Bosnian", "ca", "ca_ES", "Catalan (Spain)", "chr", "chr", "Cherokee", "co", "co", "Corsican", "cs", "cs_CZ", "Czech (Czech Republic)", "cy", "cy", "Welsh", "da", "da_DK", "Danish (Denmark)", "de", "de_DE", "German (Germany)", "de-AT", "de_AT", "German (Austria)", "de-CH", "de_CH", "German (Switzerland)", "dz", "dz_BT", "Dzongkha (Bhutan)", "el", "el_GR", "Greek (Greece)", "en", "en_US", "English (United States)", "en-AU", "en_AU", "English (Australia)", "en-CA", "en_CA", "English (Canada)", "en-GB", "en_GB", "English (United Kingdom)", "en-US", "en_US", "English (United States)", "eo", "eo", "Esperanto", "es", "es_ES", "Spanish (Spain)", "es-419", "es_XL", "Spanish (XL)", "es-ES", "es_ES", "Spanish (Spain)", "et", "et_EE", "Estonian (Estonia)", "eu", "eu", "Basque", "fa", "fa_IR", "Persian (Iran)", "fi", "fi_FI", "Finnish (Finland)", "fo", "fo_FO", "Faroese (Faroe Islands)", "fr", "fr_FR", "French (France)", "fr-CA", "fr_CA", "French (Canada)", "fr-CH", "fr_CH", "French (Switzerland)", "ga", "ga_IE", "Irish (Ireland)", "gd", "gd", "Scottish Gaelic", "gl", "gl", "Galician", "gn", "gn", "Guarani", "gsw", "gsw", "Swiss German", "gu", "gu_IN", "Gujarati (India)", "gv", "gv", "Manx", "haw", "haw", "Hawaiian", "he", "he_IL", "Hebrew (Israel)", "hi", "hi_IN", "Hindi (India)", "hr", "hr_HR", "Croatian (Croatia)", "ht", "ht", "Haitian", "hu", "hu_HU", "Hungarian (Hungary)", "hy", "hy_AM", "Armenian (Armenia)", "id", "id", "Indonesian", "io", "io", "Ido", "is", "is_IS", "Icelandic (Iceland)", "it", "it_IT", "Italian (Italy)", "iu", "iu_CA", "Inuktitut (Canada)", "ja", "ja_JP", "Japanese (Japan)", "ka", "ka_GE", "Georgian (Georgia)", "kk", "kk", "Kazakh", "kl", "kl", "Kalaallisut", "km", "km", "Khmer", "kn", "kn", "Kannada", "ko", "ko_KR", "Korean (South Korea)", "kok", "kok", "Konkani", "kw", "kw", "Cornish", "ky", "ky", "Kirghiz", "ky-Cyrl", "ky", "Kirghiz", "la", "la", "Latin", "lb", "lb", "Luxembourgish", "lo", "lo", "Lao", "lt", "lt_LT", "Lithuanian (Lithuania)", "lv", "lv_LV", "Latvian (Latvia)", "mg", "mg", "Malagasy", "mi", "mi", "Maori", "mk", "mk_MK", "Macedonian (Macedonia)", "ml", "ml", "Malayalam", "mn", "mn", "Mongolian", "mr", "mr_IN", "Marathi (India)", "ms", "ms", "Malay", "mt", "mt_MT", "Maltese (Malta)", "my", "my", "Burmese", "nap", "nap", "Neapolitan", "nb", "nb_NO", "Norwegian Bokm��l (Norway)", "ne", "ne_NP", "Nepali (Nepal)", "nl", "nl_NL", "Dutch (Netherlands)", "nl-BE", "nl_BE", "Dutch (Belgium)", "nn", "nn_NO", "Norwegian Nynorsk (Norway)", "nv", "nv", "Navajo", "oc", "oc", "Occitan", "om", "om", "Oromo", "or", "or", "Oriya", "pa", "pa", "Punjabi", "pl", "pl_PL", "Polish (Poland)", "ps", "ps", "Pashto", "pt", "pt_BR", "Portuguese (Brazil)", "pt-BR", "pt_BR", "Portuguese (Brazil)", "pt-PT", "pt_PT", "Portuguese (Portugal)", "qu", "qu", "Quechua", "rn", "rn", "Rundi", "ro", "ro_RO", "Romanian (Romania)", "ru", "ru_RU", "Russian (Russia)", "rw", "rw", "Kinyarwanda", "sa", "sa", "Sanskrit", "scn", "scn", "Sicilian", "se", "se", "Northern Sami", "si", "si", "Sinhala", "sk", "sk_SK", "Slovak (Slovakia)", "sl", "sl_SI", "Slovenian (Slovenia)", "so", "so", "Somali", "sq", "sq", "Albanian", "sr", "sr_CS", "Serbian (Serbia and Montenegro)", "sv", "sv_SE", "Swedish (Sweden)", "sw", "sw", "Swahili", "ta", "ta", "Tamil", "te", "te", "Telugu", "tg", "tg", "Tajik", "th", "th_TH", "Thai (Thailand)", "tk-Cyrl", "tk-Cyrl", "Turkmen (Cyrillic)", "tk-Latn", "tk-Cyrl", "Turkmen (Cyrillic)", "tl", "fil", "Filipino", "tlh", "tlh", "Klingon", "to", "to_TO", "Tongan (Tonga)", "tr", "tr_TR", "Turkish (Turkey)", "tt-Cyrl", "tt-Cyrl", "Tatar (Cyrillic)", "tt-Latn", "tt-Cyrl", "Tatar (Cyrillic)", "ug", "ug", "Uighur", "uk", "uk_UA", "Ukrainian (Ukraine)", "ur", "ur_PK", "Urdu (Pakistan)", "uz", "uz_UZ", "Uzbek (Uzbekistan)", "uz-Cyrl", "uz_UZ", "Uzbek (Uzbekistan)", "uz-Latn", "uz_UZ", "Uzbek (Uzbekistan)", "vi", "vi_VN", "Vietnamese (Vietnam)", "wa", "wa", "Walloon", "yi", "yi", "Yiddish", "zh-Hans", "zh_CN", "Chinese (China)", "zh-Hant", "zh_TW", "Chinese (Taiwan)", "zu", "zu", "Zulu"

Attaching JFileChooser showing whether the CocoaUI file dialog uses localized strings.

Adding basic Java test showing locales.

Adding NetBeans test printing locale and using Open File Dialog.

I have replaced the 3 out of 4 APIs we were using in JavaRuntimeSupport. The 4th API, ie. JRSSetDefaultLocalization, according to Apple is used to set locale of bundle, so that the strings in Cocoa components, such as Open File Dialog, show according to the locale, but from my testing this doesn't appear to work. Is JFileChooser using localized strings (ie. Open) if locale is set either using System Preferences (ie. "Language & Text"), or overriden using Java command parameter (ie. -Duser.language=pl -Duser.country=PL): Java.....................System Preferences...........Java command JDK6 (Apple).........YES..................................NO JDK7....................NO....................................NO JDK8 (original).......NO....................................NO JDK8 (fix)..............NO....................................NO So, it appears this used to work (using System Preferences to change the locale) for JDK6, but starting with JDK7, this no longer works, so this API seems to be a NOP in JDK7,JDK8 The conclusion then are that this API does not need to be implemented at this time, though we do have a bigger issue with localization that seems to have regressed since JDK6. We'll need a new issue filed to address this.

This is the reason we end up invoking OS system Java warning - we pull in system JavaRuntimeSupport library by java_props_macosx.c static void *getJRSFramework() { static void *jrsFwk = NULL; if (jrsFwk == NULL) { jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL); } return jrsFwk; }

Verified (using dladdr) that in fact the JNI_CreateJavaVM method called is the from our own jdk that we link against, ex: JNI_CreateJavaVM found in /Volumes/work/jdk/jdk8/build/macosx-x86_64-normal-server-slowdebug/jdk/lib/server/libjvm.dylib After debugging JNI_CreateJavaVM it seems that it does not return in the case where the OS reports it needs to install Java. Looking deeper into it, we exit from: Threads::threads_do at the time it tries to call: // The VM creates & returns objects of this class. Make sure it's initialized. initialize_class(vmSymbols::java_lang_Class(), CHECK_0);

A simple workaround would be to dynamically look up JNI calls using our own jvm directly. I will continue to investigate, however, how we can tell the OS to load our jvm before its own.

> otool -LD jni jni: @rpath/libjvm.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0) Even though we explicitly link against our own jvm lib using "-L /Volumes/work/bugs/7131356/jnimac/jre1.7.0_25.jre/Contents/Home/lib/server -ljvm" the linker uses @rpath to reference the library and later at the launch time again despite the fact that we set "DYLD_INSERT_LIBRARIES=$JAVA_HOME/lib/server/libjvm.dylib DYLD_LIBRARY_PATH=$JAVA_HOME/lib/server" the system seems to prefer the OS built-in jvm lib, which throws the error about "Java not installed" on vanillla OSes.

Please check if this is an installation issue or a runtime issue.