JAVA-ASM学习笔记之java字节码简介

简介: 前言 由于之前接触了集团的故障演练平台monkeyking,对JavaAgent与ASM产生了兴趣。前段时间稍微总结了下JavaAgent的简单内容《JavaAgent学习笔记》。这次则想学习一下ASM(Java字节码操纵框架)。但是在学习的过程中,发现一直对类似如下的代码持续懵逼中,看来想要了解ASM,还是得学下JAVA字节码。 static ClassWriter createCl

前言

由于之前接触了集团的故障演练平台monkeyking,对JavaAgent与ASM产生了兴趣。前段时间稍微总结了下JavaAgent的简单内容《JavaAgent学习笔记》。这次则想学习一下ASM(Java字节码操纵框架)。但是在学习的过程中,发现一直对类似如下的代码持续懵逼中,看来想要了解ASM,还是得学下JAVA字节码。

    static ClassWriter createClassWriter(String className) {
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        //声明一个类,使用JDK1.8版本,public的类,父类是java.lang.Object,没有实现任何接口  
        cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);
        //初始化一个无参的构造函数  
        MethodVisitor constructor = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        constructor.visitVarInsn(Opcodes.ALOAD, 0);
        //执行父类的init初始化  
        constructor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
        //从当前方法返回void    
        constructor.visitInsn(Opcodes.RETURN);
        constructor.visitMaxs(1, 1);
        constructor.visitEnd();
        return cw;
    }

class文件结构

public class Tester {
    private int intfiled = 1;
    private String strfiled = "test";
    public void run() {
        System.out.println("This is my first ASM test");
    }
    public void loop(){
        List<String> list = new ArrayList<>();
    }

} 

首先我们将以上代码使用javap -verbose Tester指令解析该类文件,将会得到以下内容,然后我们再根据class文件结构一起来研究一下。

Classfile /Users/archersblood/ideaworkspace/test/target/classes/Tester.class
  Last modified Dec 15, 2017; size 816 bytes
  MD5 checksum bb7e0325a8414bf572a09f35d0a36b24
  Compiled from "Tester.java"
public class Tester
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #11.#31        // java/lang/Object."<init>":()V
   #2 = Fieldref           #10.#32        // Tester.intfiled:I
   #3 = String             #33            // test
   #4 = Fieldref           #10.#34        // Tester.strfiled:Ljava/lang/String;
   #5 = Fieldref           #35.#36        // java/lang/System.out:Ljava/io/PrintStream;
   #6 = String             #37            // This is my first ASM test
   #7 = Methodref          #38.#39        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #8 = Class              #40            // java/util/ArrayList
   #9 = Methodref          #8.#31         // java/util/ArrayList."<init>":()V
  #10 = Class              #41            // Tester
  #11 = Class              #42            // java/lang/Object
  #12 = Utf8               intfiled
  #13 = Utf8               I
  #14 = Utf8               strfiled
  #15 = Utf8               Ljava/lang/String;
  #16 = Utf8               <init>
  #17 = Utf8               ()V
  #18 = Utf8               Code
  #19 = Utf8               LineNumberTable
  #20 = Utf8               LocalVariableTable
  #21 = Utf8               this
  #22 = Utf8               LTester;
  #23 = Utf8               run
  #24 = Utf8               loop
  #25 = Utf8               list
  #26 = Utf8               Ljava/util/List;
  #27 = Utf8               LocalVariableTypeTable
  #28 = Utf8               Ljava/util/List<Ljava/lang/String;>;
  #29 = Utf8               SourceFile
  #30 = Utf8               Tester.java
  #31 = NameAndType        #16:#17        // "<init>":()V
  #32 = NameAndType        #12:#13        // intfiled:I
  #33 = Utf8               test
  #34 = NameAndType        #14:#15        // strfiled:Ljava/lang/String;
  #35 = Class              #43            // java/lang/System
  #36 = NameAndType        #44:#45        // out:Ljava/io/PrintStream;
  #37 = Utf8               This is my first ASM test
  #38 = Class              #46            // java/io/PrintStream
  #39 = NameAndType        #47:#48        // println:(Ljava/lang/String;)V
  #40 = Utf8               java/util/ArrayList
  #41 = Utf8               Tester
  #42 = Utf8               java/lang/Object
  #43 = Utf8               java/lang/System
  #44 = Utf8               out
  #45 = Utf8               Ljava/io/PrintStream;
  #46 = Utf8               java/io/PrintStream
  #47 = Utf8               println
  #48 = Utf8               (Ljava/lang/String;)V
{
  public Tester();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_1
         6: putfield      #2                  // Field intfiled:I
         9: aload_0
        10: ldc           #3                  // String test
        12: putfield      #4                  // Field strfiled:Ljava/lang/String;
        15: return
      LineNumberTable:
        line 4: 0
        line 5: 4
        line 6: 9
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      16     0  this   LTester;

  public void run();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #6                  // String This is my first ASM test
         5: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 8: 0
        line 9: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   LTester;

  public void loop();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #8                  // class java/util/ArrayList
         3: dup
         4: invokespecial #9                  // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: return
      LineNumberTable:
        line 11: 0
        line 12: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   LTester;
            8       1     1  list   Ljava/util/List;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            8       1     1  list   Ljava/util/List<Ljava/lang/String;>;
}
SourceFile: "Tester.java"

