You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by va...@apache.org on 2006/12/15 09:33:23 UTC

svn commit: r487483 [2/4] - in /harmony/enhanced/drlvm/trunk: build/make/targets/ vm/interpreter/src/ vm/jitrino/src/jet/ vm/port/src/lil/em64t/pim/ vm/port/src/lil/ia32/pim/ vm/port/src/lil/ipf/pim/ vm/tests/smoke/shutdown/ vm/vmcore/include/ vm/vmcor...

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_properties.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_properties.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_properties.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_properties.cpp Fri Dec 15 00:33:21 2006
@@ -1,395 +1,394 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#include <apr_file_io.h>
-#include <apr_file_info.h>
-#include <apr_env.h>
-#include <apr_strings.h>
-#include "port_dso.h"
-#include "port_filepath.h"
-#include "port_sysinfo.h"
-
-#define LOG_DOMAIN "init.properties"
-#include "cxxlog.h"
-#include "properties.h"
-#include "vm_properties.h"
-#include "init.h"
-
-inline char* unquote(char *str)
-{
-    const char *tokens = " \t\n\r\'\"";
-    size_t i = strspn(str, tokens);
-    str += i;
-    char *p = str + strlen(str) - 1;
-    while(strchr(tokens, *p) && p >= str)
-        *(p--) = '\0';
-    return str;
-}
-
-#define PROP_ENV_NAME  "VM_PROPERTIES"
-#define PROP_FILE_NAME "vm.properties"
-
-#define MAX_PROP_LINE 5120
-
-// local memory pool for temporary allocation
-static apr_pool_t *prop_pool;
-
-static void
-read_properties(char *fname, Properties & prop)
-{
-    apr_file_t *f;
-    char *src, *tok;
-    if (APR_SUCCESS != apr_file_open(&f, fname, APR_FOPEN_READ, 0, prop_pool))
-        return;
-    WARN("USAGE OF vm.properties FILE IS DEPRECATED. THIS FUNCTIONALITY WILL BE REMOVED SOON. ALL PROPERTIES SHOULD BE SET ON COMMAND LINE");
-    char buf[MAX_PROP_LINE];
-    while (!apr_file_eof(f) && !apr_file_gets(buf, MAX_PROP_LINE, f))
-    {
-        if (buf[0] != '#') {
-            src = strdup(buf);
-            tok = strchr(src, '=');
-            if(tok)
-            {
-                *tok = '\0';
-                prop.set(unquote(src), unquote(tok + 1));
-            }
-            STD_FREE(src);
-        }
-    }
-    apr_file_close(f);
-}
-
-#define API_DLL1 "harmonyvm"
-#define API_DLL2 "hythr"
-#define API_DLL3 "hysig"
-#define API_DLL4 "hyprt"
-#define API_DLL5 "hyzlib"
-#define API_DLL6 "hytext"
-#define API_DLL7 "hynio"
-#define API_DLL8 "vmi"
-#define API_DLLA "hyluni"
-#define API_DLLB "hyarchive"
-
-#define GC_DLL "gc_cc"
-
-/**
- *  Compose a string of file names each of them beginning with path,
- *  names separated by PORT_PATH_SEPARATOR.  If patch is NULL, no path
- *  or separator will be prefixed
- */
-static char *compose_full_files_path_names_list(const char *path,
-                                                const char **dll_names,
-                                                const int names_number, 
-                                                bool is_dll)
-{
-    char* full_name = "";
-    for (int iii = 0; iii < names_number; iii++)
-    {
-        const char *tmp = dll_names[iii];
-        if (is_dll) {
-            tmp = port_dso_name_decorate(tmp, prop_pool);
-        }
-        
-        /*
-         *  if the path is non-null, prefix, otherwise do nothing
-         *  to avoid the problem of "/libfoo.so" when we don't want
-         *  a path attached
-         */
-         
-        if (path != NULL) { 
-            tmp = port_filepath_merge(path, tmp, prop_pool);
-        }
-        
-        full_name = apr_pstrcat(prop_pool, full_name, tmp, 
-            (iii + 1 < names_number) ? PORT_PATH_SEPARATOR_STR : "", NULL);
-    }
-
-    return full_name;
-}
-
-static void init_java_properties(Properties & properties)
-{
-    //java part
-    //!!! java.compiler property must be defined by EM
-
-    char *os_name, *os_version, *path;
-    const char *tmp;
-    char *path_buf = NULL;
-
-    port_OS_name_version(&os_name, &os_version, prop_pool);
-    apr_filepath_get(&path, APR_FILEPATH_NATIVE, prop_pool);
-    if (APR_SUCCESS != apr_temp_dir_get(&tmp, prop_pool)) {
-        tmp = ".";
-    }
-    properties.set("java.version", "1.5.0");
-    properties.set("java.vendor", "Apache Software Foundation");
-    properties.set("java.vendor.url", "http://harmony.apache.org");
-    // java.home initialization, try to find absolute location of the executable and set
-    // java.home to the parent directory.
-    char *base_path_buf;
-    if (port_executable_name(&base_path_buf, prop_pool) != APR_SUCCESS) {
-        DIE("Failed to find executable location");
-    }
-    // directory for the executable
-    char *p = strrchr(base_path_buf, PORT_FILE_SEPARATOR);
-    if (NULL == p)
-        DIE("Failed to determine executable parent directory");
-    *p = '\0';
-    // home directory
-    char* home_path = apr_pstrdup(prop_pool, base_path_buf);
-    p = strrchr(home_path, PORT_FILE_SEPARATOR);
-    if (NULL == p)
-        DIE("Failed to determine java home directory");
-    *p = '\0';
-
-    properties.set("java.home", home_path);
-    properties.set("java.vm.specification.version", "1.0");
-    properties.set("java.vm.specification.vendor", "Sun Microsystems Inc.");
-    properties.set("java.vm.specification.name", "Java Virtual Machine Specification");
-    properties.set("java.vm.version", "11.2.0");
-    properties.set("java.vm.vendor", "Apache Software Foundation");
-    properties.set("java.vm.name", "DRLVM");
-    properties.set("java.specification.version", "1.5");
-    properties.set("java.specification.vendor", "Sun Microsystems Inc.");
-    properties.set("java.specification.name", "Java Platform API Specification");
-    properties.set("java.class.version", "49.0");
-    properties.set("java.class.path", ".");
-
-    // java.library.path initialization, the value is the location of VM executable,
-    // prepended to OS library search path
-    char *env;
-    char *lib_path = base_path_buf;
-    if (APR_SUCCESS == port_dso_search_path(&env, prop_pool))
-    {
-        lib_path = apr_pstrcat(prop_pool, base_path_buf, PORT_PATH_SEPARATOR_STR,
-                               base_path_buf, PORT_FILE_SEPARATOR_STR, "default",
-                               PORT_PATH_SEPARATOR_STR, env, NULL);
-    }
-    properties.set("java.library.path", lib_path);
-    //java.ext.dirs initialization.
-    char *ext_path = port_filepath_merge(home_path, "lib" PORT_FILE_SEPARATOR_STR "ext", prop_pool);
-    properties.set("java.ext.dirs", ext_path);
-    properties.set("os.name", os_name);
-    properties.set("os.arch", port_CPU_architecture());
-    properties.set("os.version", os_version);
-    properties.set("file.separator", PORT_FILE_SEPARATOR_STR);
-    properties.set("path.separator", PORT_PATH_SEPARATOR_STR);
-    properties.set("line.separator", APR_EOL_STR);
-    // user.name initialization, try to get the name from the system
-    char *user_buf;
-    apr_status_t status = port_user_name(&user_buf, prop_pool);
-    if (APR_SUCCESS != status) {
-        DIE("Failed to get user name from the system. Error code " << status);
-    }
-    properties.set("user.name", user_buf);
-    // user.home initialization, try to get home from the system.
-    char *user_home;
-    status = port_user_home(&user_home, prop_pool);
-    if (APR_SUCCESS != status) {
-        DIE("Failed to get user home from the system. Error code " << status);
-    }
-    properties.set("user.home", user_home);
-    // java.io.tmpdir initialization. 
-    const char *tmpdir;
-    status = apr_temp_dir_get(&tmpdir, prop_pool);
-    if (APR_SUCCESS != status) {
-        tmpdir = user_home;
-    }
-    properties.set("java.io.tmpdir", tmpdir);
-    properties.set("user.dir", path);
-
-    // FIXME??? other (not required by api specification) properties
-    
-    properties.set("java.vm.info", "no info");
-    properties.set("java.tmpdir", tmp);
-    properties.set("user.language", "en");
-    properties.set("user.region", "US");
-    properties.set("file.encoding", "8859_1");
-
-    // FIXME user.timezone initialization, required by java.util.TimeZone implementation
-    char *user_tz;
-    status = port_user_timezone(&user_tz, prop_pool);
-    if (APR_SUCCESS != status) {
-        INFO("Failed to get user timezone from the system. Error code " << status);
-        user_tz = "GMT";
-    }
-    
-    properties.set("user.timezone", user_tz);
-
-    // FIXME: This is a workaround code for third party APIs which depend on this property.
-    properties.set("java.util.prefs.PreferencesFactory",
-#ifdef PLATFORM_NT
-        "java.util.prefs.RegistryPreferencesFactoryImpl");
-#else
-        "java.util.prefs.FilePreferencesFactoryImpl");
-#endif
-
-    // Added for compatibility with the external java JDWP agent
-    properties.set("sun.boot.library.path", base_path_buf);
-
-    /*
-    *  it's possible someone forgot to set this property - set to default of .
-    */
-    if (!properties.is_set(O_A_H_VM_VMDIR)) {
-        TRACE2("init", "o.a.h.vm.vmdir not set - setting predefined value of as '.'");
-        properties.set(O_A_H_VM_VMDIR, ".");
-    }
-
-    /*
-    *  also, do the same for java.class.path
-    */
-    if (!properties.is_set("java.class.path")) {
-        TRACE2("init", "java.class.path not set - setting predefined value of as '.'");
-        properties.set("java.class.path", ".");
-    }
-}
-
-//vm part
-static void init_vm_properties(Properties & properties)
-{
-        properties.set("vm.assert_dialog", "true");
-        properties.set("vm.crash_handler", "false");
-        properties.set("vm.finalize", "true");
-        properties.set("vm.jit_may_inline_sync", "true");
-        properties.set("vm.use_verifier", "true");
-        properties.set("vm.jvmti.enabled", "false");
-        properties.set("vm.cleanupOnExit", "false");
-        properties.set("vm.bootclasspath.appendclasspath", "false");
-
-        /*
-        *  vm.boot.library.path initialization, the value is the location of VM executable
-        * 
-        *  2006-09-06 gmj :  there's no reason to ever believe this is true given how the VM can be 
-        *  launched in a mariad of ways, so just set to empty string.
-        */
-        properties.set("vm.boot.library.path", "");
-
-        properties.set("vm.dlls", PORT_DSO_NAME(GC_DLL));
-
-        // vm.other_natives_dlls initialization, the value is location of VM executable.
-        const char *api_dll_files[] =
-        {
-            API_DLL1,
-                API_DLL2,
-                API_DLL3,
-                API_DLL4,
-                API_DLL5,
-                API_DLL6,
-                API_DLL7,
-                API_DLL8,
-                API_DLLA,
-                API_DLLB
-        };
-        int n_api_dll_files = sizeof(api_dll_files) / sizeof(char *);
-        /*
-        *  pass NULL for the pathname as we don't want 
-        *  any path pre-pended
-        */
-        char* path_buf = compose_full_files_path_names_list(NULL, api_dll_files, n_api_dll_files, true);
-        properties.set("vm.other_natives_dlls", path_buf);
-}
-
-void
-initialize_properties(Global_Env * p_env)
-{
-    if (!prop_pool) {
-        apr_pool_create(&prop_pool, 0);
-    }
-/*
- * 0. Add predefined properties from property table
- */
-     
-    init_java_properties(*p_env->JavaProperties());
-    init_vm_properties(*p_env->VmProperties());
-
-/* 
- * 1. VM looks for an environment variable, say, 
- *    VM_PROPERTIES=d:\xyz\eee\vm.Properties, read the Properties;
- */
-    char *pf;
-    if (apr_env_get(&pf, PROP_ENV_NAME, prop_pool) == APR_SUCCESS){
-        read_properties(pf, *p_env->JavaProperties());
-    }
-/*
- * 2. Looks for vm.Properties in the directory where vm executable resides 
- *    (it's also a global file), read the Properties, if key is duplicated, 
- *    override the value;
- */
-    char *buf;
-    if (port_executable_name(&buf, prop_pool) == APR_SUCCESS)
-    {
-        char *p = strrchr(buf, PORT_FILE_SEPARATOR);
-        if (p)
-        {
-            *(p + 1) = '\0';
-            buf = apr_pstrcat(prop_pool, buf, PROP_FILE_NAME, NULL);
-            read_properties(buf, *p_env->JavaProperties());
-        }
-    }
-
-/*
- * 3. Looks for it in current directory(it's an app-specific file), read the 
- *    Properties, if key is duplicated, override the value;
- */
-    apr_filepath_get(&buf, 0, prop_pool);
-    buf = port_filepath_merge(buf, PROP_FILE_NAME, prop_pool);
-    read_properties(buf, *p_env->JavaProperties());
-/*
- * 4. Check whether there is a command line option, say, 
- *    -Properties-file "d:\xyz\eee\vm.Properties" or -Droperties key=value, 
- *    read the Properties, if key is duplicated, override the value. 
- */
-    char *src, *tok;
-    for (int arg_num = 0; arg_num < p_env->vm_arguments.nOptions; arg_num++)
-    {
-        char *option = p_env->vm_arguments.options[arg_num].optionString;
-        if (strncmp(option, "-D", 2) == 0)
-        {
-            TRACE("setting property " << option + 2);
-            src = strdup(option + 2);
-            tok = strchr(src, '=');
-            if(tok)
-            {
-                *tok = '\0';
-                p_env->JavaProperties()->set(unquote(src), unquote(tok + 1));
-            }
-            else 
-            {
-                p_env->JavaProperties()->set(unquote(src), "");
-            }
-            STD_FREE(src);
-        } 
-        else if (strncmp(option, "-XD", 3) == 0)
-        {
-            TRACE("setting internal property " << option + 3);
-            src = strdup(option + 3);
-            tok = strchr(src, '=');
-            if(tok)
-            {
-                *tok = '\0';
-                p_env->VmProperties()->set(unquote(src), unquote(tok + 1));
-            }
-            else 
-            {
-                p_env->VmProperties()->set(unquote(src), "");
-            }
-
-            STD_FREE(src);
-        }
-    }
-    apr_pool_clear(prop_pool);
-}
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include <apr_file_io.h>
+#include <apr_file_info.h>
+#include <apr_env.h>
+#include <apr_strings.h>
+#include "port_dso.h"
+#include "port_filepath.h"
+#include "port_sysinfo.h"
+
+#define LOG_DOMAIN "init.properties"
+#include "cxxlog.h"
+#include "properties.h"
+#include "vm_properties.h"
+#include "init.h"
+
+inline char* unquote(char *str)
+{
+    const char *tokens = " \t\n\r\'\"";
+    size_t i = strspn(str, tokens);
+    str += i;
+    char *p = str + strlen(str) - 1;
+    while(strchr(tokens, *p) && p >= str)
+        *(p--) = '\0';
+    return str;
+}
+
+#define PROP_ENV_NAME  "VM_PROPERTIES"
+#define PROP_FILE_NAME "vm.properties"
+
+#define MAX_PROP_LINE 5120
+
+// local memory pool for temporary allocation
+static apr_pool_t *prop_pool;
+
+static void
+read_properties(char *fname, Properties & prop)
+{
+    apr_file_t *f;
+    char *src, *tok;
+    if (APR_SUCCESS != apr_file_open(&f, fname, APR_FOPEN_READ, 0, prop_pool))
+        return;
+    WARN("USAGE OF vm.properties FILE IS DEPRECATED. THIS FUNCTIONALITY WILL BE REMOVED SOON. ALL PROPERTIES SHOULD BE SET ON COMMAND LINE");
+    char buf[MAX_PROP_LINE];
+    while (!apr_file_eof(f) && !apr_file_gets(buf, MAX_PROP_LINE, f))
+    {
+        if (buf[0] != '#') {
+            src = strdup(buf);
+            tok = strchr(src, '=');
+            if(tok)
+            {
+                *tok = '\0';
+                prop.set(unquote(src), unquote(tok + 1));
+            }
+            STD_FREE(src);
+        }
+    }
+    apr_file_close(f);
+}
+
+#define API_DLL1 "harmonyvm"
+#define API_DLL2 "hythr"
+#define API_DLL3 "hysig"
+#define API_DLL4 "hyprt"
+#define API_DLL5 "hyzlib"
+#define API_DLL6 "hytext"
+#define API_DLL7 "hynio"
+#define API_DLL8 "vmi"
+#define API_DLLA "hyluni"
+#define API_DLLB "hyarchive"
+
+#define GC_DLL "gc_cc"
+
+/**
+ *  Compose a string of file names each of them beginning with path,
+ *  names separated by PORT_PATH_SEPARATOR.  If patch is NULL, no path
+ *  or separator will be prefixed
+ */
+static char *compose_full_files_path_names_list(const char *path,
+                                                const char **dll_names,
+                                                const int names_number, 
+                                                bool is_dll)
+{
+    char* full_name = "";
+    for (int iii = 0; iii < names_number; iii++)
+    {
+        const char *tmp = dll_names[iii];
+        if (is_dll) {
+            tmp = port_dso_name_decorate(tmp, prop_pool);
+        }
+        
+        /*
+         *  if the path is non-null, prefix, otherwise do nothing
+         *  to avoid the problem of "/libfoo.so" when we don't want
+         *  a path attached
+         */
+         
+        if (path != NULL) { 
+            tmp = port_filepath_merge(path, tmp, prop_pool);
+        }
+        
+        full_name = apr_pstrcat(prop_pool, full_name, tmp, 
+            (iii + 1 < names_number) ? PORT_PATH_SEPARATOR_STR : "", NULL);
+    }
+
+    return full_name;
+}
+
+static void init_java_properties(Properties & properties)
+{
+    //java part
+    //!!! java.compiler property must be defined by EM
+
+    char *os_name, *os_version, *path;
+    const char *tmp;
+    char *path_buf = NULL;
+
+    port_OS_name_version(&os_name, &os_version, prop_pool);
+    apr_filepath_get(&path, APR_FILEPATH_NATIVE, prop_pool);
+    if (APR_SUCCESS != apr_temp_dir_get(&tmp, prop_pool)) {
+        tmp = ".";
+    }
+    properties.set("java.version", "1.5.0");
+    properties.set("java.vendor", "Apache Software Foundation");
+    properties.set("java.vendor.url", "http://harmony.apache.org");
+    // java.home initialization, try to find absolute location of the executable and set
+    // java.home to the parent directory.
+    char *base_path_buf;
+    if (port_executable_name(&base_path_buf, prop_pool) != APR_SUCCESS) {
+        DIE("Failed to find executable location");
+    }
+    // directory for the executable
+    char *p = strrchr(base_path_buf, PORT_FILE_SEPARATOR);
+    if (NULL == p)
+        DIE("Failed to determine executable parent directory");
+    *p = '\0';
+    // home directory
+    char* home_path = apr_pstrdup(prop_pool, base_path_buf);
+    p = strrchr(home_path, PORT_FILE_SEPARATOR);
+    if (NULL == p)
+        DIE("Failed to determine java home directory");
+    *p = '\0';
+
+    properties.set("java.home", home_path);
+    properties.set("java.vm.specification.version", "1.0");
+    properties.set("java.vm.specification.vendor", "Sun Microsystems Inc.");
+    properties.set("java.vm.specification.name", "Java Virtual Machine Specification");
+    properties.set("java.vm.version", "11.2.0");
+    properties.set("java.vm.vendor", "Apache Software Foundation");
+    properties.set("java.vm.name", "DRLVM");
+    properties.set("java.specification.version", "1.5");
+    properties.set("java.specification.vendor", "Sun Microsystems Inc.");
+    properties.set("java.specification.name", "Java Platform API Specification");
+    properties.set("java.class.version", "49.0");
+    properties.set("java.class.path", ".");
+
+    // java.library.path initialization, the value is the location of VM executable,
+    // prepended to OS library search path
+    char *env;
+    char *lib_path = base_path_buf;
+    if (APR_SUCCESS == port_dso_search_path(&env, prop_pool))
+    {
+        lib_path = apr_pstrcat(prop_pool, base_path_buf, PORT_PATH_SEPARATOR_STR,
+                               base_path_buf, PORT_FILE_SEPARATOR_STR, "default",
+                               PORT_PATH_SEPARATOR_STR, env, NULL);
+    }
+    properties.set("java.library.path", lib_path);
+    //java.ext.dirs initialization.
+    char *ext_path = port_filepath_merge(home_path, "lib" PORT_FILE_SEPARATOR_STR "ext", prop_pool);
+    properties.set("java.ext.dirs", ext_path);
+    properties.set("os.name", os_name);
+    properties.set("os.arch", port_CPU_architecture());
+    properties.set("os.version", os_version);
+    properties.set("file.separator", PORT_FILE_SEPARATOR_STR);
+    properties.set("path.separator", PORT_PATH_SEPARATOR_STR);
+    properties.set("line.separator", APR_EOL_STR);
+    // user.name initialization, try to get the name from the system
+    char *user_buf;
+    apr_status_t status = port_user_name(&user_buf, prop_pool);
+    if (APR_SUCCESS != status) {
+        DIE("Failed to get user name from the system. Error code " << status);
+    }
+    properties.set("user.name", user_buf);
+    // user.home initialization, try to get home from the system.
+    char *user_home;
+    status = port_user_home(&user_home, prop_pool);
+    if (APR_SUCCESS != status) {
+        DIE("Failed to get user home from the system. Error code " << status);
+    }
+    properties.set("user.home", user_home);
+    // java.io.tmpdir initialization. 
+    const char *tmpdir;
+    status = apr_temp_dir_get(&tmpdir, prop_pool);
+    if (APR_SUCCESS != status) {
+        tmpdir = user_home;
+    }
+    properties.set("java.io.tmpdir", tmpdir);
+    properties.set("user.dir", path);
+
+    // FIXME??? other (not required by api specification) properties
+    
+    properties.set("java.vm.info", "no info");
+    properties.set("java.tmpdir", tmp);
+    properties.set("user.language", "en");
+    properties.set("user.region", "US");
+    properties.set("file.encoding", "8859_1");
+
+    // FIXME user.timezone initialization, required by java.util.TimeZone implementation
+    char *user_tz;
+    status = port_user_timezone(&user_tz, prop_pool);
+    if (APR_SUCCESS != status) {
+        INFO("Failed to get user timezone from the system. Error code " << status);
+        user_tz = "GMT";
+    }
+    
+    properties.set("user.timezone", user_tz);
+
+    // FIXME: This is a workaround code for third party APIs which depend on this property.
+    properties.set("java.util.prefs.PreferencesFactory",
+#ifdef PLATFORM_NT
+        "java.util.prefs.RegistryPreferencesFactoryImpl");
+#else
+        "java.util.prefs.FilePreferencesFactoryImpl");
+#endif
+
+    // Added for compatibility with the external java JDWP agent
+    properties.set("sun.boot.library.path", base_path_buf);
+
+    /*
+    *  it's possible someone forgot to set this property - set to default of .
+    */
+    if (!properties.is_set(O_A_H_VM_VMDIR)) {
+        TRACE2("init", "o.a.h.vm.vmdir not set - setting predefined value of as '.'");
+        properties.set(O_A_H_VM_VMDIR, ".");
+    }
+
+    /*
+    *  also, do the same for java.class.path
+    */
+    if (!properties.is_set("java.class.path")) {
+        TRACE2("init", "java.class.path not set - setting predefined value of as '.'");
+        properties.set("java.class.path", ".");
+    }
+}
+
+//vm part
+static void init_vm_properties(Properties & properties)
+{
+        properties.set("vm.assert_dialog", "true");
+        properties.set("vm.crash_handler", "false");
+        properties.set("vm.finalize", "true");
+        properties.set("vm.jit_may_inline_sync", "true");
+        properties.set("vm.use_verifier", "true");
+        properties.set("vm.jvmti.enabled", "false");
+        properties.set("vm.bootclasspath.appendclasspath", "false");
+
+        /*
+        *  vm.boot.library.path initialization, the value is the location of VM executable
+        * 
+        *  2006-09-06 gmj :  there's no reason to ever believe this is true given how the VM can be 
+        *  launched in a mariad of ways, so just set to empty string.
+        */
+        properties.set("vm.boot.library.path", "");
+
+        properties.set("vm.dlls", PORT_DSO_NAME(GC_DLL));
+
+        // vm.other_natives_dlls initialization, the value is location of VM executable.
+        const char *api_dll_files[] =
+        {
+            API_DLL1,
+                API_DLL2,
+                API_DLL3,
+                API_DLL4,
+                API_DLL5,
+                API_DLL6,
+                API_DLL7,
+                API_DLL8,
+                API_DLLA,
+                API_DLLB
+        };
+        int n_api_dll_files = sizeof(api_dll_files) / sizeof(char *);
+        /*
+        *  pass NULL for the pathname as we don't want 
+        *  any path pre-pended
+        */
+        char* path_buf = compose_full_files_path_names_list(NULL, api_dll_files, n_api_dll_files, true);
+        properties.set("vm.other_natives_dlls", path_buf);
+}
+
+void
+initialize_properties(Global_Env * p_env)
+{
+    if (!prop_pool) {
+        apr_pool_create(&prop_pool, 0);
+    }
+/*
+ * 0. Add predefined properties from property table
+ */
+     
+    init_java_properties(*p_env->JavaProperties());
+    init_vm_properties(*p_env->VmProperties());
+
+/* 
+ * 1. VM looks for an environment variable, say, 
+ *    VM_PROPERTIES=d:\xyz\eee\vm.Properties, read the Properties;
+ */
+    char *pf;
+    if (apr_env_get(&pf, PROP_ENV_NAME, prop_pool) == APR_SUCCESS){
+        read_properties(pf, *p_env->JavaProperties());
+    }
+/*
+ * 2. Looks for vm.Properties in the directory where vm executable resides 
+ *    (it's also a global file), read the Properties, if key is duplicated, 
+ *    override the value;
+ */
+    char *buf;
+    if (port_executable_name(&buf, prop_pool) == APR_SUCCESS)
+    {
+        char *p = strrchr(buf, PORT_FILE_SEPARATOR);
+        if (p)
+        {
+            *(p + 1) = '\0';
+            buf = apr_pstrcat(prop_pool, buf, PROP_FILE_NAME, NULL);
+            read_properties(buf, *p_env->JavaProperties());
+        }
+    }
+
+/*
+ * 3. Looks for it in current directory(it's an app-specific file), read the 
+ *    Properties, if key is duplicated, override the value;
+ */
+    apr_filepath_get(&buf, 0, prop_pool);
+    buf = port_filepath_merge(buf, PROP_FILE_NAME, prop_pool);
+    read_properties(buf, *p_env->JavaProperties());
+/*
+ * 4. Check whether there is a command line option, say, 
+ *    -Properties-file "d:\xyz\eee\vm.Properties" or -Droperties key=value, 
+ *    read the Properties, if key is duplicated, override the value. 
+ */
+    char *src, *tok;
+    for (int arg_num = 0; arg_num < p_env->vm_arguments.nOptions; arg_num++)
+    {
+        char *option = p_env->vm_arguments.options[arg_num].optionString;
+        if (strncmp(option, "-D", 2) == 0)
+        {
+            TRACE("setting property " << option + 2);
+            src = strdup(option + 2);
+            tok = strchr(src, '=');
+            if(tok)
+            {
+                *tok = '\0';
+                p_env->JavaProperties()->set(unquote(src), unquote(tok + 1));
+            }
+            else 
+            {
+                p_env->JavaProperties()->set(unquote(src), "");
+            }
+            STD_FREE(src);
+        } 
+        else if (strncmp(option, "-XD", 3) == 0)
+        {
+            TRACE("setting internal property " << option + 3);
+            src = strdup(option + 3);
+            tok = strchr(src, '=');
+            if(tok)
+            {
+                *tok = '\0';
+                p_env->VmProperties()->set(unquote(src), unquote(tok + 1));
+            }
+            else 
+            {
+                p_env->VmProperties()->set(unquote(src), "");
+            }
+
+            STD_FREE(src);
+        }
+    }
+    apr_pool_clear(prop_pool);
+}

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_shutdown.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_shutdown.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_shutdown.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_shutdown.cpp Fri Dec 15 00:33:21 2006
@@ -24,6 +24,7 @@
 #include "open/hythread.h"
 #include "open/jthread.h"
 #include "open/gc.h"
