Home  >  Q&A  >  body text

java程序运行时是如何找到库函数并运行的?

题主是一名C/C++程序员,刚开始学习java。

疑惑如下:

  1. java没有头文件,当调用第三方包(无源码)的方法,编译器如何保证程序员使用了正确的原型呢?

  2. 定义包时,为了保证包名唯一,使用package a.b.c语法,包的类需要在文件系统的a/b/c目录下。但当其他java程序使用该包时,这个路径信息怎么在运行查找这个包时体现?

  3. 某c程序编译时依赖库liba.so,那么运行时系统必须提供库liba.so,但是java程序编译时使用abc.jar,但是运行时可以提供bcd.jar,只要bcd.jar里具有该java程序用到的类就行?(我自己瞎猜的,请问这个说法对不对?)

最后,java有没有类似于《链接、装载与库》这样的书籍,或者请大家推荐一些可以了解原理的书籍,能够解答这些困惑,中英文皆可。

感谢。


非常感谢大家的解答,试着将各位的回答总结整理如下:

  1. jar包里的class文件中含有文件原型。c/c++的libxxx.so/libxx.a中只有符号,没有原型,原型由头文件中提供;java的class文件中即含有原型信息。编译器只要解析class文件即可知道程序员是否使用了正确的原型。(@fredric_201 与 @心不在焉 )

  2. jar包即zip包,里面存在目录结构,该结构与包名结构完全一致(标准jar包,非android jar包)。(@心不在焉 与 @beanlam)

  3. 说法正确。java程序依赖的实际是class,jar包只是一组class的zip包,其命名无关紧要,因此可以任意修改。如果非要和c/C++进行对比,libxx.so类似于.class,而非jar包。(@心不在焉 与 @beanlam)

笔者在ubuntu机器上使用zipinfo查看openjdk自带的jar包,如下:

prife@droi: /usr/lib/jvm/java-7-openjdk-amd64/jre/lib
$ zipinfo rt.jar
...
-rw----     2.0 fat    24298 bl defN 15-Jul-24 08:17 java/lang/String.class
-rw----     2.0 fat     1734 bl defN 15-Jul-24 08:17 java/lang/Object.class

可以看到rt.jar包里具有跟包名完全一致的目录结构。

最后感谢大家推荐的书籍:

《深入理解java虚拟机》
《Java Virtual Machine Specification》

PS. 笔者之所以对第二点看到困惑,因为作为Android程序员,发现安卓的jar包里是只有dex文件,没有包名的目录结构。

再次感谢大家的解答。

PHP中文网PHP中文网2712 days ago352

reply all(5)I'll reply

  • ringa_lee

    ringa_lee2017-04-18 09:23:50

    1. Java’s bytecode contains the prototype information of the method. Just have the class file when compiling.
    2. When Java is running, look for the jar file from the classpath, and then look for the a/b/c.class corresponding to the package name in the jar file.
    3, it’s like this

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-18 09:23:50

    Read a book that explains JVM. For specific details, look at class loading, "In-depth JVM Virtual Machine".
    1.: The full class name defines a class, and each class is loaded once.
    2. Are you asking how to find it? I think it is similar to the full class name.
    I don’t understand the last one

    reply
    0
  • 黄舟

    黄舟2017-04-18 09:23:50

    My personal understanding is this:
    1. The library compiled by c/c++ and the jar package generated by java are not equivalent. The jar package is essentially just a compressed package; if you must make an analogy, c/c++ The compilation process should be equivalent to the process of Java generating class files, that is, the code is converted into files that the machine (or virtual machine) can understand and execute;
    2. The JAVA virtual machine loads the target class file into the memory, including the class information It should be placed in the "method area". When instantiated, the reference is on the stack and the instance is on the heap (similar to malloc or new in c/c++).
    3. Each class is uniquely identified in the JVM through the three parts of information: class loader + package name + class name;
    4. Better books include "In-depth Understanding of Java Virtual Machine" and "OSGI Principles and Best Practices" ;

    reply
    0
  • 怪我咯

    怪我咯2017-04-18 09:23:50

    1. If A.java depends on the xxx.jar package, you need to include xxx.jar in the classpath during compilation (such as the javac command). When the compiler compiles A.java, it will look for the xxx.jar package. , see if there is a class that A depends on, whether the class it depends on has corresponding methods, etc. Not sure if this is what you mean Make sure you use the correct prototype.

    2. Java requires that the package name must have a corresponding file system structure, such as com.x.y这个包,就必须有相应的com/x/y/目录与它对应。这个路径信息在两方面有体现,一个是编译的时候,一个是运行的时候。
    编译和运行都要指定classpath,可以把这个classpath类比成操作系统的环境变量path,比如我们把javac这个命令加到了path环境变量下,需要在把javac所在的目录加到path上。
    classpath也一样,无论在运行还是编译的时候,如果你要引用一个类,比如说是com.a.b.String,那么首先你得有对应的目录结构com/a/b/。你可以把com文件夹随便放在硬盘中的某个目录下,比如说放在D:/test下,那么你需要在classpath里加上D:/test. In this way, when com.a.b.String is referenced, the compiler or runtime will go to the directory specified by the classpath to find it. How to find it? According to the package name, and then find the corresponding directory structure.
    The directory structure reflects its role here.

    3. Don’t worry about the name of the jar package, because the jar package is actually a file in zip format, and the jar package will also be added to the classpath. What the Java virtual machine really cares about is the directory structure inside the jar package. With this To determine the package name and class location, etc. As long as the Jar package has a corresponding class, you can rename the jar package arbitrarily.

    4. The difference between Java and C/C++ is that Java runs on the Java virtual machine, so if you understand the underlying mechanism, you will most likely look at the virtual machine. The linking and loading of C/C++ correspond to the principle of class loader(ClassLoader) in Java. For information in this area, you can read "In-depth Understanding of Java Virtual Machine" (Zhou Zhiming), or Oracle's official Java Virtual Machine Specification(jvms.pdf), which can be found on the official website.
    Actually, I think the poster’s problem is more about the specifications of the Java language itself. For this, you can refer to some tutorial books, or Oracle’s official Java Language Specifications(jls.pdf), which can also be found on the Oracle official website.

    reply
    0
  • 高洛峰

    高洛峰2017-04-18 09:23:50

    Please refer to Chapter 5 of "Java Virtual Machine Specification": Chapter 5. Loading, Linking, and Initializing

    reply
    0
  • Cancelreply