Disabling compile-time dependency checking when compiling Java classes

后端 未结 8 1139
一整个雨季
一整个雨季 2020-12-28 09:10

Consider the following two Java classes:

a.) class Test { void foo(Object foobar) { } }

b.) class Test { void foo(pkg.not.in.classpath.FooBar foobar) { } }
         


        
相关标签:
8条回答
  • 2020-12-28 09:44

    Can you give any example for which it would be technically impossible to generate a valid Java class file without performing compile time dependency checking?

    Consider this code:

    public class GotDeps {
      public static void main(String[] args) {
        int i = 1;
        Dep.foo(i);
      }
    }
    

    If the target method has the signature public static void foo(int n), then these instructions will be generated:

    public static void main(java.lang.String[]);
      Code:
       0:   iconst_1
       1:   istore_1
       2:   iload_1
       3:   invokestatic    #16; //Method Dep.foo:(I)V
       6:   return
    

    If the target method has the signature public static void foo(long n), then the int will be promoted to a long prior to the method invocation:

    public static void main(java.lang.String[]);
      Code:
       0:   iconst_1
       1:   istore_1
       2:   iload_1
       3:   i2l
       4:   invokestatic    #16; //Method Dep.foo:(J)V
       7:   return
    

    In this case, it would not be possible to generate the invocation instructions or how to populate the CONSTANT_Methodref_info structure referred to in the class constant pool by the number 16. See the class file format in the VM spec for more details.

    0 讨论(0)
  • 2020-12-28 09:51

    It would be a violation of the JLS to compile a class without looking at the type signatures of the classes it depends on. No conformant Java compiler would allow you to do this.

    However ... it is possible to do something rather similar. Specifically, if we have a class A and a class B that depends on A, it is possible to do the following:

    1. Compile A.java
    2. Compile B.java against A.class.
    3. Edit A.java to change it in an incompatible way.
    4. Compile A.java, replacing the old A.class.
    5. Run a Java application using B.class and the new (incompatible) A.class.

    If you do this, the application will fail with a IncompatibleClassChangeError when the class loader notices the signature incompatibility.

    Actually, this illustrates why compiling ignoring dependencies would be a bad idea. If you run an application with inconsistent bytecode files, (only) the first inconsistency detected will be reported. So if you have lots of inconsistencies, you will need to run your application lots of times to "detect" them all. Indeed, if there is any dynamic loading of classes (e.g. using Class.forName()) in the application or any of its dependencies, then some of these problems may not show up immediately.

    In summary, the cost of ignoring dependencies at compile time would be slower Java development and less reliable Java applications.

    0 讨论(0)
提交回复
热议问题