还有使用sublime打开Tester.java看到它的十六进制字节码内容:

cafe babe|0000 0034|0031 0a|00 0b|00 1f|09
000a 0020 0800 2109 000a 0022 0900 2300
2408 0025 0a00 2600 2707 0028 0a00 0800
1f07 0029 0700 2a01 0008 696e 7466 696c
6564 0100 0149 0100 0873 7472 6669 6c65
6401 0012 4c6a 6176 612f 6c61 6e67 2f53
7472 696e 673b 0100 063c 696e 6974 3e01
0003 2829 5601 0004 436f 6465 0100 0f4c
696e 654e 756d 6265 7254 6162 6c65 0100
124c 6f63 616c 5661 7269 6162 6c65 5461
626c 6501 0004 7468 6973 0100 084c 5465
7374 6572 3b01 0003 7275 6e01 0004 6c6f
6f70 0100 046c 6973 7401 0010 4c6a 6176
612f 7574 696c 2f4c 6973 743b 0100 164c
6f63 616c 5661 7269 6162 6c65 5479 7065
5461 626c 6501 0024 4c6a 6176 612f 7574
696c 2f4c 6973 743c 4c6a 6176 612f 6c61
6e67 2f53 7472 696e 673b 3e3b 0100 0a53
6f75 7263 6546 696c 6501 000b 5465 7374
6572 2e6a 6176 610c 0010 0011 0c00 0c00
0d01 0004 7465 7374 0c00 0e00 0f07 002b
0c00 2c00 2d01 0019 5468 6973 2069 7320
6d79 2066 6972 7374 2041 534d 2074 6573
7407 002e 0c00 2f00 3001 0013 6a61 7661
2f75 7469 6c2f 4172 7261 794c 6973 7401
0006 5465 7374 6572 0100 106a 6176 612f
6c61 6e67 2f4f 626a 6563 7401 0010 6a61
7661 2f6c 616e 672f 5379 7374 656d 0100
036f 7574 0100 154c 6a61 7661 2f69 6f2f
5072 696e 7453 7472 6561 6d3b 0100 136a
6176 612f 696f 2f50 7269 6e74 5374 7265
616d 0100 0770 7269 6e74 6c6e 0100 1528
4c6a 6176 612f 6c61 6e67 2f53 7472 696e
673b 2956 0021 000a 000b 0000 0002 0002
000c 000d 0000 0002 000e 000f 0000 0003
0001 0010 0011 0001 0012 0000 0042 0002
0001 0000 0010 2ab7 0001 2a04 b500 022a
1203 b500 04b1 0000 0002 0013 0000 000e
0003 0000 0004 0004 0005 0009 0006 0014
0000 000c 0001 0000 0010 0015 0016 0000
0001 0017 0011 0001 0012 0000 0037 0002
0001 0000 0009 b200 0512 06b6 0007 b100
0000 0200 1300 0000 0a00 0200 0000 0800
0800 0900 1400 0000 0c00 0100 0000 0900
1500 1600 0000 0100 1800 1100 0100 1200
0000 5300 0200 0200 0000 09bb 0008 59b7
0009 4cb1 0000 0003 0013 0000 000a 0002
0000 000b 0008 000c 0014 0000 0016 0002
0000 0009 0015 0016 0000 0008 0001 0019
001a 0001 001b 0000 000c 0001 0008 0001
0019 001c 0001 0001 001d 0000 0002 001e


