Комментарии (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 оптимизировать исполнение.