java - 256 个 java 字节码如何转换为 java 所做的一切(图形、IO 等)

标签 java bytecode

我正在查看 java 字节码列表和维基百科,它们似乎都是基本操作(分支、推送、弹出、转换等)。许多文章都使用这些基本示例。但是当我从控制台读取一行或者创建一个新的 JButton 时会发生什么?打开端口的字节码在哪里?

我相信我看到了一些“进行系统调用”的东西(虽然我今天没有找到它,浏览了几次列表)。这些“特殊”调用是否有自己的代码,由 VM 直接委托(delegate)(技术上不知道怎么说)给操作系统?我知道有一些方法可以打开字节码,但我正在寻找一般解释,而不是学习高级字节码的周数。

最佳答案

没有用于打开端口或在屏幕上绘制图形的字节代码。有执行这些任务的类。这些类具有 native 方法,这些方法是用 C(或任何其他可以编译为 native 库的语言)编写的方法,并且由于它们是 native 的,它们可以访问操作系统的网络和 graphcis 库来执行这些任务。所以你正在实例化这些类并调用它们的一些方法。 Java 字节码提供了用于实例化类和调用对象方法的字节码。如果 JVM 发现这是一个本地方法,它将调用属于该方法的本地代码,而该本地代码几乎可以执行 C 或 C++ 程序可以执行的任何操作。

例如,如果您调用 System.out.println在 Java 中,大致会发生以下情况:

System是一个带有静态变量的类 out .此变量指向 java.io.PrintStream 类型的对象在你的 main 之前 JVM 已经创建了它方法曾经被执行过。 out变量初始化如下:

FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));

setOut0方法定义为

private static native void setOut0(PrintStream out);

这意味着 setOut0 是一个本地方法,用 C 或其他一些可以编译并链接到本地​​库的语言编写,尽管至少 Java 和这个库之间的接口(interface)通常是用 C 编写的。

Java 将在所有加载的库中搜索名称为 Java_java_lang_System_setOut0 的符号(在这种情况下,符号表示函数名称) , 这是 Java_ClassName_MethodName并调用它。我为该方法找到的示例 C 代码如下所示:

JNIEXPORT void JNICALL
Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream)
{
    jfieldID fid =
        (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");
    if (fid == 0)
        return;
    (*env)->SetStaticObjectField(env,cla,fid,stream);
}

但这不是真正的魔法,真正的魔法发生在别处。 PrintStream.write()电话 BufferedWriter.write() .此方法再次调用 OutputStreamWriter.write() (不是直接的,但迟早会在那里结束)并且此方法调用 StreamEncoder.write() .哇,越来越难追踪那个电话了。 StreamEncoder电话 BufferedOutputStream.write() ,这个叫FileOutputStream.write()这个叫FileOutputStream.writeBytes()最后,我们终于到了! FileOutputStream.writeBytes()是一个本地方法。它看起来像这样:

JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_writeBytes(JNIEnv *env,
    jobject this, jbyteArray bytes, jint off, jint len) {
    writeBytes(env, this, bytes, off, len, fos_fd);
}

所以它调用了一个名为 writeBytes 的函数,这个函数看起来会根据您的操作系统而有所不同,例如无论是 Windows、Linux 还是 OS X。在 UNIX/Linux 系统上,此函数可能会调用另一个函数(等等),但某处是一个简单的 C 函数调用,用于将某些内容写入 C FILE *。流或文件描述符(在 C 中只是一个 int)。所以它可能是 printf()/fprintf()puts()/fputs()写入 stdout 的调用或 write()写入 STDOUT_FILENO 的调用.在 Windows 中,它通常是对 WriteFile() 的调用, 尽管它也可以是 printf()/fprintf() (这些是 C 标准函数,所有平台都必须支持它们)。

关于java - 256 个 java 字节码如何转换为 java 所做的一切(图形、IO 等),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14430749/

相关文章:

java - 我如何将保存的项目添加到 Flutter 中的 Collection 夹部分?

java - 编辑引用的项目配置而不重建

python3 -O file.py 没有创建 file.pyo

java - 类文件中的注释存储在哪里

java - JAX-RS MessageBodyReader

java - 为什么我的 catch block 永远循环?

java - .length 无法解析或不是字段

java - 如何检查java方法的字节码长度

java - 用动态生成的类替换反射调用

python - 为什么在导入时会创建 .pyc 文件?