从‘零’学JAVA(一)——简析Hello Java

一、引言

众所周知,在计算机的世界里,唯一能被识别的只有0与1这样的二进制文件。但是利用二进制来与计算机打交道,是非常麻烦的一件事,于是一代代程序员总结出两种可行方案来以简洁,易懂的编程语言驱使计算机。第一种方案,解释执行:和同声翻译一个原理,对于源代码,提交一行,解释器则解释一行;第二种方案,编译执行:和著作译本类似,先将整个源代码编译为硬件可执行语言,再提交。而我们的java语言则介于二者之间,属于先编译再解释,通过jvm,从java编译为class文件,再解释为机器码。

那么class文件结构怎样?class文件又是怎么加载到jvm,接下来我们将以Hello Java为案列,逐一分析。

二、案列呈现

HelloJava:

package com.syr.test;

/**
 * @author sunyiran
 * @createTime 2019-04-03 22:01
 */
public class HelloJava implements HelloJavaInterface {

    private static final String HELLO_JAVA = "Hello Java";

    @Override
    public String getContent() {
        return HELLO_JAVA;
    }

    public static void main(String[] args) {
        System.out.println(new HelloJava().getContent());
    }

}

先编译:Javac HelloJava.java,再解释执行:java HelloJava

OK,显示成功:

三、基础知识准备

3.1 安装classpy

第一步:在本地,git clone https://github.com/zxh0/classpy

第二步:安装gradle,https://jingyan.baidu.com/article/00a07f38706f0b82d028dcf3.html

第三步:进入classpy安装目录,执行gradlew run

出现如下结果,则OK

3.2 查看Hello Java的class结构

3.3 class结构基础

Class文件是一组以8个字节为基本单位的二进制文件,每项数据组以严格顺序排列,中间不包含任何分隔符和占位符。Class文件格式采用类C的伪代码结构,它主要有无符号数和表两种数组结构。

无符号数,按值大小,分为1字节(u1),2字节(u2),3字节(u3),4字节(u4)四种。无符号数从内容上说,可以理解为一个个键值对,但是实质上在class中只存有它的值,内容区分主要依靠严格的顺序结构。

表,是多个无符号数和其他表组成,如同java中的Map,其值可以是Map,是具有层次关系的复合结构。

在3.2中,左侧所描述的结构,从上往下分析:

magic:魔数,是class文件的类型标识符,u4类型,其值cafebaby(咖啡宝贝)为定值。

minor_version:是class文件的次版本号,u2类型,与主版本号,共同确保jvm对于不同的jdk能向下兼容执行。

major_version:是class文件的主版本号,u2类型,这里为52=3*16+4。

constant_pool_count:引用的常量数目,u2类型,从1开始计数。

constant_pool:引用常量详情,表结构,每个数据项,都有tag,依靠tag和constant_pool_count来确定需要多少字节来描述常量引用详情。

access_flags:访问权限标识符,u2类型,ACC_PUBLIC表示public权限。

this_class:class文件地址,u2类型,为包名中/代替.再加上/类名。

supper_class:父类class文件地址,u2类型,默认为Object。

interfaces_count:实现的接口数目,u2类型。

interfaces:接口详情。

fields_count:类中字段属性数目,u2类型。

fields:属性详情。

methods_count:方法数目,u2类型。

methods:方法详情,<init>代表构造方法。

attributes_count:类的基本元信息数目,u2类型

attributes:类的元信息。

3.4 Class的加载过程

一个class对象,它的整个生命周期分为:加载,验证,准备,解析,初始化,使用,卸载,共七个阶段,其中前五个阶段为class的加载过程。

加载,是以双亲委派模式根据class文件全路径读取进jvm;验证,是判断文件是否为class类型,是否jvm能兼容运行等;准备,为类的静态变量分配空间,并赋予初始值(非指定值);解析,将常量池符号引用解析为直接引用;初始化,为静态变量赋予指定值,如果是静态代码块,则直接执行。

3.5 JVM内存分配

JVM内存主要分为虚拟机栈,本地方法栈,方法区,堆,程序计数器,其中堆和方法区为所有线程共享。程序计数器,用来表示当前对象运行行数;本地方法栈,指向本地native方法;方法区,存有静态变量,常量信息,类信息等元数据(虚拟机并未规定一定存在方法区,jdk1.8后元数据放入了堆内存的元空间);堆,存放创建的对象;虚拟机栈,存线程运行时的临时变量。

四、Hello Java完整解析

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值