Magic Number

     首先是魔数,一共4字节,而且固定不变,它的值是 0XCAFE BABE,用来标明是class文件类型,为了保证文件的安全性,将文件类型写在文件内部来保证不被篡改。
                  
    
      CAFE BABE,看来是当时开发者的恶趣味吧

Version

    Version字段分为minor_verion(主版本)和major_version(次版本),比如,我们使用java -version

java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

其中1.8为主版本,0_121为次版本,然后我们在org.objectweb.asm.Opcodes可以看到各主版本的数值

    int V1_1 = 3 << 16 | 45;
    int V1_2 = 0 << 16 | 46;
    int V1_3 = 0 << 16 | 47;
    int V1_4 = 0 << 16 | 48;
    int V1_5 = 0 << 16 | 49;
    int V1_6 = 0 << 16 | 50;
    int V1_7 = 0 << 16 | 51;
    int V1_8 = 0 << 16 | 52;
    int V1_9 = 0 << 16 | 53;

由于我使用的是maven工程,pom设置了jdk版本为1.8。所以对应就是主版本数值为52,对应的字节码0000 0034,3*16+4=52。

Constant Pool

常量池是Class文件中的资源仓库。常量池中主要存储2大类常量:字面量和符号引用。字面量如文本字符串的常量值等等,而符号引用如类和接口的全局限定名,字段的名称和描述符,方法的名称和描述符。简单的说字面量是值,符号引用是名称。

常量池的大小我们可以看到是0x0031,为3*16+1 = 49,然后有效值-1。刚好就是我们类解析之后的结果48个常量值。接着是0x0a,值是10,说明是tag为10的Methodref类型的数据。我们也可以结合之前对Tester.class文件的类解析的结果对照来理解常量池。

   #1 = Methodref          #11.#31        // java/lang/Object."<init>":()V
  #11 = Class              #42            // java/lang/Object
  
  #16 = Utf8               <init>
  #17 = Utf8               ()V
  
  #31 = NameAndType        #16:#17        // "<init>":()V
  
  #42 = Utf8               java/lang/Object

比如第一行,Methodref类型的数据,包含的11(0x000b)和31(ox001f=16+15)两个索引项,11索引指向Class,表明这个init方法是Object的,并且再次指向42的该类的全局限定名java/lang/Object。接着另一部分,31指向一个NameAndType(字段或方法描述),然后 NameAndType的方法名称指向16表明是一个类初始化方法,17的指向“()V”表示是个无参方法,如果是有参数,则在“()”放入参数类型全局限定名。然后是0x09,说明是Fieldref,然后依次类推。接着是一些UTF-8类型的,比如:“<init>”,java字节码保存的是十六进制的UTF8码,可以用以下代码进行转码,得出:3C696E69743E。这段字节码之后的01 0003 2829 56 则说明是tag为1的UTF-8,长度为3,内容是282956,正好是“()V”。最后的常量是(Ljava/lang/String;)V,值为284C6A6176612F6C616E672F537472696E673B2956,如下图。至此,常量池结束。


    public static void main(String[] args) throws Exception {
        String str = "<init>";
        printHexString(str.getBytes());
    }

    public static void printHexString(byte[] b) {
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            System.out.print(hex.toUpperCase());
        }
    }​

另外,在jdk7开始,又引入了以下三种。
CONSTANT_MethodHandle_info
CONSTANT_MethodType_info
CONSTANT_InvokeDynamic_info

Access Tag

