← Назад к вопросам

В каком виде код попадает в JAR-файл

1.0 Junior🔥 191 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# В каком виде код попадает в JAR-файл

Код в JAR-файл попадает в виде скомпилированного Java bytecode — промежуточного представления, которое исполняется виртуальной машиной JVM, а не процессором напрямую.

Полный процесс: Java код → JAR

1. Исходный код (.java)

// src/main/java/com/example/Calculator.java
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

2. Компиляция

Компилятор javac преобразует .java в .class файлы с bytecode:

javac src/main/java/com/example/Calculator.java
# Результат: src/main/java/com/example/Calculator.class

3. Содержимое .class файла (bytecode)

Calculator.class содержит байт-код — инструкции для JVM:

CAfebabe    (магический номер JVM)
0000  0034  (версия Java)
constant_pool (константы, строки, имена методов)
methods:     (bytecode инструкции методов)
  public int add(int, int)
    0: iconst_0   (поместить 0 в стек)
    1: istore_3   (сохранить в переменную)
    2: iload_1    (загрузить параметр a)
    3: iload_2    (загрузить параметр b)
    4: iadd       (добавить)
    5: ireturn    (вернуть)

4. Упаковка в JAR

Все скомпилированные .class файлы упаковываются в ZIP архив (JAR):

jar cf myapp.jar -C build/classes .
# или через Maven:
mvn package  # создаст target/myapp-1.0.jar

Структура JAR файла

myapp-1.0.jar
├── META-INF/
│   ├── MANIFEST.MF        (метаданные)
│   └── maven/
│       └── com/example/...
├── com/
│   └── example/
│       ├── Calculator.class
│       ├── Utils.class
│       └── Main.class
├── resources/
│   ├── application.properties
│   └── logo.png
└── lib/
    └── dependency.jar     (другие библиотеки)

Это просто ZIP архив, в котором .class файлы лежат в той же структуре папок, что и в исходном коде.

Как смотреть содержимое JAR

# Список файлов
jar tf myapp-1.0.jar

# Распаковать
jar xf myapp-1.0.jar

# Или через unzip
unzip myapp-1.0.jar

Дизассемблирование: как посмотреть bytecode

# Инструмент javap показывает bytecode
javap -c Calculator.class

# Вывод:
# public int add(int, int);
#   Code:
#      0: iload_1
#      1: iload_2
#      2: iadd
#      3: ireturn

Важные точки

1. Исходный код НЕ включается

// src/main/java/com/example/Secret.java
public class Secret {
    private String apiKey = "secret-key-123";  // Есть в коде
}

// В Secret.class будет bytecode, но НЕ сам текст apiKey
// Однако, через reflection можно получить имя поля и тип

2. Метаданные сохраняются

public class Example {
    @Deprecated
    public void oldMethod() {}  // Аннотация сохранится в bytecode
}

3. Константы инлайнятся

public class Constants {
    public static final int MAX = 100;
    public int getMax() {
        return MAX;  // В bytecode будет просто 100, не ссылка на поле
    }
}

Пример: полный процесс с Maven

# 1. Написали код
echo 'public class Hello { public static void main(String[] a) { System.out.println("Hi"); } }' > src/main/java/Hello.java

# 2. Скомпилировали
mvn compile
# Создано: target/classes/Hello.class

# 3. Упаковали
mvn jar:jar
# Создано: target/hello-1.0.jar

# 4. Запустили
java -jar target/hello-1.0.jar
# или
java -cp target/hello-1.0.jar Hello

Что происходит при запуске JAR

1. JVM читает JAR (как ZIP архив)
2. Находит нужный .class файл
3. Загружает bytecode в память
4. Проверяет его (verification)
5. Компилирует в машинный код (JIT compilation) при необходимости
6. Исполняет

Bytecode vs Machine Code

АспектBytecode (.class)Machine Code
ПлатформаНезависимо (JVM)Зависимо (x86, ARM)
РазмерМеньшеБольше
СкоростьМедленнее (при загрузке)Быстрее (исполнение)
Портативность"Write Once, Run Anywhere"Нужна перекомпиляция

Пример: проверка структуры

public class Main {
    public static void main(String[] args) {
        // Посмотрим, что попадает в JAR
        Class<?> clazz = Main.class;
        System.out.println("Класс: " + clazz.getName());
        System.out.println("Методы:");
        for (var method : clazz.getDeclaredMethods()) {
            System.out.println("  - " + method.getName());
        }
        // На этапе runtime можем узнать структуру класса
        // но исходный текст кода не видим
    }
}

Fat JAR (Uber JAR) и классификаторы

<!-- Maven: создать JAR со всеми зависимостями -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>com.example.Main</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
</plugin>

Rезультат: myapp-1.0-jar-with-dependencies.jar содержит весь код и все библиотеки.

Заключение

В JAR-файл код попадает в виде:

  • Скомпилированный bytecode (.class файлы)
  • Метаданные (аннотации, информация о типах)
  • Ресурсы (конфиги, изображения, XML)
  • Манифест (описание приложения)

Исходный код (.java) НЕ включается. Это обеспечивает независимость от платформы и позволяет JVM оптимизировать исполнение.