+#include "open/thread_externals.h"
 
 #include "jni.h"
 #include "jni_direct.h"
@@ -82,6 +83,85 @@
     return JNI_OK;
 }
 
+static void vm_shutdown_callback() {
+    hythread_t   self_native;
+    jthread      self_java;
+    VM_thread *  self_vm;
+    JNIEnv     * jni_env;
+    Global_Env * vm_env;
+        
+    self_native = hythread_self();
+    self_java = jthread_get_java_thread(self_native);
+    self_vm = get_vm_thread(self_native);
+
+    // Make sure the thread is still attached to the VM.
+    if (self_java == NULL || self_vm == NULL) {
+        return;
+    }
+        
+    jni_env = jthread_get_JNI_env(self_java);
+    vm_env = jni_get_vm_env(jni_env);
+
+    // We need to be in suspend disabled state to be able to throw an exception.
+    assert(!hythread_is_suspend_enabled());
+
+    //hythread_suspend_disable();
+
+    // Raise an exception. In shutdown stage it should cause entire stack unwinding.
+    jthread_throw_exception_object(vm_env->java_lang_ThreadDeath);
+
+    //hythread_suspend_enable();
+}
+
+/*
+void vm_shutdown_stop_java_threads(int exit_code)
+{
+    jthread current_java_thread;
+    JNIEnv_Internal * jni_env;
+    Global_Env * vm_env;
+    
+    // Current thread should be in suspend enabled state to prevent
+    // possible dead-locks.
+    assert(hythread_is_suspend_enabled());
+    
+    current_java_thread = jthread_self();
+    // Current thread should be attached to ThreadManager.
+    assert(current_java_thread);
+    jni_env = (JNIEnv_Internal *) jthread_get_JNI_env(current_java_thread);
+    vm_env = jni_env->vm->vm_env;
+    
+    // 2) Acquire VM state lock.
+    apr_thread_mutex_lock(vm_env->vm_state_mutex);
+    assert(vm_env->vm_state != Global_Env::VM_INITIALIZING);
+    
+    // 3) Check VM state.
+    if (vm_env->vm_state == Global_Env::VM_SHUTDOWNING) {
+        apr_thread_mutex_unlock(vm_env->vm_state_mutex);
+        return;
+    }
+
+    assert(vm_env->vm_state == Global_Env::VM_RUNNING);
+
+    // 4) Change VM state. Exception propagation mechanism should be changed
+    // upon setting up this flag.
+    vm_env->vm_state = Global_Env::VM_SHUTDOWNING;
+    
+    // 5) Block thread creation.
+    // TODO: investigate how to achive that with ThreadManager
+    
+    // 6) Execute shutdown callback for the current thread.
+    vm_shutdown_callback(NULL);
+    
+    // 7) Setup shutdown callback to all java threads but current.
+    // It causes an exception to be raised and all java monitors to
+    // be released upon reaching a safepoint.
+    hythread_group_set_suspend_disabled_callback(hythread_group_get_java(), vm_shutdown_callback, NULL);
+    
+    // 8) Unlock VM state mutex.
+    apr_thread_mutex_unlock(vm_env->vm_state_mutex);
+}
+*/
+
 /**
  * TODO:
  */