常量池结束之后是访问标记符0x0021,ACC_PUBLIC(0x0001)+ACC_SUPER (0x0020)。public大家都懂,super在这里不做详细介绍,有兴趣的话可以可以看一下这篇文章《ACC_SUPER和早期的invokespecial》

    int ACC_PUBLIC = 0x0001; // class, field, method
    int ACC_PRIVATE = 0x0002; // class, field, method
    int ACC_PROTECTED = 0x0004; // class, field, method
    int ACC_STATIC = 0x0008; // field, method
    int ACC_FINAL = 0x0010; // class, field, method, parameter
    int ACC_SUPER = 0x0020; // class
    int ACC_SYNCHRONIZED = 0x0020; // method
    int ACC_OPEN = 0x0020; // module
    int ACC_TRANSITIVE = 0x0020; // module requires
    int ACC_VOLATILE = 0x0040; // field
    int ACC_BRIDGE = 0x0040; // method
    int ACC_STATIC_PHASE = 0x0040; // module requires
    int ACC_VARARGS = 0x0080; // method
    int ACC_TRANSIENT = 0x0080; // field
    int ACC_NATIVE = 0x0100; // method
    int ACC_INTERFACE = 0x0200; // class
    int ACC_ABSTRACT = 0x0400; // class, method
    int ACC_STRICT = 0x0800; // method
    int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
    int ACC_ANNOTATION = 0x2000; // class
    int ACC_ENUM = 0x4000; // class(?) field inner
    int ACC_MANDATED = 0x8000; // parameter, module, module *
    int ACC_MODULE = 0x8000; // class

The class name

这个类文件的the class name 部分的值是0x000a。对应常量池索引为10。

  #10 = Class              #41            // Tester
  #41 = Utf8               Tester

Super class name

这个类文件的super class name 部分的值是0x000b。对应常量池索引为11。

  #11 = Class              #42            // java/lang/Object
  #42 = Utf8               java/lang/Object

Interface

这部分数据为0x0000,说明未实现任何接口。

Fields

private int intfiled = 1;
private String strfiled = "test";

 
这部分数据起始为0x0002,说明是有2个字段。下图是field的结构图 。首先第一个fields结构体是 开头是access_flags值为0x0002,说明是private,然后是name_index0x000c,名称指向常量池12,“intfiled”。接着是descriptor0x000d,指向13 “I”,说明是这个字段是整数类型。接着是属性数0x0000,说明没有属性值。接着是第二个字段。开头是access_flags值依旧为0x0002,说明是private,然后是name_index0x000e,名称指向常量池14为“strfiled”。接着是descriptor0x000f,执向15“Ljava/lang/String”,说明这个字段是个String。然后又是0x0000,说明没有属性值。

Method


然后是麻烦的Method区域,这里放置的是这个类的所有方法。它的结构体与字段相同。首先看到的是0x0003,说明这个类共3个方法。一个默认的init(构造方法)还有run()与loop()。

public Tester() {
}

public void run() {
System.out.println("This is my first ASM test");
}

public void loop() {
new ArrayList();
}

第一个方法。开头是accessflags值为0x0001,说明是public,然后是name_index0x0010,名称指向常量池16 "<init>",  接着是descriptor0x00011,指向17 “()V”,说明是这个无参方法。接着是属性数0x0001,说明有1个属性。然后根据这个属性的结构体。name_index是0x0012,指向18“code”,然后0x0000 0042,说明code属性长度是4*16+2=66。code部分解析更加复杂,其结构体如下图。具体解析这里不再详细介绍(里面包含了操作符之类的信息)。
attribute:  code: 
第二个方法。开头是accessflags值为0x0001,说明是public,然后是name_index0x0017,名称指向常量池23 "run",  接着是descriptor0x00011,指向17 “()V”,说明是这个无参方法。接着是属性数0x0001,说明有1个属性。然后根据这个属性的结构体。name_index是0x0012,指向18“code”,然后是0x0000 0037,说明长度是3*16+7 = 55(u1)
第三个方法。开头是accessflags值为0x0001,说明是public,然后是name_index0x0018,名称指向常量池24 "loop",  接着是descriptor0x00011,指向17 “()V”,说明是这个无参方法。接着是属性数0x0001,说明有1个属性。然后根据这个属性的结构体。name_index是0x0012,指向18“code”,然后是0x0000 0053,说明长度是5*16+3 = 83(u1)

Attributes

这个字段一般是记录文件属性的。它的结构为

信息开头是0x0001,说明是数组长度为1,然后是0x001d,索引为29,常量池指向"SourceFile", 然后是长度0x0000 0002,最后就是0x001e,索引为30,常量池内容为“Tester.java”。这样一个.class文件就解析完毕了。


经过完整的解析,一个.class文件的结构就清晰展现了出来。

