Review request for 7034570 - java.lang.Runtime.exec(String[] cmd, String[] env) can not work properly if SystemRoot not inherited
Ulf Zibis
Ulf.Zibis at gmx.de
Fri Apr 15 11:35:03 UTC 2011
Am 15.04.2011 11:45, schrieb Michael McMahon:
> Ulf,
>
> On "SystemRoot" vs "systemroot", I had thought that Windows required the sort
> to be case-sensitive. But, I double-checked and it doesn't. So we can use "SystemRoot".
If that would be true, we wouldn't need to sort by CASE_INSENSITIVE_ORDER or rather NameComparator. ;-)
Again my question: What you think of my below code?
I think we only need 1 call site to insert the potentially missing "SystemRoot" variable, a simple
array is faster than initializing a needless j.u.List, and boolean foundSysRoot is redundant to int cmp.
Additionally I think having the addEnv method is too disproportionate. We can just inline 2
different String-catenations, and it should compile to 3/4 sb.append() under the hood.
So here my shortest version:
// Only for use by ProcessImpl.start()
String toEnvironmentBlock() {
// Sort Unicode-case-insensitively by name
Map.Entry<String,String>[] list = entrySet().toArray(new Map.Entry<>[size()]);
Arrays.sort(list, entryComparator);
StringBuilder sb = new StringBuilder(list.length*30);
for (int i = 0, cmp = -1; ; i++) {
Map.Entry<String,String> e = i < list.length ? list[i] : null;
// Some versions of MSVCRT.DLL require SystemRoot to be set:
final String ROOT = "SystemRoot";
if (cmp < 0 && (e == null || (cmp = nameComparator.compare(e.getKey(), ROOT)) > 0)) {
String value = getenv(ROOT);
if (value != null)
sb.append(ROOT+'='+value+'\u0000');
// Ensure double NUL termination, even if environment is empty.
else if (list.length == 0)
sb.append('\u0000');
}
if (e == null) break;
sb.append(e.getKey()+'='+e.getValue()+'\u0000');
}
// Ensure double NUL termination
return sb.append('\u0000').toString();
}
-Ulf
>
> Ulf Zibis wrote:
>> You can have the code much shorter (and faster):
>>
>> // Only for use by ProcessImpl.start()
>> String toEnvironmentBlock() {
>> // Sort Unicode-case-insensitively by name
>> Map.Entry<String,String>[] list = entrySet().toArray(new Map.Entry<>[size()]);
>> Arrays.sort(list, entryComparator);
>>
>> StringBuilder sb = new StringBuilder(list.length*30);
>> for (int i = 0, cmp = -1; ; i++) {
>> Map.Entry<String,String> e = i < list.length ? list[i] : null;
>> final String ROOT = "SystemRoot";
>> if (cmp < 0 && (e == null || (cmp = nameComparator.compare(e.getKey(), ROOT)) > 0)) {
>> String value = getenv(ROOT);
>> if (value != null)
>> addEnv(sb, ROOT, value);
>> // Ensure double NUL termination, even if environment is empty.
>> else if (list.length == 0)
>> sb.append('\u0000');
>> }
>> if (e == null) break;
>> addEnv(sb, e.getKey(), e.getValue());
>> }
>> // Ensure double NUL termination
>> return sb.append('\u0000').toString();
>> }
>>
>> // add the environment variable to the child
>> private static void addEnv(StringBuilder sb, String key, String value) {
>> sb.append(key+'='+value+'\u0000'); // under the hood, it compiles to 4 sb.append()
>> }
>>
>> Do you like it?
>>
>> Note: I think, if we use NameComparator, we can use "SystemRoot".
>>
>> -Ulf
More information about the core-libs-dev
mailing list