>  Q&A  >  본문

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일 전351

모든 응답(5)나는 대답할 것이다

  • ringa_lee

    ringa_lee2017-04-18 09:23:50

    1. Java의 바이트코드에는 메소드의 프로토타입 정보가 포함되어 있으며 컴파일 시 클래스 파일이면 충분합니다.
    2. Java가 실행되면 클래스 경로에서 jar 파일을 찾은 다음 a를 찾습니다. /b는 jar 파일의 패키지 이름에 해당합니다. /c.class
    3, 이렇습니다

    회신하다
    0
  • 伊谢尔伦

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

    JVM에 대한 자세한 내용은 클래스 로딩 "심층 JVM 가상 머신"을 참조하세요.
    1.: 전체 클래스 이름은 클래스를 정의하며 각 클래스는 한 번 로드됩니다.
    2. 어떻게 찾는지 물어보시네요. 학급 이름과 비슷한 것 같아요.
    마지막 내용이 이해가 안 돼요

    회신하다
    0
  • 黄舟

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

    개인적으로 이해하는 바는 다음과 같습니다.
    1. c/C++로 컴파일된 라이브러리와 Java로 생성된 jar 패키지는 본질적으로 압축된 패키지일 뿐입니다. c/C++ 컴파일 프로세스는 Java가 클래스 파일을 생성하는 프로세스와 동일해야 합니다. 즉, 코드는 머신(또는 가상 머신)이 이해하고 실행할 수 있는 파일로 변환됩니다.
    2. JAVA 가상 머신은 클래스 파일을 로드합니다. 대상 클래스 파일을 메모리에 추가하면 클래스 정보는 "메서드 영역"에 배치되어야 합니다. 인스턴스화되면 참조는 스택에 있고 인스턴스는 힙에 있습니다(c/C++의 malloc 또는 new와 유사).
    3. 각 클래스는 클래스 로더 + 패키지 이름 + 클래스 이름의 세 부분을 통해 JVM에서 고유하게 식별됩니다.
    4. 더 나은 책에는 "Java Virtual Machine의 심층 이해"가 있습니다. 원칙 및 모범 사례';

    회신하다
    0
  • 怪我咯

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

    1. A.java가 xxx.jar 패키지에 의존하는 경우 컴파일 중에 클래스 경로에 xxx.jar을 포함해야 합니다(예: javac 명령). 컴파일러는 A.java를 컴파일할 때 xxx를 찾습니다. jar 패키지를 사용하여 A가 의존하는 클래스가 있는지, 의존하는 클래스에 해당 메서드가 있는지 등을 확인합니다. 이것이 올바른 프로토타입이 사용되었는지 확인한다는 것이 무슨 뜻인지 잘 모르겠습니다.

    2. Java에서는 패키지 이름에 해당하는 파일 시스템 구조가 있어야 합니다. 예를 들어 com.x.y 패키지에는 이에 해당하는 com/x/y/ 디렉터리가 있어야 합니다. 이 경로 정보는 컴파일 시와 실행 시 두 가지 측면에서 반영됩니다.
    컴파일과 실행 모두 클래스 경로를 지정해야 합니다. 이 클래스 경로는 운영 체제의 환경 변수 경로와 비교할 수 있습니다. 예를 들어 경로 환경 변수에 javac 명령을 추가하면 해당 디렉토리를 추가해야 합니다. javac은 경로에 위치해 있습니다.
    클래스 경로도 마찬가지입니다. 실행 중이든 컴파일 중이든 com.a.b.String과 같은 클래스를 참조하려면 먼저 해당 디렉토리 구조 com/a/b/가 있어야 합니다. com 폴더를 하드 디스크의 임의 디렉토리(예: D:/test 아래)에 넣을 수 있습니다. 그런 다음 클래스 경로에 D:/test를 추가해야 com.a.b.String을 참조하려는 경우 서버 또는 런타임은 이를 찾기 위해 클래스 경로에 지정된 디렉토리로 이동합니다. 패키지 이름에 따라 해당 디렉토리 구조를 찾으십시오.
    디렉토리 구조는 여기서의 역할을 반영합니다.

    3. jar 패키지의 이름은 걱정하지 마세요. jar 패키지는 실제로 zip 형식의 파일이고, jar 패키지도 클래스 경로에 추가되기 때문입니다. jar 패키지 디렉토리 구조, 패키지 이름과 클래스 위치 등을 결정합니다. Jar 패키지에 해당 클래스가 있는 한 jar 패키지 이름을 임의로 바꿀 수 있습니다.

    4. Java와 C/C++의 차이점은 Java는 Java 가상 머신에서 실행되므로 기본 메커니즘을 이해하면 가상 머신을 살펴볼 가능성이 높습니다. C/C++의 링크와 로딩은 자바의 클래스 로더(ClassLoader) 원리에 해당합니다. 이 분야에 대한 자세한 내용은 "Java Virtual Machine에 대한 심층적인 이해"(Zhou Zhiming) 또는 Oracle 공식 Java Virtual Machine 사양(jvms.pdf)을 참조하세요. 웹사이트.
    사실 포스터의 문제는 Java 언어 자체의 사양에 관한 것이라고 생각합니다. 이에 대해서는 일부 튜토리얼 책이나 Oracle의 공식 Java 언어 사양(jls.pdf)을 참조하면 됩니다. 이는 Oracle 공식 웹사이트의 Find it에서도 확인할 수 있습니다.

    회신하다
    0
  • 高洛峰

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

    "Java Virtual Machine 사양"의 5장: 5장. 로드, 링크 및 초기화를 참조하세요

    회신하다
    0
  • 취소회신하다