@@ -92,13 +172,15 @@
     jobject uncaught_exception;
     VM_thread * vm_thread;
     hythread_t native_thread;
-    hythread_t current_native_thread;
+    hythread_t self;
     hythread_iterator_t it;
+    hythread_t * running_threads;
+    int size;
 
     assert(hythread_is_suspend_enabled());
 
     jni_env = jthread_get_JNI_env(java_thread);
-    current_native_thread = hythread_self();
+    self = hythread_self();
 
     status = jthread_wait_for_all_nondaemon_threads();
     if (status != TM_ERROR_NONE) {
@@ -138,65 +220,177 @@
     // Call Agent_OnUnload() for agents and unload agents.
     java_vm->vm_env->TI->Shutdown(java_vm);
 
+    // Block thread creation.
+    // TODO: investigate how to achive that with ThreadManager
+
+    // Starting this moment any exception occured in java thread will cause
+    // entire java stack unwinding to the most recent native frame.
+    // JNI is not available as well.
+    assert(java_vm->vm_env->vm_state == Global_Env::VM_RUNNING);
+    java_vm->vm_env->vm_state = Global_Env::VM_SHUTDOWNING;
+
     // Stop all (except current) java and native threads
     // before destroying VM-wide data.
 
-    // TODO: current implementation doesn't stop java threads :-(
-    // So, don't perform cleanup if there are running java threads.
+    // Stop java threads
+    size = 0;
     it = hythread_iterator_create(NULL);
-    while (native_thread = hythread_iterator_next(&it)) {
+    running_threads = (hythread_t *)apr_palloc(
+        java_vm->vm_env->mem_pool, hythread_iterator_size(it) * sizeof(hythread_t));
+    while(native_thread = hythread_iterator_next(&it)) {
         vm_thread = get_vm_thread(native_thread);
-        if (vm_thread != NULL && native_thread != current_native_thread) {
-            java_vm->vm_env->VmProperties()->set("vm.noCleanupOnExit", "true");
-            hythread_iterator_release(&it);
-            return JNI_ERR;
+        if (vm_thread != NULL && native_thread != self) {
+            running_threads[size] = native_thread;
+            ++size;
+            hythread_set_safepoint_callback(native_thread, vm_shutdown_callback);
         }
     }
     hythread_iterator_release(&it);
 
+    // Interrupt running threads.
+    for (int i = 0; i < size; i++) {
+        hythread_interrupt(running_threads[i]);
+    }
+
+    // Wait for threads completion.
+    for (int i = 0; i < size; i++) {
+        hythread_join(running_threads[i]);
+    }
+
     // TODO: ups we don't stop native threads as well :-((
     // We are lucky! Currently, there are no such threads.
 
     return JNI_OK;
 }
 
-static inline void dump_all_java_stacks()
-{
-    hythread_t native_thread;
-    hythread_iterator_t  iterator;
-    VM_thread * vm_thread;
+static int vm_interrupt_process(void * data) {
+    hythread_t * threadBuf;
+    int i;
+
+    threadBuf = (hythread_t *)data;
+    i = 0;
+    // Join all threads.
+    while (threadBuf[i] != NULL) {
+        hythread_join(threadBuf[i]);
+        i++;
+    }
 
-    INFO("****** BEGIN OF JAVA STACKS *****\n");
+    // Return 130 to be compatible with RI.
+    exit(130);
+}
 
-    hythread_suspend_all(&iterator, NULL);
-    native_thread ;
-    while(native_thread = hythread_iterator_next(&iterator)) {
-        vm_thread = get_vm_thread(native_thread);
-        if (!vm_thread) continue;
-        interpreter.stack_dump(vm_thread);
+/**
+ * Initiates VM shutdown sequence.
+ */
+static int vm_interrupt_entry_point(void * data) {
+    JNIEnv * jni_env;
+    JavaVMAttachArgs args;
+    JavaVM * java_vm;
+    jint status;
+
+    java_vm = (JavaVM *)data;
+    args.version = JNI_VERSION_1_2;
+    args.group = NULL;
+    args.name = "InterruptionHandler";
+
+    status = AttachCurrentThread(java_vm, (void **)&jni_env, &args);
+    if (status == JNI_OK) {
+        exec_shutdown_sequence(jni_env);
+        DetachCurrentThread(java_vm);
     }
-    hythread_resume_all(NULL);
-    
-    INFO("****** END OF JAVA STACKS *****\n");
+    return status;
+}
+
+/**
+ * Dumps all java stacks.
+ */
+static int vm_dump_entry_point(void * data) {
+    JNIEnv * jni_env;
+    JavaVMAttachArgs args;
+    JavaVM * java_vm;
+    jint status;
+
+    java_vm = (JavaVM *)data;
+    args.version = JNI_VERSION_1_2;
+    args.group = NULL;
+    args.name = "DumpHandler";
+
+    status = AttachCurrentThread(java_vm, (void **)&jni_env, &args);
+    if (status == JNI_OK) {
+        // TODO: specify particular VM to notify.
+        jvmti_notify_data_dump_request();
+        st_print_all(stdout);
+        DetachCurrentThread(java_vm);
+    }
+    return status;
 }
 
-void quit_handler(int UNREF x) {
-    jvmti_notify_data_dump_request();
-    if (interpreter_enabled()) {
-        dump_all_java_stacks();
-    } else {
-        td_dump_all_threads(stderr);
+/**
+ * Current process recieved an interruption signal (Ctrl+C pressed).
+ * Shutdown all running VMs and terminate the process.
+ */
+void vm_interrupt_handler(int UNREF x) {
+    JavaVM ** vmBuf;
+    hythread_t * threadBuf;
+    int nVMs;
+    jint status;
+
+    status = JNI_GetCreatedJavaVMs(NULL, 0, &nVMs);
+    assert(nVMs <= 1);
+    if (status != JNI_OK) return;
+
+    vmBuf = (JavaVM **) STD_MALLOC(nVMs * sizeof(JavaVM *));
+    status = JNI_GetCreatedJavaVMs(vmBuf, nVMs, &nVMs);
+    assert(nVMs <= 1);
+    if (status != JNI_OK) goto cleanup;
+
+    status = hythread_attach(NULL);
+    if (status != TM_ERROR_NONE) goto cleanup;
+
+
+    threadBuf = (hythread_t *) STD_MALLOC((nVMs + 1) * sizeof(hythread_t));
+    threadBuf[nVMs] = NULL;
+
+    // Create a new thread for each VM to avoid scalability and deadlock problems.
+    for (int i = 0; i < nVMs; i++) {
+        threadBuf[i] = NULL;
+        hythread_create((threadBuf + i), 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_interrupt_entry_point, (void *)vmBuf[i]);
     }
+
+    // spawn a new thread which will terminate the proccess.
+    hythread_create(NULL, 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_interrupt_process, (void *)threadBuf);
+
+cleanup:
+    STD_FREE(vmBuf);
 }
 
-void interrupt_handler(int UNREF x)
-{
-    static bool begin_shutdown_hooks = false;
+/**
+ * Current process recieved an ??? signal (Ctrl+Break pressed).
+ * Prints java stack traces for each VM running in the current procces.
+ */
+void vm_dump_handler(int UNREF x) {
+    JavaVM ** vmBuf;
+    int nVMs;
+    jint status;
+
+    status = JNI_GetCreatedJavaVMs(NULL, 0, &nVMs);
+    assert(nVMs <= 1);
+    if (status != JNI_OK) return;
+
+    vmBuf = (JavaVM **) STD_MALLOC(nVMs * sizeof(JavaVM *));
+    status = JNI_GetCreatedJavaVMs(vmBuf, nVMs, &nVMs);
+    assert(nVMs <= 1);
+
+    if (status != JNI_OK) goto cleanup;
+
+    status = hythread_attach(NULL);
+    if (status != TM_ERROR_NONE) goto cleanup;
+
+    // Create a new thread for each VM to avoid scalability and deadlock problems.
+    for (int i = 0; i < nVMs; i++) {
+        hythread_create(NULL, 0, HYTHREAD_PRIORITY_NORMAL, 0, vm_dump_entry_point, (void *)vmBuf[i]);
+    }
 
-    if(!begin_shutdown_hooks){
-        begin_shutdown_hooks = true;
-        //FIXME: integration should do int another way.
-        //vm_set_event(non_daemon_threads_dead_handle);
-    }else
-        exit(1);
+cleanup:
+    STD_FREE(vmBuf);
 }

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni.cpp Fri Dec 15 00:33:21 2006
@@ -50,6 +50,7 @@
 #include "jni_utils.h"
 #include "jit_runtime_support.h"
 #include "jvmti_direct.h"
+#include "stack_trace.h"
 
 #ifdef _IPF_
 #include "stub_code_utils.h"
@@ -418,16 +419,13 @@
     apr_thread_mutex_lock(GLOBAL_LOCK);
 
     *nVMs = 0;
-    if (!APR_RING_EMPTY(&GLOBAL_VMS, JavaVM_Internal, link)) {
-            JavaVM_Internal * current_vm = APR_RING_FIRST(&GLOBAL_VMS);
-            while (current_vm) {
-                if (*nVMs < bufLen) {
-                    vmBuf[*nVMs] = (JavaVM *)current_vm;
-                }
-                ++(*nVMs);
-                current_vm = APR_RING_NEXT(current_vm, link);
-            }
-
+    JavaVM_Internal * current_vm = APR_RING_FIRST(&GLOBAL_VMS);
+    while (current_vm != APR_RING_SENTINEL(&GLOBAL_VMS, JavaVM_Internal, link)) {
+        if (*nVMs < bufLen) {
+            vmBuf[*nVMs] = (JavaVM *)current_vm;
+        }
+        ++(*nVMs);
+        current_vm = APR_RING_NEXT(current_vm, link);
     }
     apr_thread_mutex_unlock(GLOBAL_LOCK);
     return JNI_OK;
@@ -522,6 +520,9 @@
         goto done;
     }
 
+    // The VM is fully initialized now.
+    vm_env->vm_state = Global_Env::VM_RUNNING;
+
     // Send VM init event.
     jvmti_send_vm_init_event(vm_env);
 
@@ -644,56 +645,58 @@
         assert(hythread_is_suspend_enabled());
         return struct_Class_to_jclass(clss);
     }
-    else
-    {
-        assert(exn_raised());
-        return NULL;
-    }
+
+    assert(exn_raised());
+    return NULL;
 } //DefineClass
 
-jclass JNICALL FindClass(JNIEnv* env_ext,
-                         const char* name)
+ jclass JNICALL FindClass(JNIEnv * jni_env,
+                          const char * name)
 {
-    if (exn_raised()) return NULL;
     TRACE2("jni", "FindClass called, name = " << name);
 
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (exn_raised() || vm_env->IsVmShutdowning()) return NULL;
     char *ch = strchr(name, '.');
     if (NULL != ch)
     {
-        ThrowNew_Quick(env_ext,
+        ThrowNew_Quick(jni_env,
             VM_Global_State::loader_env->JavaLangNoClassDefFoundError_String->bytes,
             name);
         return NULL;
     }
 
-    String* cls_name = VM_Global_State::loader_env->string_pool.lookup(name);
-    return FindClass(env_ext, cls_name);
+    String* cls_name = vm_env->string_pool.lookup(name);
+    return FindClass(jni_env, cls_name);
     
 } //FindClass
 
-jclass JNICALL GetSuperclass(JNIEnv * UNREF env, jclass clazz)
+jclass JNICALL GetSuperclass(JNIEnv * jni_env, jclass clazz)
 {
     TRACE2("jni", "GetSuperclass called");
     assert(hythread_is_suspend_enabled());
+    
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning()) return NULL;
     Class* clss = jclass_to_struct_Class(clazz);
     if(clss) {
         if(clss->is_interface()) {
-            return 0;
+            return NULL;
         } else {
             Class* super_class = clss->get_super_class();
             if(super_class) {
                 assert(hythread_is_suspend_enabled());
                 return struct_Class_to_jclass(super_class);
             } else {
-                return 0;
+                return NULL;
             }
         }
     } else {
-        return 0;
+        return NULL;
     }
 } //GetSuperclass
 
-jboolean JNICALL IsAssignableFrom(JNIEnv * UNREF env,
+jboolean JNICALL IsAssignableFrom(JNIEnv * UNREF jni_env,
                                   jclass clazz1,
                                   jclass clazz2)
 {
@@ -710,10 +713,11 @@
     }
 } //IsAssignableFrom
 
-jint JNICALL Throw(JNIEnv * UNREF env, jthrowable obj)
+jint JNICALL Throw(JNIEnv * UNREF jni_env, jthrowable obj)
 {
     TRACE2("jni", "Throw called");
     assert(hythread_is_suspend_enabled());
+
     if(obj) {
         exn_raise_object(obj);
         return 0;
@@ -722,7 +726,7 @@
     }
 } // Throw
 
-jint JNICALL ThrowNew(JNIEnv *env, jclass clazz, const char *message)
+jint JNICALL ThrowNew(JNIEnv * jni_env, jclass clazz, const char *message)
 {
     TRACE2("jni", "ThrowNew called, message = " << (message ? message : "<no message>"));
     assert(hythread_is_suspend_enabled());
@@ -730,18 +734,23 @@
 
     jstring str = (jstring)0;
     if(message) {
-        str = NewStringUTF(env, message);
+        str = NewStringUTF(jni_env, message);
         if(!str) {
             return -1;
         }
     }
 
-    jmethodID init_id = GetMethodID(env, clazz, "<init>", "(Ljava/lang/String;)V");
+    jmethodID init_id = GetMethodID(jni_env, clazz, "<init>", "(Ljava/lang/String;)V");
+    if (!init_id) {
+        jni_env->DeleteLocalRef(str);
+        return -1;
+    }
+
     jvalue args[1];
     args[0].l = str;
-    jobject obj = NewObjectA(env, clazz, init_id, args);
-    env->DeleteLocalRef(str);
-    if(obj && !ExceptionOccurred(env)) {
+    jobject obj = NewObjectA(jni_env, clazz, init_id, args);
+    jni_env->DeleteLocalRef(str);
+    if(obj && !ExceptionOccurred(jni_env)) {
         exn_raise_object(obj);
         return 0;
     } else {
@@ -749,58 +758,79 @@
     }
 } //ThrowNew
 
-jint JNICALL ThrowNew_Quick(JNIEnv *env, const char *classname, const char *message)
+jint JNICALL ThrowNew_Quick(JNIEnv * jni_env, const char *classname, const char *message)
 {
-    jclass exclazz = FindClass(env, classname);
+    jclass exclazz = FindClass(jni_env, classname);
     if(!exclazz) {
         return -1;
     }
 
-    jint result = ThrowNew(env, exclazz, message);
-    env->DeleteLocalRef(exclazz);
+    jint result = ThrowNew(jni_env, exclazz, message);
+    jni_env->DeleteLocalRef(exclazz);
     return result;
 } // ThrowNew_Quick
 
 //FIXME LAZY EXCEPTION (2006.05.15)
 // chacks usage of this function and replace by lazy
-jthrowable JNICALL ExceptionOccurred(JNIEnv * UNREF env)
+jthrowable JNICALL ExceptionOccurred(JNIEnv * jni_env)
 {
     TRACE2("jni", "ExceptionOccurred called");
     assert(hythread_is_suspend_enabled());
-#ifdef _DEBUG
-    tmn_suspend_disable();
-    if (!exn_raised())
-    {
-        TRACE2("jni", "Exception occured, no exception");
-    }
-    else
-    {
-        TRACE2("jni", "Exception occured, class = " << exn_get_name());
+    
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning()) {
+        // Wait until shutdown exception is raised by callback.
+        while (!exn_raised()) {
+            // Switch enable/disable status to give a chance for
+            // callback execution.
+            hythread_suspend_disable();
+            hythread_suspend_enable();
+            hythread_yield();
+        }
     }
-    tmn_suspend_enable();
-#endif
+    jthrowable result = exn_get();
 
-    if(exn_raised()) {
-        return exn_get();
+#ifdef _DEBUG
+    hythread_suspend_disable();
+    if (result) {
+        TRACE2("jni", "Exception occured, class = " << exn_get_name());
     } else {
-        return 0;
+        TRACE2("jni", "Exception occured, no exception");        
+    }
+    if (vm_env->IsVmShutdowning() && !result) {
+        TRACE2("vm.core.shutdown", "ExceptionOccured: shutdown exception hasn't been raised");
     }
+    hythread_suspend_enable();
+#endif
+    
+    return  result;
 } //ExceptionOccurred
 
-void JNICALL ExceptionDescribe(JNIEnv * UNREF env)
+void JNICALL ExceptionDescribe(JNIEnv * jni_env)
 {
     TRACE2("jni", "ExceptionDescribe called");
     assert(hythread_is_suspend_enabled());
+    // we should not report vm shutdown exception to the user
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning()) return;
     if (exn_raised()) {
         exn_print_stack_trace(stderr, exn_get());
     }
 } //ExceptionDescribe
 
-void JNICALL ExceptionClear(JNIEnv * UNREF env)
+void JNICALL ExceptionClear(JNIEnv * jni_env)
 {
     TRACE2("jni", "ExceptionClear called");
     assert(hythread_is_suspend_enabled());
+    
     tmn_suspend_disable();
+    // It is important to check the VM shutdown state in suspend disabled mode
+    // to garantee that we will not clear raised shutdown exception
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning()) {
+        tmn_suspend_enable();
+        return;
+    }
 #ifdef _DEBUG
     if (!exn_raised())
     {
@@ -815,17 +845,25 @@
     tmn_suspend_enable();
 } //ExceptionClear
 
-void JNICALL FatalError(JNIEnv * UNREF env, const char *msg)
+void JNICALL FatalError(JNIEnv * UNREF jni_env, const char *msg)
 {
     TRACE2("jni", "FatalError called");
     assert(hythread_is_suspend_enabled());
-    DIE("\nFATAL error occurred in a JNI native method:\n\t" << msg);
+    
+    fprintf(stdout, "\nFATAL ERROR occurred in native method: %s\n", msg);
+    st_print(stdout, hythread_self());
+
+    // Return 1 to be compatible with RI.
+    exit(1);
 } //FatalError
 
-jobject JNICALL NewGlobalRef(JNIEnv * UNREF env, jobject obj)
+jobject JNICALL NewGlobalRef(JNIEnv * jni_env, jobject obj)
 {
     TRACE2("jni", "NewGlobalRef called");
     assert(hythread_is_suspend_enabled());
+    
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning() || !obj) return NULL;
     if(!obj) {
         return 0;
     }
@@ -844,33 +882,35 @@
     return (jobject)new_handle;
 } //NewGlobalRef
 
-void JNICALL DeleteGlobalRef(JNIEnv * UNREF env, jobject globalRef)
+void JNICALL DeleteGlobalRef(JNIEnv * UNREF jni_env, jobject globalRef)
 {
     TRACE2("jni", "DeleteGlobalRef called");
     assert(hythread_is_suspend_enabled());
+    
+    if (globalRef == NULL) return;
+
 #ifdef _DEBUG
     tmn_suspend_disable();
     ObjectHandle h = (ObjectHandle)globalRef;
     TRACE2("jni", "DeleteGlobalRef class = " << h->object->vt()->clss);
     tmn_suspend_enable();
 #endif
-    if (globalRef != NULL) {
-        oh_deallocate_global_handle((ObjectHandle)globalRef);
-    }
+
+    oh_deallocate_global_handle((ObjectHandle)globalRef);
 } //DeleteGlobalRef
 
-jobject JNICALL NewLocalRef(JNIEnv *env, jobject ref)
+jobject JNICALL NewLocalRef(JNIEnv * jni_env, jobject ref)
 {
     TRACE2("jni", "NewLocalRef called");
     assert(hythread_is_suspend_enabled());
-    if (NULL == ref)
-        return NULL;
+    
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning() || ref == NULL) return NULL;
 
     jobject new_ref = oh_copy_to_local_handle(ref);
 
     if (NULL == new_ref) {
-        exn_raise_object(
-            (jthrowable)(((JNIEnv_Internal*)env)->vm->vm_env->java_lang_OutOfMemoryError));
+        exn_raise_object(vm_env->java_lang_OutOfMemoryError);
         return NULL;
     }
 
@@ -879,22 +919,24 @@
     return new_ref;
 } //NewLocalRef
 
-void JNICALL DeleteLocalRef(JNIEnv * UNREF env, jobject localRef)
+void JNICALL DeleteLocalRef(JNIEnv * UNREF jni_env, jobject localRef)
 {
     TRACE2("jni", "DeleteLocalRef called");
     assert(hythread_is_suspend_enabled());
+
+    if (localRef == NULL) return;
+
 #ifdef _DEBUG
     tmn_suspend_disable();
     ObjectHandle h = (ObjectHandle)localRef;
     TRACE2("jni", "DeleteLocalRef class = " << h->object->vt()->clss);
     tmn_suspend_enable();
 #endif
-    if (localRef != NULL) {
-        oh_discard_local_handle((ObjectHandle)localRef);
-    }
+
+    oh_discard_local_handle((ObjectHandle)localRef);
 } //DeleteLocalRef
 
-jboolean JNICALL IsSameObject(JNIEnv * UNREF env,
+jboolean JNICALL IsSameObject(JNIEnv * UNREF jni_env,
                               jobject ref1,
                               jobject ref2)
 {
@@ -926,7 +968,7 @@
     return result;
 } //IsSameObject
 
-VMEXPORT jint JNICALL PushLocalFrame(JNIEnv * UNREF env, jint UNREF cap)
+VMEXPORT jint JNICALL PushLocalFrame(JNIEnv * UNREF jni_env, jint UNREF cap)
 {
     TRACE2("jni", "PushLocalFrame called");
     assert(hythread_is_suspend_enabled());
@@ -934,7 +976,7 @@
     return 0;
 }
 
-VMEXPORT jobject JNICALL PopLocalFrame(JNIEnv * UNREF env, jobject res)
+VMEXPORT jobject JNICALL PopLocalFrame(JNIEnv * UNREF jni_env, jobject res)
 {
     TRACE2("jni", "PopLocalFrame called");
     assert(hythread_is_suspend_enabled());
@@ -943,7 +985,7 @@
 }
 
 
-jint JNICALL EnsureLocalCapacity(JNIEnv* UNREF env, jint UNREF cap)
+jint JNICALL EnsureLocalCapacity(JNIEnv * UNREF jni_env, jint UNREF cap)
 {
     TRACE2("jni", "EnsureLocalCapacity called");
     assert(hythread_is_suspend_enabled());
@@ -951,18 +993,21 @@
 }
 
 
-jobject JNICALL AllocObject(JNIEnv *env,
+jobject JNICALL AllocObject(JNIEnv * jni_env,
                             jclass clazz)
 {
     TRACE2("jni", "AllocObject called");
     assert(hythread_is_suspend_enabled());
-    assert(clazz);
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning() || clazz == NULL) return NULL;
+
     Class* clss = jclass_to_struct_Class(clazz);
 
     if(clss->is_interface() || clss->is_abstract()) {
         // Can't instantiate interfaces and abtract classes.
-        ThrowNew_Quick(env, "java/lang/InstantiationException", clss->get_name()->bytes);
-        return 0;
+        ThrowNew_Quick(jni_env, "java/lang/InstantiationException", clss->get_name()->bytes);
+        return NULL;
     }
 
     tmn_suspend_disable();       //---------------------------------v
@@ -970,8 +1015,7 @@
     ManagedObject *new_obj = (ManagedObject *)class_alloc_new_object(clss);
     if (new_obj == NULL) {
         tmn_suspend_enable();
-        return 0;
-
+        return NULL;
     }
     new_handle->object = (ManagedObject *)new_obj;
     tmn_suspend_enable();        //---------------------------------^
@@ -981,7 +1025,7 @@
 
 
 
-jobject JNICALL NewObject(JNIEnv *env,
+jobject JNICALL NewObject(JNIEnv * jni_env,
                           jclass clazz,
                           jmethodID methodID,
                           ...)
@@ -990,10 +1034,10 @@
     assert(hythread_is_suspend_enabled());
     va_list args;
     va_start(args, methodID);
-    return NewObjectV(env, clazz, methodID, args);
+    return NewObjectV(jni_env, clazz, methodID, args);
 } //NewObject
 
-jobject JNICALL NewObjectV(JNIEnv *env,
+jobject JNICALL NewObjectV(JNIEnv * jni_env,
                            jclass clazz,
                            jmethodID methodID,
                            va_list args)
@@ -1001,12 +1045,12 @@
     TRACE2("jni", "NewObjectV called");
     assert(hythread_is_suspend_enabled());
     jvalue *jvalue_args = get_jvalue_arg_array((Method *)methodID, args);
-    jobject result = NewObjectA(env, clazz, methodID, jvalue_args);
+    jobject result = NewObjectA(jni_env, clazz, methodID, jvalue_args);
     STD_FREE(jvalue_args);
     return result;
 } //NewObjectV
 
-jobject JNICALL NewObjectA(JNIEnv *env,
+jobject JNICALL NewObjectA(JNIEnv * jni_env,
                            jclass clazz,
                            jmethodID methodID,
                            jvalue *args)
@@ -1014,27 +1058,25 @@
     TRACE2("jni", "NewObjectA called");
     assert(hythread_is_suspend_enabled());
     // Allocate the object.
-    jobject new_handle = AllocObject(env, clazz);
+    jobject new_handle = AllocObject(jni_env, clazz);
 
     if(!new_handle) {
         // Couldn't allocate the object.
-        return 0;
+        return NULL;
     }
 
-    CallNonvirtualVoidMethodA(env, new_handle, clazz, methodID, args);
-    if (ExceptionCheck(env))
-        return NULL;
-    else
-        return new_handle;
+    CallNonvirtualVoidMethodA(jni_env, new_handle, clazz, methodID, args);
+    return ExceptionCheck(jni_env) ? NULL : new_handle;
 } //NewObjectA
 
-jclass JNICALL GetObjectClass(JNIEnv * UNREF env,
+jclass JNICALL GetObjectClass(JNIEnv * jni_env,
                               jobject obj)
 {
     TRACE2("jni", "GetObjectClass called");
     assert(hythread_is_suspend_enabled());
     // The spec guarantees that the reference is not null.
     assert(obj);
+    
     ObjectHandle h = (ObjectHandle)obj;
 
     tmn_suspend_disable();       //---------------------------------v
@@ -1051,7 +1093,7 @@
     return (jobject)new_handle;
 } //GetObjectClass
 
-jboolean JNICALL IsInstanceOf(JNIEnv *env,
+jboolean JNICALL IsInstanceOf(JNIEnv * jni_env,
                               jobject obj,
                               jclass clazz)
 {
@@ -1061,18 +1103,14 @@
         return JNI_TRUE;
     }
 
-    jclass obj_class = GetObjectClass(env, obj);
+    jclass obj_class = GetObjectClass(jni_env, obj);
 
     Class* clss = jclass_to_struct_Class(clazz);
     Class* obj_clss = jclass_to_struct_Class(obj_class);
 
     Boolean isInstance = obj_clss->is_instanceof(clss);
 
-    if(isInstance) {
-        return JNI_TRUE;
-    } else {
-        return JNI_FALSE;
-    }
+    return isInstance ? JNI_TRUE : JNI_FALSE;
 } //IsInstanceOf
 
 static bool
@@ -1095,16 +1133,20 @@
 #endif // !NDEBUG
 }
 
-jstring JNICALL NewString(JNIEnv * UNREF env,
+jstring JNICALL NewString(JNIEnv * jni_env,
                           const jchar *unicodeChars,
                           jsize length)
 {
     TRACE2("jni", "NewString called, length = " << length);
     assert(hythread_is_suspend_enabled());
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning()) return NULL;
+
     return (jstring)string_create_from_unicode_h(unicodeChars, length);
 } //NewString
 
-jsize JNICALL GetStringLength(JNIEnv * UNREF env,
+jsize JNICALL GetStringLength(JNIEnv * UNREF jni_env,
                               jstring string)
 {
     TRACE2("jni", "GetStringLength called");
@@ -1115,14 +1157,16 @@
     return string_get_length_h((ObjectHandle)string);
 } //GetStringLength
 
-const jchar *JNICALL GetStringChars(JNIEnv * UNREF env,
+const jchar *JNICALL GetStringChars(JNIEnv * jni_env,
                                     jstring string,
                                     jboolean *isCopy)
 {
     TRACE2("jni", "GetStringChars called");
     assert(hythread_is_suspend_enabled());
-    if(!string)
-        return 0;
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (!string || vm_env->IsVmShutdowning()) return NULL;
+
     assert(check_is_jstring_class(string));
 
     tmn_suspend_disable();
@@ -1133,7 +1177,7 @@
     return chars;
 } //GetStringChars
 
-void JNICALL ReleaseStringChars(JNIEnv * UNREF env,
+void JNICALL ReleaseStringChars(JNIEnv * UNREF jni_env,
                                 jstring string,
                                 const jchar *chars)
 {
@@ -1145,15 +1189,19 @@
     STD_FREE((void*)chars);
 } //ReleaseStringChars
 
-jstring JNICALL NewStringUTF(JNIEnv * UNREF env,
+jstring JNICALL NewStringUTF(JNIEnv * jni_env,
                              const char *bytes)
 {
     TRACE2("jni", "NewStringUTF called, bytes = " << bytes);
     assert(hythread_is_suspend_enabled());
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning()) return NULL;
+
     return (jstring)string_create_from_utf8_h(bytes, (unsigned)strlen(bytes));
 } //NewStringUTF
 
-jsize JNICALL GetStringUTFLength(JNIEnv * UNREF env,
+jsize JNICALL GetStringUTFLength(JNIEnv * UNREF jni_env,
                                  jstring string)
 {
     TRACE2("jni", "GetStringUTFLength called");
@@ -1164,21 +1212,22 @@
     return string_get_utf8_length_h((ObjectHandle)string);
 } //GetStringUTFLength
 
-const char *JNICALL GetStringUTFChars(JNIEnv * UNREF env,
+const char *JNICALL GetStringUTFChars(JNIEnv * jni_env,
                                       jstring string,
                                       jboolean *isCopy)
 {
     TRACE2("jni", "GetStringUTFChars called");
-    if(!string)
-        return 0;
-    assert(check_is_jstring_class(string));
     assert(hythread_is_suspend_enabled());
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning() || !string) return NULL;
+    assert(check_is_jstring_class(string));
     const char* res = string_get_utf8_chars_h((ObjectHandle)string);
     if (isCopy) *isCopy = JNI_TRUE;
     return res;
 } //GetStringUTFChars
 
-void JNICALL ReleaseStringUTFChars(JNIEnv * UNREF env,
+void JNICALL ReleaseStringUTFChars(JNIEnv * UNREF jni_env,
                                    jstring string,
                                    const char *utf)
 {
@@ -1190,18 +1239,22 @@
     STD_FREE((void*)utf);
 } //ReleaseStringUTFChars
 
-jint JNICALL RegisterNatives(JNIEnv * UNREF env,
+jint JNICALL RegisterNatives(JNIEnv * jni_env,
                              jclass clazz,
                              const JNINativeMethod *methods,
                              jint nMethods)
 {
     TRACE2("jni", "RegisterNatives called");
     assert(hythread_is_suspend_enabled());
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning()) return -1;
+
     Class_Handle clss = jclass_to_struct_Class(clazz);
     return class_register_methods(clss, methods, nMethods) ? -1 : 0;
 } //RegisterNatives
 
-jint JNICALL UnregisterNatives(JNIEnv * UNREF env, jclass clazz)
+jint JNICALL UnregisterNatives(JNIEnv * jni_env, jclass clazz)
 {
     TRACE2("jni", "UnregisterNatives called");
     assert(hythread_is_suspend_enabled());
@@ -1209,17 +1262,21 @@
     return class_unregister_methods(clss) ? -1 : 0;
 } //UnregisterNatives
 
-jint JNICALL MonitorEnter(JNIEnv * UNREF env, jobject obj)
+jint JNICALL MonitorEnter(JNIEnv * jni_env, jobject obj)
 {
     TRACE2("jni", "MonitorEnter called");
     assert(hythread_is_suspend_enabled());
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning()) return -1;
+
     jthread_monitor_enter(obj);
     return exn_raised() ? -1 : 0;
 } //MonitorEnter
 
 
 
-jint JNICALL MonitorExit(JNIEnv * UNREF env, jobject obj)
+jint JNICALL MonitorExit(JNIEnv * UNREF jni_env, jobject obj)
 {
     ASSERT_RAISE_AREA;
 
@@ -1231,20 +1288,23 @@
 
 
 
-jint JNICALL GetJavaVM(JNIEnv *env_ext, JavaVM **vm)
+jint JNICALL GetJavaVM(JNIEnv * jni_env, JavaVM **vm)
 {
     TRACE2("jni", "GetJavaVM called");
     assert(hythread_is_suspend_enabled());
-    JNIEnv_Internal *env = (JNIEnv_Internal *)env_ext;
-    *vm = env->vm;
+    *vm = ((JNIEnv_Internal *) jni_env)->vm;
     return JNI_OK;
 } //GetJavaVM
 
 
-void JNICALL GetStringRegion(JNIEnv * UNREF env, jstring s, jsize off, jsize len, jchar *b)
+void JNICALL GetStringRegion(JNIEnv * jni_env, jstring s, jsize off, jsize len, jchar *b)
 {
     TRACE2("jni", "GetStringRegion called");
     assert(hythread_is_suspend_enabled());
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    if (vm_env->IsVmShutdowning()) return;
+
     assert(s);
 
     string_get_unicode_region_h((ObjectHandle)s, off, len, b);
@@ -1257,7 +1317,7 @@
     string_get_utf8_region_h((ObjectHandle)s, off, len, b);
 }
 
-VMEXPORT void* JNICALL GetPrimitiveArrayCritical(JNIEnv* jenv, jarray array, jboolean* isCopy)
+VMEXPORT void* JNICALL GetPrimitiveArrayCritical(JNIEnv * jni_env, jarray array, jboolean* isCopy)
 {
     TRACE2("jni", "GetPrimitiveArrayCritical called");
     assert(hythread_is_suspend_enabled());
@@ -1269,35 +1329,36 @@
     TRACE2("jni.pin", "pinning array " << array->object);
     gc_pin_object((Managed_Object_Handle*)array);
     switch (array_clss->get_name()->bytes[1]) {
-    case 'B':  return GetByteArrayElements(jenv, array, isCopy);
-    case 'C':  return GetCharArrayElements(jenv, array, isCopy);
-    case 'D':  return GetDoubleArrayElements(jenv, array, isCopy);
-    case 'F':  return GetFloatArrayElements(jenv, array, isCopy);
-    case 'I':  return GetIntArrayElements(jenv, array, isCopy);
-    case 'J':  return GetLongArrayElements(jenv, array, isCopy);
-    case 'S':  return GetShortArrayElements(jenv, array, isCopy);
-    case 'Z':  return GetBooleanArrayElements(jenv, array, isCopy);
+    case 'B':  return GetByteArrayElements(jni_env, array, isCopy);
+    case 'C':  return GetCharArrayElements(jni_env, array, isCopy);
+    case 'D':  return GetDoubleArrayElements(jni_env, array, isCopy);
+    case 'F':  return GetFloatArrayElements(jni_env, array, isCopy);
+    case 'I':  return GetIntArrayElements(jni_env, array, isCopy);
+    case 'J':  return GetLongArrayElements(jni_env, array, isCopy);
+    case 'S':  return GetShortArrayElements(jni_env, array, isCopy);
+    case 'Z':  return GetBooleanArrayElements(jni_env, array, isCopy);
     default:   ABORT("Wrong array type descriptor"); return NULL;
     }
 }
 
-VMEXPORT void JNICALL ReleasePrimitiveArrayCritical(JNIEnv* jenv, jarray array, void* carray, jint mode)
+VMEXPORT void JNICALL ReleasePrimitiveArrayCritical(JNIEnv * jni_env, jarray array, void* carray, jint mode)
 {
     TRACE2("jni", "ReleasePrimitiveArrayCritical called");
     assert(hythread_is_suspend_enabled());
+
     tmn_suspend_disable();
     Class* array_clss = ((ObjectHandle)array)->object->vt()->clss;
     tmn_suspend_enable();
     assert(array_clss->get_name()->bytes[0]=='[');
     switch (array_clss->get_name()->bytes[1]) {
-    case 'B':  ReleaseByteArrayElements(jenv, array, (jbyte*)carray, mode); break;
-    case 'C':  ReleaseCharArrayElements(jenv, array, (jchar*)carray, mode); break;
-    case 'D':  ReleaseDoubleArrayElements(jenv, array, (jdouble*)carray, mode); break;
-    case 'F':  ReleaseFloatArrayElements(jenv, array, (jfloat*)carray, mode); break;
-    case 'I':  ReleaseIntArrayElements(jenv, array, (jint*)carray, mode); break;
-    case 'J':  ReleaseLongArrayElements(jenv, array, (jlong*)carray, mode); break;
-    case 'S':  ReleaseShortArrayElements(jenv, array, (jshort*)carray, mode); break;
-    case 'Z':  ReleaseBooleanArrayElements(jenv, array, (jboolean*)carray, mode); break;
+    case 'B':  ReleaseByteArrayElements(jni_env, array, (jbyte*)carray, mode); break;
+    case 'C':  ReleaseCharArrayElements(jni_env, array, (jchar*)carray, mode); break;
+    case 'D':  ReleaseDoubleArrayElements(jni_env, array, (jdouble*)carray, mode); break;
+    case 'F':  ReleaseFloatArrayElements(jni_env, array, (jfloat*)carray, mode); break;
+    case 'I':  ReleaseIntArrayElements(jni_env, array, (jint*)carray, mode); break;
+    case 'J':  ReleaseLongArrayElements(jni_env, array, (jlong*)carray, mode); break;
+    case 'S':  ReleaseShortArrayElements(jni_env, array, (jshort*)carray, mode); break;
+    case 'Z':  ReleaseBooleanArrayElements(jni_env, array, (jboolean*)carray, mode); break;
     default:   ABORT("Wrong array type descriptor"); break;
     }
     if (mode != JNI_COMMIT) {
@@ -1306,100 +1367,109 @@
     }
 }
 
-const jchar* JNICALL GetStringCritical(JNIEnv *env, jstring s, jboolean* isCopy)
+const jchar* JNICALL GetStringCritical(JNIEnv *jni_env, jstring s, jboolean* isCopy)
 {
     TRACE2("jni", "GetStringCritical called");
     assert(hythread_is_suspend_enabled());
-    return GetStringChars(env, s, isCopy);
+    return GetStringChars(jni_env, s, isCopy);
 }
 
-void JNICALL ReleaseStringCritical(JNIEnv *env, jstring s, const jchar* cstr)
+void JNICALL ReleaseStringCritical(JNIEnv * jni_env, jstring s, const jchar* cstr)
 {
     TRACE2("jni", "ReleaseStringCritical called");
     assert(hythread_is_suspend_enabled());
-    ReleaseStringChars(env, s, cstr);
+    ReleaseStringChars(jni_env, s, cstr);
 }
 
-VMEXPORT jweak JNICALL NewWeakGlobalRef(JNIEnv *env, jobject obj)
+VMEXPORT jweak JNICALL NewWeakGlobalRef(JNIEnv * jni_env, jobject obj)
 {
     TRACE2("jni", "NewWeakGlobalRef called");
     assert(hythread_is_suspend_enabled());
-    return NewGlobalRef(env, obj);
+    return NewGlobalRef(jni_env, obj);
 }
 
-VMEXPORT void JNICALL DeleteWeakGlobalRef(JNIEnv *env, jweak obj)
+VMEXPORT void JNICALL DeleteWeakGlobalRef(JNIEnv * jni_env, jweak obj)
 {
     TRACE2("jni", "DeleteWeakGlobalRef called");
     assert(hythread_is_suspend_enabled());
-    DeleteGlobalRef(env, obj);
+    DeleteGlobalRef(jni_env, obj);
 }
 
-jboolean JNICALL ExceptionCheck(JNIEnv * UNREF env)
+jboolean JNICALL ExceptionCheck(JNIEnv * jni_env)
 {
     TRACE2("jni", "ExceptionCheck called, exception status = " << exn_raised());
     assert(hythread_is_suspend_enabled());
-    if (exn_raised())
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+    
+    if (exn_raised() || vm_env->IsVmShutdowning())
         return JNI_TRUE;
     else
         return JNI_FALSE;
 }
 
-VMEXPORT jmethodID JNICALL FromReflectedMethod(JNIEnv *env, jobject method)
+VMEXPORT jmethodID JNICALL FromReflectedMethod(JNIEnv * jni_env, jobject method)
 {
     TRACE2("jni", "FromReflectedMethod called");
     Class* clss = jobject_to_struct_Class(method);
 
-    if (clss == VM_Global_State::loader_env->java_lang_reflect_Constructor_Class) 
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
+
+    if (clss == vm_env->java_lang_reflect_Constructor_Class) 
     {
         static jmethodID m = (jmethodID)class_lookup_method(clss, "getId", "()J");
-        return (jmethodID) ((POINTER_SIZE_INT) CallLongMethodA(env, method, m, 0));
+        return (jmethodID) ((POINTER_SIZE_INT) CallLongMethodA(jni_env, method, m, 0));
     } 
-    else if (clss == VM_Global_State::loader_env->java_lang_reflect_Method_Class)
+    else if (clss == vm_env->java_lang_reflect_Method_Class)
     {
         static jmethodID m = (jmethodID)class_lookup_method(clss, "getId", "()J");
-        return (jmethodID) ((POINTER_SIZE_INT) CallLongMethodA(env, method, m, 0));
+        return (jmethodID) ((POINTER_SIZE_INT) CallLongMethodA(jni_env, method, m, 0));
     }
-    else
-        return NULL;
+    return NULL;
 }
 
-VMEXPORT jfieldID JNICALL FromReflectedField(JNIEnv *env, jobject field)
+VMEXPORT jfieldID JNICALL FromReflectedField(JNIEnv * jni_env, jobject field)
 {
     TRACE2("jni", "FromReflectedField called");
     Class* clss = jobject_to_struct_Class(field);
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
 
-    if (clss == VM_Global_State::loader_env->java_lang_reflect_Field_Class) 
+    if (clss == vm_env->java_lang_reflect_Field_Class) 
     {
         static jmethodID m = (jmethodID)class_lookup_method(clss, "getId", "()J");
-        return (jfieldID) ((POINTER_SIZE_INT) CallLongMethodA(env, field, m, 0));
+        return (jfieldID) ((POINTER_SIZE_INT) CallLongMethodA(jni_env, field, m, 0));
     }
-    else
-        return NULL;
+    return NULL;
 }
 
-VMEXPORT jobject JNICALL ToReflectedMethod(JNIEnv *env, jclass UNREF cls, jmethodID methodID,
+VMEXPORT jobject JNICALL ToReflectedMethod(JNIEnv * jni_env, jclass UNREF cls, jmethodID methodID,
                                             jboolean isStatic)
 {
     TRACE2("jni", "ToReflectedMethod called");
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
     Method *m = (Method*)methodID;
-    if ((bool)m->is_static() != (bool)isStatic) // True if flags are different
+    // True if flags are different
+    if ((bool)m->is_static() != (bool)isStatic || vm_env->IsVmShutdowning())
         return NULL;
 
     if (m->is_init())
-        return reflection_reflect_constructor(env, m);
+        return reflection_reflect_constructor(jni_env, m);
     else
-        return reflection_reflect_method(env, m);
+        return reflection_reflect_method(jni_env, m);
 }
 
-VMEXPORT jobject JNICALL ToReflectedField(JNIEnv *env, jclass UNREF cls, jfieldID fieldID,
+VMEXPORT jobject JNICALL ToReflectedField(JNIEnv * jni_env, jclass UNREF cls, jfieldID fieldID,
                                            jboolean isStatic)
 {
     TRACE2("jni", "ToReflectedField called");
+
+    Global_Env * vm_env = jni_get_vm_env(jni_env);
     Field *f = (Field*)fieldID;
-    if ((bool)f->is_static() != (bool)isStatic) // True if flags are different
+    if ((bool)f->is_static() != (bool)isStatic || vm_env->IsVmShutdowning()) // True if flags are different
         return NULL;
 
-    return reflection_reflect_field(env, fieldID);
+    return reflection_reflect_field(jni_env, fieldID);
 }
 
 jobject JNICALL NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity)
@@ -1727,7 +1797,6 @@
     assert(hythread_is_suspend_enabled());
 }
 
-
 void unsafe_global_object_handles_init(JNIEnv * jni_env) {
     assert(!hythread_is_suspend_enabled());
     tmn_suspend_enable();
@@ -1740,7 +1809,7 @@
     jfieldID NEGATIVE_INFINITY_id = jni_env->GetStaticFieldID((jclass)gh_jldouble, "NEGATIVE_INFINITY", "D");      
     gc_double_NEGATIVE_INFINITY = jni_env->GetStaticDoubleField((jclass)gh_jldouble, NEGATIVE_INFINITY_id);    
     assert(hythread_is_suspend_enabled());
-     check_for_unexpected_exception();
-     assert(hythread_is_suspend_enabled());
+    check_for_unexpected_exception();
+    assert(hythread_is_suspend_enabled());
     tmn_suspend_disable();
 }