अधिकांश लोगों की तरह जिन्होंने इस धागे को पाया है, मैं कुछ यूनिट टेस्ट लिख रहा था और परीक्षण चलाने के लिए सही परिस्थितियों को सेट करने के लिए पर्यावरण चर को संशोधित करने की आवश्यकता थी। हालाँकि, मैंने पाया कि सबसे अधिक उत्तर दिए गए उत्तरों में कुछ मुद्दे थे और / या बहुत गूढ़ या अति जटिल थे। उम्मीद है कि यह दूसरों को समाधान को जल्दी से हल करने में मदद करेगा।
सबसे पहले, मैंने आखिरकार @Hubert Grzeskowiak का समाधान सबसे सरल पाया और यह मेरे लिए काम कर गया। काश मैं पहले उस पर आ जाता। यह @ एडवर्ड कैंपबेल के उत्तर पर आधारित है, लेकिन लूप खोज के लिए जटिल नहीं है।
हालांकि, मैंने @ पुसी के समाधान के साथ शुरुआत की, जिसे सबसे अधिक उत्थान मिला। यह @ बेनामी और @ एडवर्ड कैंपबेल का कॉम्बो है। @pushy का दावा है कि दोनों दृष्टिकोणों को लिनक्स और विंडोज वातावरण दोनों को कवर करने की आवश्यकता है। मैं ओएस एक्स के तहत चल रहा हूं और पाता हूं कि दोनों काम (एक बार @anonymous दृष्टिकोण के साथ एक मुद्दा तय हो गया है)। जैसा कि दूसरों ने नोट किया है, यह समाधान ज्यादातर समय काम करता है, लेकिन सभी नहीं।
मुझे लगता है कि अधिकांश भ्रम का स्रोत 'गुमनाम समाधान' क्षेत्र में @ बेनामी समाधान के संचालन से आता है। ProcessEnvironment संरचना , 'theEnvironment' कोई नक्शा <स्ट्रिंग, स्ट्रिंग> नहीं है, बल्कि यह एक नक्शा <Variable, Value> है। मानचित्र को साफ़ करना ठीक काम करता है, लेकिन putAll ऑपरेशन मानचित्र को मानचित्र <String, String> से पुनः जोड़ता है, जो संभावित रूप से तब समस्याएँ पैदा करता है जब बाद के संचालन सामान्य API का उपयोग करके डेटा संरचना पर कार्य करते हैं जो मानचित्र <Variable, Value> की अपेक्षा करता है। इसके अलावा, व्यक्तिगत तत्वों तक पहुंच / हटाना एक समस्या है। इसका समाधान अप्रत्यक्ष रूप से 'theUnmodifiableEnvironment' के माध्यम से 'theEnvironment' तक पहुँचना है। लेकिन चूंकि यह एक प्रकार है की परिभाषा को देखते UnmodifiableMap हैहुए पहुँच को UnmodifiableMap प्रकार के निजी चर 'm' के माध्यम से किया जाना चाहिए। नीचे दिए गए कोड में getModifiableEnvironmentMap2 देखें।
मेरे मामले में मुझे अपने परीक्षण के लिए कुछ पर्यावरण चर निकालने की जरूरत थी (अन्य को अपरिवर्तित होना चाहिए)। तब मैं परीक्षण के बाद पर्यावरण चर को उनकी पूर्व स्थिति में पुनर्स्थापित करना चाहता था। नीचे दी गई दिनचर्या उस कार्य को सीधे करने के लिए आगे करती है। मैंने OS X पर getModifiableEnvironmentMap के दोनों संस्करणों का परीक्षण किया, और दोनों समान रूप से काम करते हैं। हालांकि इस सूत्र में टिप्पणियों के आधार पर, एक पर्यावरण के आधार पर दूसरे की तुलना में बेहतर विकल्प हो सकता है।
नोट: मैंने 'theCaseInsensitiveEnvironmentField' तक पहुँच को शामिल नहीं किया है क्योंकि यह विंडोज विशिष्ट प्रतीत होता है और मेरे पास इसका परीक्षण करने का कोई तरीका नहीं था, लेकिन इसे जोड़ना सीधे आगे होना चाहिए।
private Map<String, String> getModifiableEnvironmentMap() {
try {
Map<String,String> unmodifiableEnv = System.getenv();
Class<?> cl = unmodifiableEnv.getClass();
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Map<String,String> modifiableEnv = (Map<String,String>) field.get(unmodifiableEnv);
return modifiableEnv;
} catch(Exception e) {
throw new RuntimeException("Unable to access writable environment variable map.");
}
}
private Map<String, String> getModifiableEnvironmentMap2() {
try {
Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
Field theUnmodifiableEnvironmentField = processEnvironmentClass.getDeclaredField("theUnmodifiableEnvironment");
theUnmodifiableEnvironmentField.setAccessible(true);
Map<String,String> theUnmodifiableEnvironment = (Map<String,String>)theUnmodifiableEnvironmentField.get(null);
Class<?> theUnmodifiableEnvironmentClass = theUnmodifiableEnvironment.getClass();
Field theModifiableEnvField = theUnmodifiableEnvironmentClass.getDeclaredField("m");
theModifiableEnvField.setAccessible(true);
Map<String,String> modifiableEnv = (Map<String,String>) theModifiableEnvField.get(theUnmodifiableEnvironment);
return modifiableEnv;
} catch(Exception e) {
throw new RuntimeException("Unable to access writable environment variable map.");
}
}
private Map<String, String> clearEnvironmentVars(String[] keys) {
Map<String,String> modifiableEnv = getModifiableEnvironmentMap();
HashMap<String, String> savedVals = new HashMap<String, String>();
for(String k : keys) {
String val = modifiableEnv.remove(k);
if (val != null) { savedVals.put(k, val); }
}
return savedVals;
}
private void setEnvironmentVars(Map<String, String> varMap) {
getModifiableEnvironmentMap().putAll(varMap);
}
@Test
public void myTest() {
String[] keys = { "key1", "key2", "key3" };
Map<String, String> savedVars = clearEnvironmentVars(keys);
// do test
setEnvironmentVars(savedVars);
}