System.getenv(): примеры (JAVA)

Метод System.getenv() в Java: получение переменных окружения
Раздел: Работа с системными свойствами и окружением
System.getenv(): Map

Описание метода System.getenv()

Метод System.getenv() предназначен для получения переменных окружения операционной системы, в которой выполняется Java-приложение. Переменные окружения представляют собой пары ключ-значение (строка-строка), доступные процессу. Метод используется, когда требуется считать конфигурационные параметры, заданные на уровне среды выполнения: пути к директориям, настройки подключения, секретные ключи и другие внешние параметры.

Метод имеет две перегруженные формы:

  • System.getenv() - без аргументов. Возвращает неизменяемую (unmodifiable) карту Map<String, String>, содержащую все текущие переменные окружения. Ключи и значения - строки. Попытка изменить возвращённую карту вызовет исключение UnsupportedOperationException.
  • System.getenv(String name) - принимает один аргумент - имя переменной. Возвращает строку - значение переменной окружения с указанным именем. Если переменная не определена, возвращается null.

Имя переменной чувствительно к регистру на большинстве Unix-подобных систем (например, Linux, macOS) и нечувствительно на Windows (хотя рекомендуется всегда указывать точный регистр). Возвращаемое значение в форме с одним аргументом - String или null.

Метод появился в JDK 1.0 и с тех пор не претерпел существенных изменений. Он относится к классу java.lang.System и является точкой доступа к окружению процесса.

Примеры использования System.getenv()

Пример 1: Получение всех переменных окружения.

import java.util.Map;
public class GetEnvAll {
    public static void main(String[] args) {
        Map<String, String> env = System.getenv();
        for (String key : env.keySet()) {
            System.out.println(key + "=" + env.get(key));
        }
    }
}
JAVA_HOME=/usr/lib/jvm/java-11-openjdk
PATH=/usr/bin:/bin
USER=user
... (зависит от системы)

Пример 2: Получение конкретной переменной.

public class GetEnvOne {
    public static void main(String[] args) {
        String path = System.getenv("PATH");
        System.out.println("PATH: " + path);
    }
}
PATH: /usr/local/bin:/usr/bin:/bin

Пример 3: Попытка получить несуществующую переменную.

public class GetEnvMissing {
    public static void main(String[] args) {
        String value = System.getenv("MY_VAR_NOT_EXISTS");
        System.out.println("Value: " + value);
    }
}
Value: null

Альтернативы в Java: System.getProperty()

В Java существует аналогичный механизм для доступа к системным свойствам - метод System.getProperty(). Системные свойства отличаются от переменных окружения:

  • Системные свойства задаются через флаг -Dproperty=value при запуске JVM и хранятся внутри виртуальной машины.
  • Переменные окружения - это параметры операционной системы, доступные всем процессам.
  • System.getProperty() возвращает String или null, а также имеет форму с аргументом по умолчанию: System.getProperty(String key, String def).

Какую альтернативу предпочесть:

  • Для внешних конфигураций, которые задаются до запуска приложения (например, в Docker-контейнере, на сервере), удобнее использовать переменные окружения.
  • Для настроек, специфичных для JVM (пути к библиотекам, кодировки), применяют системные свойства.
  • Если требуется передать параметры через командную строку с возможностью переопределения, системные свойства часто удобнее.

Следует помнить, что оба метода возвращают неизменяемые объекты (карту или строку) и не позволяют модифицировать окружение.

Альтернативы в других языках программирования

Практически все современные языки предоставляют доступ к переменным окружения. Ниже приведены краткие примеры и отличия от Java.

PHP - функция getenv():

$path = getenv('PATH');
echo $path;
$all = getenv(); // возвращает ассоциативный массив
/usr/local/bin:/usr/bin
Отличие от Java: возвращает массив, а не Map; имя может быть передано с опциональным аргументом local_only.

JavaScript (Node.js) - объект process.env:

const path = process.env.PATH;
console.log(path);
// process.env - объект, но его изменение не влияет на родительский процесс
/usr/local/bin:/usr/bin
Отличие от Java: напрямую доступен как объект; значения всегда строки; отсутствует метод, возвращающий Map.

Python - словарь os.environ:

import os
path = os.environ.get('PATH')
print(path)
# os.environ - это словарь (mapping)
/usr/local/bin:/usr/bin
Отличие от Java: изменяемый словарь, однако изменения не влияют на родительский процесс (только на дочерние).

C# - метод Environment.GetEnvironmentVariable():

string path = Environment.GetEnvironmentVariable("PATH");
Console.WriteLine(path);
/usr/local/bin:/usr/bin
Отличие от Java: есть перегрузка с указанием целевого уровня (процесс, пользователь, машина); возвращает null при отсутствии.

Go - функция os.Getenv():

package main
import "os"
func main() {
    path := os.Getenv("PATH")
    println(path)
}
/usr/local/bin:/usr/bin
Отличие от Java: возвращает пустую строку, если переменная не установлена (отсутствует nil); есть вторая форма LookupEnv.

Kotlin (на JVM) - использует тот же System.getenv() из Java, отличий нет.

Lua - таблица os.getenv():

local path = os.getenv("PATH")
print(path)
/usr/local/bin:/usr/bin
Отличие от Java: возвращает nil при отсутствии; нет возможности получить все переменные одной функцией.

