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

Могут ли *.jar входить в *.var

2.2 Middle🔥 121 комментариев
#JVM и управление памятью#Основы Java

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

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

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

Могут ли *.jar входить в *.var

Что такое .var файл

.var (или .jvar) - это архивный формат, введённый в Java 9 как часть нового модульного формата. Это зип-архив, который содержит версионированные файлы для поддержки различных версий Java.

Структура .var файла

mylib.var
├── META-INF/
│   └── MANIFEST.MF
├── base/
│   ├── lib/
│   │   ├── mylib.jar          ← ДА, jar может входить!
│   │   └── dependency.jar
│   ├── classes/
│   │   └── com/example/...
│   └── ...
├── 11/
│   └── lib/
│       └── mylib-java11.jar   ← Версионированный jar для Java 11
├── 17/
│   └── lib/
│       └── mylib-java17.jar   ← Версионированный jar для Java 17
└── 21/
    └── lib/
        └── mylib-java21.jar   ← Версионированный jar для Java 21

ДА, .jar файлы входят в .var

Да, .jar файлы МОГУТ и ВХОДЯТ в .var архивы.

.var - это просто контейнер для версионированных JAR файлов. Основная идея - одна библиотека может содержать разные версии JAR для разных версий Java.

Пример: Создание .var файла

# Структура проекта
mylib/
├── base/
│   ├── lib/
│   │   ├── mylib.jar
│   │   └── commons-logging.jar
│   └── META-INF/
│       └── MANIFEST.MF
├── 11/
│   └── lib/
│       └── mylib-java11.jar
├── 17/
│   └── lib/
│       └── mylib-java17.jar
└── 21/
    └── lib/
        └── mylib-java21.jar

# Упаковать в .var
$ jar --create --file mylib.var \
    --manifest MANIFEST.MF \
    -C mylib .

# Результат: mylib.var содержит все jar файлы

Как JVM выбирает нужный JAR

Когда приложение загружает .var файл, JVM выбирает подходящую версию:

// Если JVM версия 21
// JVM ищет в порядке:
// 1. /21/ - специфичный для Java 21
// 2. /17/ - если 21 не существует, ищет наиболее близкую
// 3. /11/
// 4. /base/ - базовая версия, универсальная

public class MyApplication {
    public static void main(String[] args) {
        // Если приложение запущено на Java 21
        // JVM загрузит mylib-java21.jar из раздела /21/
        MyLibClass lib = new MyLibClass();
    }
}

Практический пример: Maven проект с .var

<!-- pom.xml -->
<project>
    <groupId>com.example</groupId>
    <artifactId>mylib</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>  <!-- Обычно jar, но может быть и var -->
    
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

При сборке можно создать .var с несколькими версиями JAR:

$ mvn clean package
# Результат:
# target/mylib-1.0.0.jar
# или target/mylib-1.0.0.var (если настроено)

Что находится внутри .var: подробный пример

# Посмотреть содержимое .var
$ jar tf mylib.var

META-INF/
META-INF/MANIFEST.MF
base/
base/lib/
base/lib/mylib.jar          ← JAR файл
base/lib/commons-logging.jar ← JAR файл
base/META-INF/
base/META-INF/MANIFEST.MF
11/
11/lib/
11/lib/mylib-java11.jar    ← JAR файл, оптимизированный для Java 11
11/META-INF/
11/META-INF/MANIFEST.MF
17/
17/lib/
17/lib/mylib-java17.jar    ← JAR файл, оптимизированный для Java 17
21/
21/lib/
21/lib/mylib-java21.jar    ← JAR файл, оптимизированный для Java 21

# Распаковать конкретный jar
$ jar xf mylib.var 17/lib/mylib-java17.jar

Вложенные структуры: может ли JAR быть в JAR

Также важно: .jar файлы могут быть вложены в другие .jar файлы

# Структура fat-jar или uber-jar
myapp.jar
├── META-INF/
│   ├── MANIFEST.MF
│   └── maven/
├── com/example/
│   └── MyApp.class
└── lib/                       ← Вложенные JAR
    ├── commons-logging.jar    ← JAR в JAR!
    ├── log4j-core.jar
    └── spring-core.jar

Использование вложенных JAR в Java

// Spring Boot использует вложенные JAR
// Структура spring-boot-app.jar:
// META-INF/
//   MANIFEST.MF (Main-Class: org.springframework.boot.loader.JarLauncher)
// org/springframework/boot/loader/
//   JarLauncher.class
// BOOT-INF/
//   classes/
//     com/example/App.class
//   lib/
//     spring-core-6.0.jar    ← JAR в JAR!
//     jackson-core-2.15.jar  ← JAR в JAR!

// JarLauncher находит и загружает вложенные JAR

.var для версионированной поддержки

// Пример библиотеки с разной реализацией для разных Java

public class PerformanceOptimizer {
    private final VectorApi vectorApi;
    
    public PerformanceOptimizer() {
        // Java 21 имеет VectorAPI
        // Java 17 может использовать старую реализацию
        // Java 11 использует базовую реализацию
        this.vectorApi = detectAndLoadOptimalVersion();
    }
    
    private VectorApi detectAndLoadOptimalVersion() {
        int javaVersion = Runtime.version().feature();
        
        switch (javaVersion) {
            case 21:
                return new VectorApiJava21Impl();  // Из /21/lib/
            case 17:
                return new VectorApiJava17Impl();  // Из /17/lib/
            default:
                return new VectorApiBaseImpl();     // Из /base/lib/
        }
    }
}

Компиляция многовверсионного JAR

# Компилировать для разных версий Java

# Базовая версия (Java 8)
javac -d target/classes src/main/java/*.java

# Специфичная для Java 11
javac --release 11 -d target/classes-11 src/main/java-11/*.java

# Специфичная для Java 17
javac --release 17 -d target/classes-17 src/main/java-17/*.java

# Упаковать в multi-release JAR
jar --create --file mylib.jar \
    --manifest MANIFEST.MF \
    -C target/classes . \
    -C target/classes-11 META-INF/versions/11 \
    -C target/classes-17 META-INF/versions/17

Современный статус .var

Формально .var поддерживается, но на практике:

  • .var редко используется в реальных проектах
  • Multi-release JAR (MRJAR) более распространён для версионирования
  • Maven и Gradle проще работают с обычными JAR файлами

Вывод

ДА, .jar файлы могут и входят в .var архивы. .var - это контейнер для версионированных JAR файлов, позволяющий одной библиотеке содержать оптимизированные версии для разных версий Java. Структура /base/, /11/, /17/ и т.д. позволяет JVM выбрать подходящую версию JAR в зависимости от версии Java, на которой запущено приложение.

Могут ли *.jar входить в *.var | PrepBro