cafe babe                                		魔数
0000 0034                                		版本
0031  											常量池
	0a00 0b00 1f09                       
	000a 0020 0800 2109 000a 0022 0900 2300
	2408 0025 0a00 2600 2707 0028 0a00 0800
	1f07 0029 0700 2a01 0008 696e 7466 696c
	6564 0100 0149 0100 0873 7472 6669 6c65
	6401 0012 4c6a 6176 612f 6c61 6e67 2f53
	7472 696e 673b 0100 063c 696e 6974 3e01
	0003 2829 5601 0004 436f 6465 0100 0f4c
	696e 654e 756d 6265 7254 6162 6c65 0100
	124c 6f63 616c 5661 7269 6162 6c65 5461
	626c 6501 0004 7468 6973 0100 084c 5465
	7374 6572 3b01 0003 7275 6e01 0004 6c6f
	6f70 0100 046c 6973 7401 0010 4c6a 6176
	612f 7574 696c 2f4c 6973 743b 0100 164c
	6f63 616c 5661 7269 6162 6c65 5479 7065
	5461 626c 6501 0024 4c6a 6176 612f 7574
	696c 2f4c 6973 743c 4c6a 6176 612f 6c61
	6e67 2f53 7472 696e 673b 3e3b 0100 0a53
	6f75 7263 6546 696c 6501 000b 5465 7374
	6572 2e6a 6176 610c 0010 0011 0c00 0c00
	0d01 0004 7465 7374 0c00 0e00 0f07 002b
	0c00 2c00 2d01 0019 5468 6973 2069 7320
	6d79 2066 6972 7374 2041 534d 2074 6573
	7407 002e 0c00 2f00 3001 0013 6a61 7661
	2f75 7469 6c2f 4172 7261 794c 6973 7401
	0006 5465 7374 6572 0100 106a 6176 612f
	6c61 6e67 2f4f 626a 6563 7401 0010 6a61
	7661 2f6c 616e 672f 5379 7374 656d 0100
	036f 7574 0100 154c 6a61 7661 2f69 6f2f
	5072 696e 7453 7472 6561 6d3b 0100 136a
	6176 612f 696f 2f50 7269 6e74 5374 7265
	616d 0100 0770 7269 6e74 6c6e 0100 1528
	4c6a 6176 612f 6c61 6e67 2f53 7472 696e
	673b 2956 
0021 											访问标记符
000a                                            类名
000b 											父类名
0000                							被实现接口
0002 											字段
	 0002 000c 000d 0000 
	 0002 000e 000f 0000 
0003											方法
	 0001 0010 0011 0001 0012 0000 0042 0002
	 0001 0000 0010 2ab7 0001 2a04 b500 022a
     1203 b500 04b1 0000 0002 0013 0000 000e
	 0003 0000 0004 0004 0005 0009 0006 0014
     0000 000c 0001 0000 0010 0015 0016 0000

	 0001 0017 0011 0001 0012 0000 0037 0002
	 0001 0000 0009 b200 0512 06b6 0007 b100
     0000 0200 1300 0000 0a00 0200 0000 0800
     0800 0900 1400 0000 0c00 0100 0000 0900
	 1500 1600 00

       00 0100 1800 1100 0100 1200 0000 5300 
     0200 0200 0000 09bb 0008 59b7 0009 4cb1 
     0000 0003 0013 0000 000a 0002 0000 000b 
     0008 000c 0014 0000 0016 0002 0000 0009 
     0015 0016 0000 0008 0001 0019 001a 0001 
     001b 0000 000c 0001 0008 0001
     0019 001c 
0001                                       		类属性
	 0001 001d 0000 0002 001e

 