В SQL нет прямой альтернативы, так как окружение не является концепцией реляционных баз данных; переменные могут передаваться через системные функции СУБД (например, GETENV() в Oracle).

Типичные ошибки при работе с System.getenv()

1. Попытка изменить возвращённую карту.
Метод System.getenv() возвращает неизменяемую карту. Любая попытка добавить, удалить или заменить элемент приводит к исключению UnsupportedOperationException.

Map<String, String> env = System.getenv();
env.put("NEW_VAR", "value"); // ошибка
Exception in thread "main" java.lang.UnsupportedOperationException

2. Игнорирование регистра ключа на Unix-системах.
На Linux и macOS имена переменных чувствительны к регистру. Запрос System.getenv("path") вернёт null, даже если существует PATH.

System.out.println(System.getenv("path")); // null на Linux
System.out.println(System.getenv("PATH")); // /usr/bin

3. Предположение, что переменная обязательно существует.
Если переменная не определена, System.getenv(name) возвращает null, а не пустую строку. Вызов методов у null приведёт к NullPointerException.

String val = System.getenv("UNDEFINED");
System.out.println(val.length()); // NullPointerException
Exception in thread "main" java.lang.NullPointerException

4. Путаница с системными свойствами.
Начинающие разработчики иногда ожидают, что System.getenv() вернёт аргументы JVM (-D). Для этого следует использовать System.getProperty().

5. Изменение окружения через ProcessBuilder после вызова getenv.
Объект, возвращённый getenv(), не связан с окружением дочерних процессов, создаваемых через ProcessBuilder. Для передачи окружения дочерним процессам необходимо настроить сам ProcessBuilder.

Изменения в версиях Java

Метод System.getenv() существует с самого первого выпуска JDK (1.0) и с тех пор его сигнатура и поведение не менялись. В ранних версиях метод getenv() без аргументов был deprecated (устаревшим) начиная с JDK 1.1 до JDK 1.4, но был восстановлен в JDK 5.0 и больше не является устаревшим.

В Java 9 была введена модульная система (Jigsaw). Модули могут ограничивать доступ к некоторым классам, но java.lang.System остаётся доступным всегда. Изменений в самом методе не произошло.

В Java 17 (LTS) и более новых версиях метод работает без изменений. Не появилось новых перегрузок или флагов.

Таким образом, System.getenv() - стабильный и неизменный API, на который можно полагаться в любой версии Java от 1.0 до 21.

Расширенные примеры использования

Пример 1: Получение значения с проверкой и значением по умолчанию (без использования тернарного оператора).

Пример java
public class GetEnvWithDefault {
    public static void main(String[] args) {
        String home = System.getenv("HOME");
        if (home == null) {
            home = "/tmp";
        }
        System.out.println("Home: " + home);
    }
}
Home: /home/user

Пример 2: Создание неизменяемой копии карты окружения (на всякий случай, хотя уже неизменяема).

Пример java
import java.util.Collections;
import java.util.Map;

public class UnmodifiableCopy {
    public static void main(String[] args) {
        Map<String, String> env = System.getenv();
        Map<String, String> copy = Collections.unmodifiableMap(env);
        System.out.println(copy.size());
    }
}
42

Пример 3: Использование в Docker-среде для чтения пароля из переменной окружения (без жёсткого кода).

Пример java
public class DbPassword {
    public static void main(String[] args) {
        String password = System.getenv("DB_PASSWORD");
        if (password == null || password.isEmpty()) {
            throw new RuntimeException("DB_PASSWORD not set");
        }
        // соединение с БД
        System.out.println("Password retrieved");
    }
}
(выполнение без ошибок, если переменная задана)

Пример 4: Перебор всех переменных окружения с фильтрацией по префиксу (например, MYAPP_).

Пример java
public class FilteredEnv {
    public static void main(String[] args) {
        String prefix = "MYAPP_";
        Map<String, String> env = System.getenv();
        for (Map.Entry<String, String> entry : env.entrySet()) {
            if (entry.getKey().startsWith(prefix)) {
                System.out.println(entry.getKey() + " = " + entry.getValue());
            }
        }
    }
}
(выводятся только переменные, начинающиеся с MYAPP_)

Пример 5: Проверка на существование переменной с использованием containsKey().

Пример java
public class CheckExists {
    public static void main(String[] args) {
        Map<String, String> env = System.getenv();
        if (env.containsKey("JAVA_HOME")) {
            System.out.println("JAVA_HOME is set to " + env.get("JAVA_HOME"));
        } else {
            System.out.println("JAVA_HOME is not set");
        }
    }
}
JAVA_HOME is set to /usr/lib/jvm/java-11-openjdk

Пример 6: Конвертация карты в обычный HashMap для последующей модификации (хотя модификация не повлияет на окружение).

Пример java
import java.util.HashMap;
import java.util.Map;

public class MutableEnvCopy {
    public static void main(String[] args) {
        Map<String, String> env = System.getenv();
        Map<String, String> mutable = new HashMap<>(env);
        mutable.put("MY_VAR", "my_value");
        System.out.println(mutable.get("MY_VAR"));
    }
}
my_value

джава System.getenv() function comments

En
System.getenv() Returns an unmodifiable string map view of the current system environment