为什么编译的Java类文件小比C编译的文件? [英] Why are compiled Java class files smaller than C compiled files?

查看:154
本文介绍了为什么编译的Java类文件小比C编译的文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么我们从编译.c文件,打印得到的.o文件你好,世界!比Java的.class文件也较大打印你好,世界!

I would like to know why the .o file that we get from compiling a .c file that prints "Hello, World!" is larger than a Java .class file that also prints "Hello, World!"?

推荐答案

Java使用字节code能独立于平台和precompiled,但字节code所使用的跨preTER而供应是足够紧凑,所以它是不一样的那台机器code,你可以在编译的C程序见。只是看看Java编译的全过程:

Java uses Bytecode to be platform independent and "precompiled", but bytecode is used by interpreter and is served to be compact enough, so it is not the same that machine code which you can see in compiled C program. Just take a look at the full process of Java compilation:

Java program  
-> Bytecode   
  -> High-level Intermediate Representation (HIR)   
    -> Middle-level Intermediate Representation (MIR)   
      -> Low-level Intermediate Representation (LIR)  
        -> Register allocation
          -> EMIT (Machine Code)

这是链Java程序机器code转型。正如你看到的字节code是远离机器code。我不能在互联网上的好东西找来向您展示真正的程序(一个例子)这条路,一切我发现是的这presentation ,在这里你可以看到每一个步骤如何改变code presentation。我希望这回答了你如何以及为什么编译的C程序和Java字节code是不同的。

this is the chain for Java Program to Machine code transformation. As you see bytecode is far away from machine code. I can't find in the Internet good stuff to show you this road on the real program (an example), everything I've found is this presentation, here you can see how each steps changes code presentation. I hope it answers you how and why compiled c program and Java bytecode are different.

更新:
这是字节code之后的所有步骤都是由JVM运行时根据其决定编译code(这是另一个故事...做的是JVM字节code间pretation之间的平衡其编译为本地平台相关的code)

UPDATE: All steps which are after "bytecode" are done by JVM in runtime depending on its decision to compile that code (that's another story... JVM is balancing between bytecode interpretation and its compiling to native platform dependent code)

终于找到很好的例子,从线性扫描寄存器分配采取了Java HotSpot的™客户端编译器(BTW良好的阅读理解什么是内部JVM回事)。试想一下,我们有Java程序:

Finally found good example, taken from Linear Scan Register Allocation for the Java HotSpot™ Client Compiler (btw good reading to understand what is going on inside JVM). Imagine that we have java program:

public static void fibonacci() {
  int lo = 0;
  int hi = 1;
  while (hi < 10000) {
    hi = hi + lo;
    lo = hi - lo;
    print(lo);
  }
}

那么它的字节code是:

then its bytecode is:

0:  iconst_0
1:  istore_0 // lo = 0
2:  iconst_1
3:  istore_1 // hi = 1
4:  iload_1
5:  sipush 10000
8:  if_icmpge 26 // while (hi < 10000)
11: iload_1
12: iload_0
13: iadd
14: istore_1 // hi = hi + lo
15: iload_1
16: iload_0
17: isub
18: istore_0 // lo = hi - lo
19: iload_0
20: invokestatic #12 // print(lo)
23: goto 4 // end of while-loop
26: return

每个命令需要1字节(JVM支持256的命令,但在实际上有小于数)+的参数。一起花费27个字节。我省略了所有阶段,而这里是准备执行机code:

each command takes 1 byte (JVM supports 256 commands, but in fact has less than that number) + arguments. Together it takes 27 bytes. I omit all stages, and here is ready to execute machine code:

00000000: mov dword ptr [esp-3000h], eax
00000007: push ebp
00000008: mov ebp, esp
0000000a: sub esp, 18h
0000000d: mov esi, 1h
00000012: mov edi, 0h
00000017: nop
00000018: cmp esi, 2710h
0000001e: jge 00000049
00000024: add esi, edi
00000026: mov ebx, esi
00000028: sub ebx, edi
0000002a: mov dword ptr [esp], ebx
0000002d: mov dword ptr [ebp-8h], ebx
00000030: mov dword ptr [ebp-4h], esi
00000033: call 00a50d40
00000038: mov esi, dword ptr [ebp-4h]
0000003b: mov edi, dword ptr [ebp-8h]
0000003e: test dword ptr [370000h], eax
00000044: jmp 00000018
00000049: mov esp, ebp
0000004b: pop ebp
0000004c: test dword ptr [370000h], eax
00000052: ret

它需要83(52进制+ 1个字节)字节的结果。

it takes 83 (52 in hex + 1 byte) bytes in result.

PS。我不考虑到联(被别人提及),以及compiledc和字节code文件头(可能他们也不同,我不知道如何与c是它的,但在字节code文件中的所有字符串都移动到特殊的头池,并在程序有用于头部​​等的位置。)

PS. I don't take into account linking (was mentioned by others), as well as compiledc and bytecode file headers (probably they are different too; I don't know how is it with c, but in bytecode file all strings are moved to special header pool, and in program there is used its "position" in header etc.)

UPDATE2:也许值得一提的,是Java的工作与栈(网上商店/ ILOAD命令),但基于x86和大多数其他平台的机器code与寄存器的作品。正如你所看到的机器code是寄存器的满这给了额外的大小来编译后的程序与更简单的基于堆栈的字节code比较。

UPDATE2: Probably worth to mention, that java works with stack (istore/iload commands), though machine code based on x86 and most other platform works with registers. As you can see machine code is "full" of registers and that gives extra size to the compiled program in comparing with more simple stack-based bytecode.

这篇关于为什么编译的Java类文件小比C编译的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