目录
相关文章
|
2月前
|
Java
Java 数组学习笔记
本文整理Java数组常用操作:遍历、求和、查找、最值及二维数组行求和等典型练习,涵盖静态初始化、元素翻倍、去极值求平均等实例,帮助掌握数组基础与应用。
|
2月前
|
小程序 Java 知识图谱
Java 学习笔记 —— BMI & BMR 计算器
这是一个使用 Java 编写的 BMI 与 BMR 计算器小程序,可输入年龄、性别、身高和体重,计算身体质量指数(BMI)和基础代谢率(BMR),并输出健康评估结果。通过该项目,掌握了 Java 的输入处理、数据验证、条件判断、数学运算及格式化输出等基础知识,是 Java 初学者的理想练习项目。
|
3月前
|
自然语言处理 前端开发 算法
Java编译器优化秘籍:字节码背后的IR魔法与常见技巧
编译器将源代码转换为机器码的过程中,会经历多个中间表达形式(IR)的转换与优化。前端生成高级IR(HIR),后端将其转为低级IR(LIR)并进行机器相关优化。Java编译流程包括源码到字节码、再由即时编译器转换为内部HIR(如SSA图)、优化后生成LIR,最终编译为机器码。常见优化技术包括常量折叠、值编号、死代码消除、公共子表达式消除等,旨在提升程序性能与执行效率。
150 0
|
4月前
|
人工智能 安全 Java
Go与Java泛型原理简介
本文介绍了Go与Java泛型的实现原理。Go通过单态化为不同类型生成函数副本,提升运行效率;而Java则采用类型擦除,将泛型转为Object类型处理,保持兼容性但牺牲部分类型安全。两种机制各有优劣,适用于不同场景。
169 24
|
4月前
|
人工智能 Java
java中static关键字简介
`static`关键字用于修饰类的成员变量和方法,使其属于类而非对象。静态成员可通过类名直接访问,无需实例化对象。静态方法只能访问静态成员,不能直接访问非静态成员或使用`this`关键字。此外,静态代码块在类首次加载时执行且仅执行一次,适用于初始化操作。
183 0
|
5月前
|
Java API 微服务
2025 年 Java 从入门到精通学习笔记全新版
《Java学习笔记:从入门到精通(2025更新版)》是一本全面覆盖Java开发核心技能的指南,适合零基础到高级开发者。内容包括Java基础(如开发环境配置、核心语法增强)、面向对象编程(密封类、接口增强)、进阶技术(虚拟线程、结构化并发、向量API)、实用类库与框架(HTTP客户端、Spring Boot)、微服务与云原生(容器化、Kubernetes)、响应式编程(Reactor、WebFlux)、函数式编程(Stream API)、测试技术(JUnit 5、Mockito)、数据持久化(JPA、R2DBC)以及实战项目(Todo应用)。
357 5
|
8月前
|
存储 Java
# 【Java全栈学习笔记-U1-day02】变量+数据类型+运算符
本篇笔记主要围绕Java全栈学习的第二天内容展开,涵盖了变量、数据类型、运算符以及Scanner类的应用。首先介绍了变量的概念与命名规范,以及如何定义和使用变量;接着详细讲解了Java中的基本数据类型,包括整型、浮点型、字符型、布尔型等,并通过实例演示了数据类型的运用。随后,深入探讨了各类运算符(赋值、算术、关系、逻辑)及其优先级,帮助理解表达式的构成。最后,介绍了如何利用Scanner类实现用户输入功能,并通过多个综合示例(如计算圆面积、购物打折、变量交换及银行利息计算)巩固所学知识。完成相关作业将进一步加深对这些基础概念的理解与实践能力。
159 13
|
8月前
|
存储 缓存 算法
JVM简介—1.Java内存区域
本文详细介绍了Java虚拟机运行时数据区的各个方面,包括其定义、类型(如程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和直接内存)及其作用。文中还探讨了各版本内存区域的变化、直接内存的使用、从线程角度分析Java内存区域、堆与栈的区别、对象创建步骤、对象内存布局及访问定位,并通过实例说明了常见内存溢出问题的原因和表现形式。这些内容帮助开发者深入理解Java内存管理机制,优化应用程序性能并解决潜在的内存问题。
399 29
JVM简介—1.Java内存区域
|
8月前
|
Java Linux API
课时3:Java简介(Java主要特点)
本文介绍了Java的主要特点及其运行机制。Java结合了编译型和解释型语言的优点,通过Java虚拟机(JVM)实现跨平台移植,简化了不同操作系统间的开发流程。Java的特点包括可移植性、简单易用、支持多线程编程、自动垃圾收集和面向对象编程。随着硬件技术的发展,Java的性能问题已大大改善,成为行业标准之一,广泛应用于各种商用平台开发。
289 1
|
8月前
|
开发框架 移动开发 Java
课时2:Java简介(Java发展概述)
课时2:Java简介(Java发展概述) 摘要: 1. Java基础知识:介绍Java作为编程语言及其思想。 2. Java的发展历史:从1991年GREEN项目到1995年正式推出,历经网景公司、HotJava浏览器等关键节点。 3. Java的版本信息:涵盖从JDK 1.0到JDK 1.8的主要版本及特性,如Lambda表达式和模块化支持。
182 0