Время компиляции и зависимость от времени выполнения - Java - PullRequest
74 голосов
/ 24 ноября 2010

Какая разница между зависимостями времени компиляции и времени выполнения в Java?Это связано с путем к классу, но чем они отличаются?

Ответы [ 6 ]

67 голосов
/ 25 ноября 2010
  • Зависимость во время компиляции : вам нужна зависимость в CLASSPATH для компиляции артефакта. Они создаются потому, что у вас есть какая-то «ссылка» на зависимость, жестко запрограммированную в вашем коде, например, вызов new для некоторого класса, расширение или реализация чего-либо (прямо или косвенно) или вызов метода с использованием прямой reference.method() обозначение.

  • Зависимость во время выполнения : вам нужна зависимость в вашем CLASSPATH для запуска артефакта. Они создаются потому, что вы выполняете код, который обращается к зависимости (либо жестко закодированным способом, либо с помощью отражения, либо как угодно).

Хотя зависимость во время компиляции обычно подразумевает зависимость во время выполнения, вы можете иметь зависимость только во время компиляции. Это основано на том факте, что Java связывает зависимости класса только при первом доступе к этому классу, поэтому, если вы никогда не получите доступ к определенному классу во время выполнения, потому что путь кода никогда не пересекается, Java будет игнорировать и класс, и его зависимости.

Пример этого

В C.java (генерирует C.class):

package dependencies;
public class C { }

В A.java (генерирует класс A.):

package dependencies;
public class A {
    public static class B {
        public String toString() {
            C c = new C();
            return c.toString();
        }
    }
    public static void main(String[] args) {
        if (args.length > 0) {
            B b = new B();
            System.out.println(b.toString());
        }
    }
}

В этом случае A имеет зависимость во время компиляции от C до B, но она будет иметь зависимость во время выполнения от C, если вы передадите некоторые параметры при выполнении java dependencies.A, как JVM будет пытаться решить зависимость B от C только тогда, когда ей удастся выполнить B b = new B(). Эта функция позволяет вам предоставлять во время выполнения только зависимости классов, которые вы используете в путях кода, и игнорировать зависимости остальных классов в артефакте.

30 голосов
/ 24 ноября 2010

Простой пример - смотреть на API как API сервлетов.Чтобы ваши сервлеты компилировались, вам нужен servlet-api.jar, но во время выполнения контейнер сервлета обеспечивает реализацию API сервлета, поэтому вам не нужно добавлять servlet-api.jar в путь к классу времени выполнения.

24 голосов
/ 24 ноября 2010

Компилятору нужен правильный путь к классу для компиляции вызовов в библиотеку (зависимости времени компиляции)

JVM нужен правильный путь к классу для загрузки классов в библиотеке, которую вы вызываете (зависимости времени выполнения).

Они могут отличаться несколькими способами:

1) если ваш класс C1 вызывает библиотечный класс L1, а L1 вызывает библиотечный класс L2, то C1 имеет зависимость времени выполнения от L1 иL2, но только зависимость времени компиляции от L1.

2), если ваш класс C1 динамически создает интерфейс I1, используя Class.forName () или какой-то другой механизм, и реализующий класс для интерфейса I1 - это класс L1,тогда C1 имеет зависимость времени выполнения от I1 и L1, но только зависимость времени компиляции от I1.

Другие «косвенные» зависимости, которые одинаковы для времени компиляции и времени выполнения:

3) ваш класс C1 расширяет библиотечный класс L1, а L1 реализует интерфейс I1 и расширяет библиотечный класс L2: C1 зависит от времени компиляции от L1, L2 и I1.

4) у вашего класса C1 есть метод foo(I1 i1) и метод bar(L1 l1), где I1 - это интерфейс, а L1 - это класс, который принимает параметр, который является интерфейсом I1: C1 имеет зависимость времени компиляции от I1и L1.

По сути, чтобы сделать что-нибудь интересное, ваш класс должен взаимодействовать с другими классами и интерфейсами в пути к классам.Граф классов / интерфейсов, сформированный этим набором библиотек interfaces , дает цепочку зависимостей времени компиляции.Библиотека реализаций дает цепочку зависимостей во время выполнения. Обратите внимание, что цепочка зависимостей во время выполнения зависит от времени выполнения или медленна при сбое: если реализация L1 иногда зависит от создания экземпляра объектакласс L2, и этот класс создается только в одном конкретном сценарии, тогда нет никакой зависимости, кроме как в этом сценарии.

11 голосов
/ 24 ноября 2010

Java на самом деле ничего не связывает во время компиляции.Он только проверяет синтаксис, используя соответствующие классы, которые он находит в CLASSPATH.Только во время выполнения все будет собрано и выполнено на основе CLASSPATH в то время.

10 голосов
/ 24 ноября 2010

Зависимости времени компиляции - это только те зависимости (другие классы), которые вы используете напрямую в классе, который вы компилируете. Зависимости времени выполнения охватывают как прямые, так и косвенные зависимости класса, который вы запускаете. Таким образом, зависимости времени выполнения включают в себя зависимости зависимостей и любые зависимости отражения, такие как имена классов, которые есть в String, но используются в Class#forName().

1 голос
/ 01 февраля 2016

Для Java зависимость от времени компиляции - это зависимость вашего исходного кода.Например, если класс A вызывает метод из класса B, то A зависит от B во время компиляции, так как A должен знать о B (тип B) для компиляции.Хитрость здесь заключается в следующем: скомпилированный код еще не является полным и исполняемым кодом.Он включает заменяемые адреса (символы, метаданные) для источников, которые еще не скомпилированы или не существуют во внешних банках.Во время связывания эти адреса должны быть заменены реальными адресами в памяти.Чтобы сделать это правильно, должны быть созданы правильные символы / адреса.И это может быть сделано с типом класса (B).Я полагаю, что это главная зависимость во время компиляции.

Зависимость времени выполнения больше связана с фактическим потоком контроля.Это включает в себя фактические адреса памяти.Это зависимость, которая у вас есть, когда ваша программа работает.Здесь вам нужны детали класса B, такие как реализации, а не только информация о типе.Если класс не существует, вы получите RuntimeException и JVM завершит работу.

Обе зависимости, как правило, и не должны проходить в одном направлении.Это вопрос дизайна ОО.

В C ++ компиляция немного отличается (не только вовремя), но также имеет компоновщик.Таким образом, я думаю, этот процесс похож на Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...