提交 6284011b 编写于 作者: P phh

6819213: revive sun.boot.library.path

Summary: Support multiplex and mutable sun.boot.library.path
Reviewed-by: acorn, dcubed, xlu
上级 34826104
......@@ -1518,21 +1518,51 @@ const char* os::dll_file_extension() { return ".so"; }
const char* os::get_temp_directory() { return "/tmp/"; }
void os::dll_build_name(
char* buffer, size_t buflen, const char* pname, const char* fname) {
// copied from libhpi
static bool file_exists(const char* filename) {
struct stat statbuf;
if (filename == NULL || strlen(filename) == 0) {
return false;
}
return os::stat(filename, &statbuf) == 0;
}
void os::dll_build_name(char* buffer, size_t buflen,
const char* pname, const char* fname) {
// Copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0;
/* Quietly truncate on buffer overflow. Should be an error. */
// Quietly truncate on buffer overflow. Should be an error.
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
*buffer = '\0';
return;
}
if (pnamelen == 0) {
sprintf(buffer, "lib%s.so", fname);
snprintf(buffer, buflen, "lib%s.so", fname);
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
for (int i = 0 ; i < n ; i++) {
// Really shouldn't be NULL, but check can't hurt
if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
continue; // skip the empty path values
}
snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
if (file_exists(buffer)) {
break;
}
}
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else {
sprintf(buffer, "%s/lib%s.so", pname, fname);
snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
}
}
......
......@@ -1827,21 +1827,51 @@ const char* os::dll_file_extension() { return ".so"; }
const char* os::get_temp_directory() { return "/tmp/"; }
void os::dll_build_name(
char* buffer, size_t buflen, const char* pname, const char* fname) {
// copied from libhpi
static bool file_exists(const char* filename) {
struct stat statbuf;
if (filename == NULL || strlen(filename) == 0) {
return false;
}
return os::stat(filename, &statbuf) == 0;
}
void os::dll_build_name(char* buffer, size_t buflen,
const char* pname, const char* fname) {
// Copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0;
/* Quietly truncate on buffer overflow. Should be an error. */
// Quietly truncate on buffer overflow. Should be an error.
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
*buffer = '\0';
return;
}
if (pnamelen == 0) {
sprintf(buffer, "lib%s.so", fname);
snprintf(buffer, buflen, "lib%s.so", fname);
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
for (int i = 0 ; i < n ; i++) {
// really shouldn't be NULL but what the heck, check can't hurt
if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
continue; // skip the empty path values
}
snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
if (file_exists(buffer)) {
break;
}
}
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else {
sprintf(buffer, "%s/lib%s.so", pname, fname);
snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
}
}
......
......@@ -1004,26 +1004,61 @@ const char * os::get_temp_directory()
}
}
void os::dll_build_name(char *holder, size_t holderlen,
const char* pname, const char* fname)
{
// copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0;
const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
/* Quietly truncates on buffer overflow. Should be an error. */
if (pnamelen + strlen(fname) + 10 > holderlen) {
*holder = '\0';
return;
}
static bool file_exists(const char* filename) {
if (filename == NULL || strlen(filename) == 0) {
return false;
}
return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
}
if (pnamelen == 0) {
sprintf(holder, "%s.dll", fname);
} else if (c == ':' || c == '\\') {
sprintf(holder, "%s%s.dll", pname, fname);
} else {
sprintf(holder, "%s\\%s.dll", pname, fname);
void os::dll_build_name(char *buffer, size_t buflen,
const char* pname, const char* fname) {
// Copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0;
const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
// Quietly truncates on buffer overflow. Should be an error.
if (pnamelen + strlen(fname) + 10 > buflen) {
*buffer = '\0';
return;
}
if (pnamelen == 0) {
jio_snprintf(buffer, buflen, "%s.dll", fname);
} else if (c == ':' || c == '\\') {
jio_snprintf(buffer, buflen, "%s%s.dll", pname, fname);
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
for (int i = 0 ; i < n ; i++) {
char* path = pelements[i];
// Really shouldn't be NULL, but check can't hurt
size_t plen = (path == NULL) ? 0 : strlen(path);
if (plen == 0) {
continue; // skip the empty path values
}
const char lastchar = path[plen - 1];
if (lastchar == ':' || lastchar == '\\') {
jio_snprintf(buffer, buflen, "%s%s.dll", path, fname);
} else {
jio_snprintf(buffer, buflen, "%s\\%s.dll", path, fname);
}
if (file_exists(buffer)) {
break;
}
}
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else {
jio_snprintf(buffer, buflen, "%s\\%s.dll", pname, fname);
}
}
// Needs to be in os specific directory because windows requires another
......
......@@ -852,16 +852,13 @@ bool Arguments::add_property(const char* prop) {
FreeHeap(value);
}
return true;
}
else if (strcmp(key, "sun.java.command") == 0) {
} else if (strcmp(key, "sun.java.command") == 0) {
_java_command = value;
// don't add this property to the properties exposed to the java application
FreeHeap(key);
return true;
}
else if (strcmp(key, "sun.java.launcher.pid") == 0) {
} else if (strcmp(key, "sun.java.launcher.pid") == 0) {
// launcher.pid property is private and is processed
// in process_sun_java_launcher_properties();
// the sun.java.launcher property is passed on to the java application
......@@ -870,13 +867,14 @@ bool Arguments::add_property(const char* prop) {
FreeHeap(value);
}
return true;
}
else if (strcmp(key, "java.vendor.url.bug") == 0) {
} else if (strcmp(key, "java.vendor.url.bug") == 0) {
// save it in _java_vendor_url_bug, so JVM fatal error handler can access
// its value without going through the property list or making a Java call.
_java_vendor_url_bug = value;
} else if (strcmp(key, "sun.boot.library.path") == 0) {
PropertyList_unique_add(&_system_properties, key, value, true);
return true;
}
// Create new property and add at the end of the list
PropertyList_unique_add(&_system_properties, key, value);
return true;
......@@ -895,7 +893,7 @@ void Arguments::set_mode_flags(Mode mode) {
// Ensure Agent_OnLoad has the correct initial values.
// This may not be the final mode; mode may change later in onload phase.
PropertyList_unique_add(&_system_properties, "java.vm.info",
(char*)Abstract_VM_Version::vm_info_string());
(char*)Abstract_VM_Version::vm_info_string(), false);
UseInterpreter = true;
UseCompiler = true;
......@@ -2767,7 +2765,7 @@ void Arguments::PropertyList_add(SystemProperty** plist, const char* k, char* v)
}
// This add maintains unique property key in the list.
void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, char* v) {
void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, char* v, jboolean append) {
if (plist == NULL)
return;
......@@ -2775,7 +2773,11 @@ void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, c
SystemProperty* prop;
for (prop = *plist; prop != NULL; prop = prop->next()) {
if (strcmp(k, prop->key()) == 0) {
prop->set_value(v);
if (append) {
prop->append_value(v);
} else {
prop->set_value(v);
}
return;
}
}
......
......@@ -475,10 +475,13 @@ class Arguments : AllStatic {
// System properties
static void init_system_properties();
// Proptery List manipulation
// Property List manipulation
static void PropertyList_add(SystemProperty** plist, SystemProperty *element);
static void PropertyList_add(SystemProperty** plist, const char* k, char* v);
static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v);
static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v) {
PropertyList_unique_add(plist, k, v, false);
}
static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v, jboolean append);
static const char* PropertyList_get_value(SystemProperty* plist, const char* key);
static int PropertyList_count(SystemProperty* pl);
static const char* PropertyList_get_key_at(SystemProperty* pl,int index);
......
......@@ -90,7 +90,7 @@ public:
static inline struct protoent* get_proto_by_name(char* name);
// HPI_LibraryInterface
static inline void dll_build_name(char *buf, int buf_len, char* path,
static inline void dll_build_name(char *buf, int buf_len, const char* path,
const char *name);
static inline void* dll_load(const char *name, char *ebuf, int ebuflen);
static inline void dll_unload(void *lib);
......@@ -137,7 +137,15 @@ public:
return result; \
}
#define VM_HPIDECL_VOID(name, names, func, arg_type, arg_print, arg) \
inline void hpi::name arg_type { \
if (TraceHPI) { \
tty->print("hpi::" names "("); \
tty->print arg_print; \
tty->print(") = "); \
} \
func arg; \
}
#define HPIDECL_VOID(name, names, intf, func, arg_type, arg_print, arg) \
inline void hpi::name arg_type { \
......@@ -197,11 +205,11 @@ HPIDECL(fsize, "fsize", _file, FileSizeFD, int, "%d",
(fd, size));
// HPI_LibraryInterface
HPIDECL_VOID(dll_build_name, "dll_build_name", _library, BuildLibName,
(char *buf, int buf_len, char *path, const char *name),
("buf = %p, buflen = %d, path = %s, name = %s",
buf, buf_len, path, name),
(buf, buf_len, path, name));
VM_HPIDECL_VOID(dll_build_name, "dll_build_name", os::dll_build_name,
(char *buf, int buf_len, const char *path, const char *name),
("buf = %p, buflen = %d, path = %s, name = %s",
buf, buf_len, path, name),
(buf, buf_len, path, name));
VM_HPIDECL(dll_load, "dll_load", os::dll_load,
void *, "(void *)%p",
......
......@@ -863,7 +863,6 @@ char* os::format_boot_path(const char* format_string,
bool os::set_boot_path(char fileSep, char pathSep) {
const char* home = Arguments::get_java_home();
int home_len = (int)strlen(home);
......@@ -893,6 +892,60 @@ bool os::set_boot_path(char fileSep, char pathSep) {
return true;
}
/*
* Splits a path, based on its separator, the number of
* elements is returned back in n.
* It is the callers responsibility to:
* a> check the value of n, and n may be 0.
* b> ignore any empty path elements
* c> free up the data.
*/
char** os::split_path(const char* path, int* n) {
*n = 0;
if (path == NULL || strlen(path) == 0) {
return NULL;
}
const char psepchar = *os::path_separator();
char* inpath = (char*)NEW_C_HEAP_ARRAY(char, strlen(path) + 1);
if (inpath == NULL) {
return NULL;
}
strncpy(inpath, path, strlen(path));
int count = 1;
char* p = strchr(inpath, psepchar);
// Get a count of elements to allocate memory
while (p != NULL) {
count++;
p++;
p = strchr(p, psepchar);
}
char** opath = (char**) NEW_C_HEAP_ARRAY(char*, count);
if (opath == NULL) {
return NULL;
}
// do the actual splitting
p = inpath;
for (int i = 0 ; i < count ; i++) {
size_t len = strcspn(p, os::path_separator());
if (len > JVM_MAXPATHLEN) {
return NULL;
}
// allocate the string and add terminator storage
char* s = (char*)NEW_C_HEAP_ARRAY(char, len + 1);
if (s == NULL) {
return NULL;
}
strncpy(s, p, len);
s[len] = '\0';
opath[i] = s;
p += len + 1;
}
FREE_C_HEAP_ARRAY(char, inpath);
*n = count;
return opath;
}
void os::set_memory_serialize_page(address page) {
int count = log2_intptr(sizeof(class JavaThread)) - log2_intptr(64);
_mem_serialize_page = (volatile int32_t *)page;
......
......@@ -607,6 +607,7 @@ class os: AllStatic {
char fileSep,
char pathSep);
static bool set_boot_path(char fileSep, char pathSep);
static char** split_path(const char* path, int* n);
};
// Note that "PAUSE" is almost always used with synchronization
......
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test TestBootNativeLibraryPath.java
* @bug 6819213
* @compile -XDignore.symbol.file TestBootNativeLibraryPath.java
* @summary verify sun.boot.native.library.path is expandable on 32 bit systems
* @run main TestBootNativeLibraryPath
* @author ksrini
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class TestBootNativeLibraryPath {
private static final String TESTFILE = "Test6";
static void createTestClass() throws IOException {
FileOutputStream fos = new FileOutputStream(TESTFILE + ".java");
PrintStream ps = new PrintStream(fos);
ps.println("public class " + TESTFILE + "{");
ps.println("public static void main(String[] args) {\n");
ps.println("System.out.println(System.getProperty(\"sun.boot.library.path\"));\n");
ps.println("}}\n");
ps.close();
fos.close();
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
String javacOpts[] = {TESTFILE + ".java"};
if (javac.run(null, null, null, javacOpts) != 0) {
throw new RuntimeException("compilation of " + TESTFILE + ".java Failed");
}
}
static List<String> doExec(String... args) {
String javaCmd = System.getProperty("java.home") + "/bin/java";
if (!new File(javaCmd).exists()) {
javaCmd = System.getProperty("java.home") + "/bin/java.exe";
}
ArrayList<String> cmds = new ArrayList<String>();
cmds.add(javaCmd);
for (String x : args) {
cmds.add(x);
}
System.out.println("cmds=" + cmds);
ProcessBuilder pb = new ProcessBuilder(cmds);
Map<String, String> env = pb.environment();
pb.directory(new File("."));
List<String> out = new ArrayList<String>();
try {
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader rd = new BufferedReader(new InputStreamReader(p.getInputStream()),8192);
String in = rd.readLine();
while (in != null) {
out.add(in);
System.out.println(in);
in = rd.readLine();
}
int retval = p.waitFor();
p.destroy();
if (retval != 0) {
throw new RuntimeException("Error: test returned non-zero value");
}
return out;
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex.getMessage());
}
}
public static void main(String[] args) {
try {
if (!System.getProperty("sun.arch.data.model").equals("32")) {
System.out.println("Warning: test skipped for 64-bit systems\n");
return;
}
String osname = System.getProperty("os.name");
if (osname.startsWith("Windows")) {
osname = "Windows";
}
createTestClass();
// Test a simple path
String libpath = File.pathSeparator + "tmp" + File.pathSeparator + "foobar";
List<String> processOut = null;
String sunbootlibrarypath = "-Dsun.boot.library.path=" + libpath;
processOut = doExec(sunbootlibrarypath, "-cp", ".", TESTFILE);
if (processOut == null || !processOut.get(0).endsWith(libpath)) {
throw new RuntimeException("Error: did not get expected error string");
}
} catch (IOException ex) {
throw new RuntimeException("Unexpected error " + ex);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册