Home » Основы Java — учебник для начинающих
Основы Java — учебник для начинающих

Основы Java — учебник для начинающих

Если ты серверный админ, то Java — это то, с чем ты столкнёшься рано или поздно. Половина корпоративных приложений написана на ней, веб-серверы вроде Tomcat или Jetty крутят Java-код, а различные утилиты для мониторинга и автоматизации тоже часто написаны на Java. Понимание основ этого языка поможет тебе не только разобраться в логах и конфигах, но и написать собственные скрипты для автоматизации рутинных задач. Да, Python может быть проще для скриптинга, но Java даёт больше контроля над системными ресурсами и лучше интегрируется с enterprise-окружением.

В этой статье мы разберём Java с точки зрения практического применения на серверах. Я покажу, как быстро поднять среду разработки, написать первые утилиты и интегрировать их в твою инфраструктуру. Никаких академических примеров с “Hello World” — только то, что реально пригодится в работе.

Как это работает: архитектура Java

Java — это компилируемый язык, но работает он не совсем так, как C++ или Go. Когда ты компилируешь Java-код, получается не нативный машинный код, а байт-код, который выполняется в виртуальной машине Java (JVM). Это означает, что один и тот же .jar файл запустится на любой системе, где есть JVM.

Для серверного администратора это важно понимать, потому что:

  • Java-приложения потребляют память под JVM + само приложение
  • Настройки JVM (heap size, garbage collector) сильно влияют на производительность
  • Один сервер может запускать несколько JVM с разными приложениями
  • Все Java-приложения зависят от версии JRE/JDK

Основные компоненты экосистемы:

  • JDK (Java Development Kit) — полный набор для разработки
  • JRE (Java Runtime Environment) — только для запуска приложений
  • JVM (Java Virtual Machine) — виртуальная машина

Быстрая настройка среды разработки

Если ты работаешь с серверами, скорее всего у тебя Ubuntu/CentOS/Debian. Вот как быстро поднять Java-окружение:

Ubuntu/Debian:


# Обновляем пакеты
sudo apt update

# Устанавливаем OpenJDK (рекомендую 11 или 17 LTS)
sudo apt install openjdk-11-jdk

# Проверяем установку
java -version
javac -version

# Настраиваем JAVA_HOME
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64' >> ~/.bashrc
echo 'export PATH=$PATH:$JAVA_HOME/bin' >> ~/.bashrc
source ~/.bashrc

CentOS/RHEL:


# Устанавливаем OpenJDK
sudo yum install java-11-openjdk-devel

# Или для новых версий CentOS
sudo dnf install java-11-openjdk-devel

# Настраиваем переменные окружения
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk' >> ~/.bashrc
source ~/.bashrc

Для продакшена лучше использовать VPS или выделенный сервер с достаточным объёмом RAM — Java-приложения прожорливы к памяти.

Первая практическая утилита: мониторинг дискового пространства

Давай сразу напишем что-то полезное. Создадим утилиту для мониторинга свободного места на дисках:


// DiskMonitor.java
import java.io.File;
import java.text.DecimalFormat;
import java.util.Arrays;

public class DiskMonitor {
    private static final DecimalFormat df = new DecimalFormat("#.##");
    
    public static void main(String[] args) {
        // Получаем все корневые директории
        File[] roots = File.listRoots();
        
        System.out.println("Disk Usage Report:");
        System.out.println("==================");
        
        for (File root : roots) {
            long totalSpace = root.getTotalSpace();
            long freeSpace = root.getFreeSpace();
            long usedSpace = totalSpace - freeSpace;
            
            double usedPercent = (double) usedSpace / totalSpace * 100;
            
            System.out.printf("Mount: %s\n", root.getAbsolutePath());
            System.out.printf("Total: %s GB\n", formatBytes(totalSpace));
            System.out.printf("Used:  %s GB (%.1f%%)\n", formatBytes(usedSpace), usedPercent);
            System.out.printf("Free:  %s GB\n", formatBytes(freeSpace));
            
            // Предупреждение при заполнении > 80%
            if (usedPercent > 80) {
                System.out.println("⚠️  WARNING: Disk usage is high!");
            }
            
            System.out.println();
        }
    }
    
    private static String formatBytes(long bytes) {
        double gb = bytes / (1024.0 * 1024.0 * 1024.0);
        return df.format(gb);
    }
}

Компилируем и запускаем:


javac DiskMonitor.java
java DiskMonitor

Полезные примеры для серверного администрирования

Парсинг логов

Часто нужно быстро проанализировать логи. Вот утилита для парсинга Apache access.log:


// LogAnalyzer.java
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class LogAnalyzer {
    private static final Pattern LOG_PATTERN = Pattern.compile(
        "^(\\S+) \\S+ \\S+ \\[([\\w:/]+\\s[+\\-]\\d{4})\\] \"(\\S+) (\\S+) (\\S+)\" (\\d{3}) (\\d+|-)"
    );
    
    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Usage: java LogAnalyzer ");
            System.exit(1);
        }
        
        Map ipCounts = new HashMap<>();
        Map statusCounts = new HashMap<>();
        
        try (BufferedReader reader = new BufferedReader(new FileReader(args[0]))) {
            String line;
            while ((line = reader.readLine()) != null) {
                Matcher matcher = LOG_PATTERN.matcher(line);
                if (matcher.matches()) {
                    String ip = matcher.group(1);
                    String status = matcher.group(6);
                    
                    ipCounts.put(ip, ipCounts.getOrDefault(ip, 0) + 1);
                    statusCounts.put(status, statusCounts.getOrDefault(status, 0) + 1);
                }
            }
        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
            System.exit(1);
        }
        
        System.out.println("Top 10 IPs:");
        ipCounts.entrySet().stream()
            .sorted(Map.Entry.comparingByValue().reversed())
            .limit(10)
            .forEach(entry -> System.out.printf("%s: %d requests\n", entry.getKey(), entry.getValue()));
        
        System.out.println("\nStatus codes:");
        statusCounts.forEach((status, count) -> 
            System.out.printf("%s: %d\n", status, count));
    }
}

Проверка сетевых портов

Простая утилита для проверки доступности портов:


// PortChecker.java
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class PortChecker {
    public static void main(String[] args) {
        if (args.length != 2) {
            System.err.println("Usage: java PortChecker  ");
            System.exit(1);
        }
        
        String host = args[0];
        int port = Integer.parseInt(args[1]);
        
        checkPort(host, port);
    }
    
    private static void checkPort(String host, int port) {
        try (Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress(host, port), 3000);
            System.out.printf("✅ Port %d is open on %s\n", port, host);
        } catch (IOException e) {
            System.out.printf("❌ Port %d is closed on %s (%s)\n", port, host, e.getMessage());
        }
    }
}

Сравнение с другими решениями

Критерий Java Python Bash Go
Скорость разработки Средняя Высокая Низкая Средняя
Производительность Высокая Низкая Средняя Очень высокая
Потребление памяти Высокое Среднее Низкое Низкое
Интеграция с enterprise Отличная Хорошая Плохая Средняя
Многопоточность Отличная Плохая Средняя Отличная

Продвинутые возможности для автоматизации

Интеграция с системными командами

Java может выполнять системные команды и обрабатывать их вывод:


// SystemCommand.java
import java.io.*;

public class SystemCommand {
    public static String executeCommand(String command) throws IOException {
        ProcessBuilder pb = new ProcessBuilder("bash", "-c", command);
        Process process = pb.start();
        
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        StringBuilder output = new StringBuilder();
        String line;
        
        while ((line = reader.readLine()) != null) {
            output.append(line).append("\n");
        }
        
        return output.toString();
    }
    
    public static void main(String[] args) {
        try {
            // Получаем нагрузку на CPU
            String cpuInfo = executeCommand("top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | sed 's/%us,//'");
            System.out.println("CPU Usage: " + cpuInfo.trim() + "%");
            
            // Получаем информацию о памяти
            String memInfo = executeCommand("free -h | grep Mem | awk '{print $3 \"/\" $2}'");
            System.out.println("Memory Usage: " + memInfo.trim());
            
        } catch (IOException e) {
            System.err.println("Error executing command: " + e.getMessage());
        }
    }
}

Работа с файлами конфигурации

Часто нужно парсить и модифицировать конфиги. Вот пример работы с properties-файлами:


// ConfigManager.java
import java.io.*;
import java.util.Properties;

public class ConfigManager {
    private Properties props;
    private String configFile;
    
    public ConfigManager(String configFile) throws IOException {
        this.configFile = configFile;
        this.props = new Properties();
        
        try (FileInputStream fis = new FileInputStream(configFile)) {
            props.load(fis);
        }
    }
    
    public String get(String key) {
        return props.getProperty(key);
    }
    
    public void set(String key, String value) {
        props.setProperty(key, value);
    }
    
    public void save() throws IOException {
        try (FileOutputStream fos = new FileOutputStream(configFile)) {
            props.store(fos, "Updated by ConfigManager");
        }
    }
    
    public static void main(String[] args) {
        try {
            ConfigManager config = new ConfigManager("server.properties");
            
            // Читаем текущие настройки
            System.out.println("Current port: " + config.get("server.port"));
            
            // Изменяем настройки
            config.set("server.port", "8080");
            config.set("server.host", "0.0.0.0");
            
            // Сохраняем изменения
            config.save();
            
        } catch (IOException e) {
            System.err.println("Error: " + e.getMessage());
        }
    }
}

Интересные факты и нестандартные применения

Вот несколько интересных способов использования Java в серверном администрировании:

  • JMX (Java Management Extensions) — позволяет мониторить и управлять Java-приложениями удалённо. Многие инструменты мониторинга используют JMX для получения метрик.
  • Java NIO — для высокопроизводительных сетевых приложений. Можно написать свой lightweight прокси-сервер.
  • Scripting Engine — Java может выполнять скрипты на JavaScript, Groovy и других языках прямо внутри JVM.
  • Native Image (GraalVM) — компилирует Java-код в нативные бинарники, что устраняет overhead JVM.

