Подтвердить что ты не робот

Время компиляции vs Время выполнения Зависимость - Java

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

4b9b3361

Ответ 1

  • Зависимость времени компиляции. Вам нужна зависимость в вашем CLASSPATH для компиляции вашего артефакта. Они создаются, потому что у вас есть какая-то "ссылка" на зависимость, жестко закодированную в вашем коде, например вызов new для какого-либо класса, расширение или реализацию чего-либо (прямо или косвенно) или вызов метода с использованием прямого reference.method() обозначение.

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

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

Пример этого

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

package dependencies;
public class C { }

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

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(). Эта функция позволяет обеспечить во время выполнения только зависимости классов, которые вы используете в своих кодах, и игнорировать зависимости остальных классов в артефакте.

Ответ 2

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

Ответ 3

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

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.

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

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

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