Статистика использования Java в серверной инфраструктуре по данным TIOBE Index:

  • Java остаётся в топ-3 языков программирования уже более 20 лет
  • Около 40% enterprise-приложений написано на Java
  • Netflix, LinkedIn, Uber активно используют Java для backend-сервисов

Альтернативные JVM-языки

Если синтаксис Java кажется избыточным, можно использовать другие языки, которые компилируются в JVM bytecode:

  • Kotlin — современный язык от JetBrains, более лаконичный синтаксис
  • Scala — функциональный язык, популярен в big data (Spark, Kafka)
  • Groovy — динамический язык, отлично подходит для скриптинга
  • Clojure — функциональный Lisp для JVM

Полезные библиотеки и фреймворки

Для серверного администрирования пригодятся:

  • Apache Commons — набор утилит для работы с файлами, строками, коллекциями
  • Jackson — для работы с JSON/XML
  • OkHttp — HTTP-клиент для REST API
  • Logback/SLF4J — логирование
  • Quartz — планировщик задач
  • Spring Boot — для создания микросервисов

Пример использования OkHttp для мониторинга веб-сервисов:


// ServiceMonitor.java
import okhttp3.*;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;

public class ServiceMonitor {
    private static final OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(Duration.ofSeconds(5))
        .readTimeout(Duration.ofSeconds(10))
        .build();
    
    public static void checkService(String url) {
        Request request = new Request.Builder()
            .url(url)
            .build();
        
        Instant start = Instant.now();
        
        try (Response response = client.newCall(request).execute()) {
            Duration responseTime = Duration.between(start, Instant.now());
            
            if (response.isSuccessful()) {
                System.out.printf("✅ %s - OK (%d ms)\n", url, responseTime.toMillis());
            } else {
                System.out.printf("❌ %s - Error %d (%d ms)\n", url, response.code(), responseTime.toMillis());
            }
        } catch (IOException e) {
            Duration responseTime = Duration.between(start, Instant.now());
            System.out.printf("❌ %s - Connection failed (%d ms): %s\n", url, responseTime.toMillis(), e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        String[] services = {
            "https://google.com",
            "https://github.com",
            "http://localhost:8080/health"
        };
        
        for (String service : services) {
            checkService(service);
        }
    }
}

Создание собственного JAR-файла

Для удобства развёртывания лучше упаковать утилиты в JAR-файлы:


# Создаём манифест
echo "Main-Class: DiskMonitor" > manifest.txt

# Компилируем
javac DiskMonitor.java

# Создаём JAR
jar cfm diskmonitor.jar manifest.txt DiskMonitor.class

# Запускаем
java -jar diskmonitor.jar

Для автоматизации сборки лучше использовать Maven или Gradle:





    4.0.0
    
    com.example
    server-tools
    1.0-SNAPSHOT
    
    
        11
        11
    
    
    
        
            com.squareup.okhttp3
            okhttp
            4.11.0
        
    

Интеграция с Docker

Современные Java-приложения часто запускаются в контейнерах. Вот пример Dockerfile:


# Dockerfile
FROM openjdk:11-jre-slim

WORKDIR /app

COPY target/server-tools-1.0-SNAPSHOT.jar app.jar

# Оптимизируем для контейнера
ENV JAVA_OPTS="-Xmx256m -Xms128m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"

EXPOSE 8080

CMD ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

Важные настройки JVM для контейнеров:

  • -XX:+UseContainerSupport — учитывает лимиты контейнера
  • -XX:InitialRAMPercentage=50 — процент памяти для heap
  • -XX:MaxRAMPercentage=80 — максимальный процент памяти

Заключение и рекомендации

Java для серверного администратора — это мощный инструмент, который стоит изучить. Да, он может показаться избыточным для простых задач, но когда нужна производительность, интеграция с enterprise-системами или сложная обработка данных, Java показывает себя с лучшей стороны.

Рекомендую начать с:

  • Установки OpenJDK 11 или 17 LTS
  • Изучения основ синтаксиса через практические задачи
  • Написания простых утилит для автоматизации рутинных задач
  • Постепенного изучения популярных библиотек и фреймворков

Используй Java там, где нужна:

  • Высокая производительность
  • Сложная многопоточность
  • Интеграция с Java-приложениями
  • Обработка больших объёмов данных
  • Создание веб-сервисов и API

Для хостинга Java-приложений выбирай серверы с достаточным объёмом RAM — минимум 2GB для простых утилит, 4GB+ для веб-приложений. VPS подойдёт для разработки и тестирования, а для продакшена лучше взять выделенный сервер.

Помни: Java — это не только “enterprise монстр”, но и практичный инструмент для повседневных задач системного администратора. Главное — не бояться verbose синтаксиса и сосредоточиться на возможностях языка.


В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.

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

Leave a reply

Your email address will not be published. Required fields are marked