java 测试开发基础知识(类加载,JVM等)

写在开头:

面试的时候别人很可能会问你的java原理,.class load 原理, jvm机制,这些都是Java的底层知识,特整理如下:

1. 首先,编写一个java程序,大家会用ide编写一个例如helloworld.java的文件, 程序是能够识别这个文件的,但是计算机不行,所以需要一个编译的过程:

执行java.exe , 例如 在cmd的窗口执行:   $java  helloworld.java , 这个时候你会发现在同级目录系生成了一个helloworld.class的可执行文件,这个文件是可以

被JVM直接执行的,原理如下:

.class文件大体如下:

JVM虚拟机只能识别.class文件这种字节码文件,然后将字节码翻译成可执行的0,1;这个说明了JVM具有语言无关性,不仅仅是平台无关性,这也是scala,Grovvy,JRUby….能在JVM上运行的原因,各种语言通过不同的编译器将其编译成.class文件

Java类加载机制(jvm 如何处理.class文件?)

首先要了解jvm的构造:

大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) ,   VM Stack(虚拟机栈,也有翻译成JAVA 方法栈的),Native Method Stack  ( 本地方法栈 ),其中Method Area 和  Heap 是线程共享的  ,VM Stack,Native Method Stack  和Program Counter Register  是非线程共享的。为什么分为 线程共享和非线程共享的呢?请继续往下看。

概括地说来,JVM初始运行的时候都会分配好 Method Area(方法区) 和Heap(堆) ,而JVM 每遇到一个线程,就为其分配一个 Program Counter Register(程序计数器) ,   VM Stack(虚拟机栈)和Native Method Stack  (本地方法栈), 当线程终止时,三者(虚拟机栈,本地方法栈和程序计数器)所占用的内存空间也会被释放掉。这也是为什么我把内存区域分为线程共享和非线程共享的原因,非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与JAVA程序运行的生命周期相同,所以这也是系统垃圾回收的场所只发生在线程共享的区域(实际上对大部分虚拟机来说知发生在Heap上)的原因。

所以内存泄露一般也发生在heap 和method area区域

类加载过程:

1.概述

Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能。

虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。

2.工作机制

类装载器就是寻找类的字节码文件,并构造出类在JVM内部表示的对象组件。在Java中,类装载器把一个类装入JVM中,要经过以下步骤:

类加载过程

类加载分为三个步骤:加载连接初始化

如下图 , 是一个类从加载到使用及卸载的全部生命周期,图片来自参考资料;

加载

根据一个类的全限定名(如cn.edu.hdu.test.HelloWorld.class)来读取此类的二进制字节流到JVM内部;

将字节流所代表的静态存储结构转换为方法区的运行时数据结构(hotspot选择将Class对象存储在方法区中,Java虚拟机规范并没有明确要求一定要存储在方法区或堆区中)

转换为一个与目标类型对应的java.lang.Class对象;

连接

验证

验证阶段主要包括四个检验过程:文件格式验证、元数据验证、字节码验证和符号引用验证;

准备

为类中的所有静态变量分配内存空间,并为其设置一个初始值(由于还没有产生对象,实例变量将不再此操作范围内);

解析

将常量池中所有的符号引用转为直接引用(得到类或者字段、方法在内存中的指针或者偏移量,以便直接调用该方法)。这个阶段可以在初始化之后再执行。

初始化

在连接的准备阶段,类变量已赋过一次系统要求的初始值,而在初始化阶段,则是根据程序员自己写的逻辑去初始化类变量和其他资源,举个例子如下:

    public static int value1  = 5;
    public static int value2  = 6;
    static{
        value2 = 66;
    }

在准备阶段value1和value2都等于0;

在初始化阶段value1和value2分别等于5和66;

  • 所有类变量初始化语句和静态代码块都会在编译时被前端编译器放在收集器里头,存放到一个特殊的方法中,这个方法就是<clinit>方法,即类/接口初始化方法,该方法只能在类加载的过程中由JVM调用;
  • 编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块中只能访问到定义在静态语句块之前的变量;
  • 如果超类还没有被初始化,那么优先对超类初始化,但在<clinit>方法内部不会显示调用超类的<clinit>方法,由JVM负责保证一个类的<clinit>方法执行之前,它的超类<clinit>方法已经被执行。
  • JVM必须确保一个类在初始化的过程中,如果是多线程需要同时初始化它,仅仅只能允许其中一个线程对其执行初始化操作,其余线程必须等待,只有在活动线程执行完对类的初始化操作之后,才会通知正在等待的其他线程。(所以可以利用静态内部类实现线程安全的单例模式)
  • 如果一个类没有声明任何的类变量,也没有静态代码块,那么可以没有类<clinit>方法;

何时触发初始化

  1. 为一个类型创建一个新的对象实例时(比如new、反射、序列化)
  2. 调用一个类型的静态方法时(即在字节码中执行invokestatic指令)
  3. 调用一个类型或接口的静态字段,或者对这些静态字段执行赋值操作时(即在字节码中,执行getstatic或者putstatic指令),不过用final修饰的静态字段除外,它被初始化为一个编译时常量表达式
  4. 调用JavaAPI中的反射方法时(比如调用java.lang.Class中的方法,或者java.lang.reflect包中其他类的方法)
  5. 初始化一个类的派生类时(Java虚拟机规范明确要求初始化一个类时,它的超类必须提前完成初始化操作,接口例外)
  6. JVM启动包含main方法的启动类时。

初步了解这么多够面试用了,如果想要更详细的,请参考大佬的分析:

https://www.cnblogs.com/aspirant/p/7200523.html

原文地址:https://www.cnblogs.com/Ronaldo-HD/p/9847682.html

时间: 2024-11-12 22:46:12

java 测试开发基础知识(类加载,JVM等)的相关文章

Java的入门基础知识

https://course.tianmaying.com/java-basic%2Bjava-environment#0 作者:David链接:https://www.zhihu.com/question/25255189/answer/86898400来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 这个教程将Java的入门基础知识贯穿在一个实例中,逐步深入,可以帮助你快速进入Java编程的世界.万事开头难,逐步跟着这个教程走一遍,对Java应该就会有一种入门的

IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token

本文引用了简书作者“骑小猪看流星”技术文章“Cookie.Session.Token那点事儿”的部分内容,感谢原作者. 1.前言 众所周之,IM是个典型的快速数据流交换系统,当今主流IM系统(尤其移动端IM)的数据流交换方式都是Http短连接+TCP或UDP长连接来实现.Http短连接主要用于从服务器读取各种持久化信息:比如用户信息.聊天历史记录.好友列表等等,长连接则是用于实时的聊天消息或指令的接收和发送. 作为IM系统中不可或缺的技术,Http短连的重要性无可替代,但Http作为传统互联网信

iOS开发基础知识--碎片6

iOS开发基础知识--碎片6  三十三:IOS多视图跳转方法 第一种: 跳转:[self presentModalViewController:control animated:YES]; 返回:[self dismissModalViewControllerAnimated:YES]; 第二种: 跳转:[self.navigationController pushViewController:subTableViewController animated:YES]; 返回:[self.navi

iOS开发基础知识--碎片7

iOS开发基础知识--碎片7  三十八:各个版本IPHONE分辨率及图片的实现原理 [email protected] : iPhone 4s (320 x 420) [email protected] : iPhones 5, 5C and 5S (320 x 568) [email protected] : iPhone 6 (375 x 667) [email protected] : iPhone 6+ (414 x 736) [email protected]~ipad : iPad

iOS开发——总结篇&amp;IOS开发基础知识

IOS开发基础知识 1:Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id) 对象在运行时获取其类型的能力称为内省.内省可以有多种方法实现. 判断对象类型 -(BOOL) isKindOfClass: classObj判断是否是这个类或者这个类的子类的实例 -(BOOL) isMemberOfClass: classObj 判断是否是这个类的实例 实例一: Person *person = [[Person alloc] init]; //父

iOS开发基础知识--碎片16

iOS开发基础知识--碎片16  1:Objective-C语法之动态类型 (isKindOfClass, isMemberOfClass,id) 对象在运行时获取其类型的能力称为内省.内省可以有多种方法实现. 判断对象类型 -(BOOL) isKindOfClass: classObj判断是否是这个类或者这个类的子类的实例 -(BOOL) isMemberOfClass: classObj 判断是否是这个类的实例 实例一: Person *person = [[Person alloc] in

IOS开发基础知识碎片-导航

1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可以存放,就是类NSNumber c:NSDATA与NSString互转 d:去除输入框空格(NSString也适用) f:IBOutlet,IBAction说明 2:IOS开发基础知识--碎片2  a:获得另一个控件器,并实现跳转 b:判断IOS版本 c:Button不同状态下背景图片 d:判断设备

(001)springboot中测试的基础知识以及接口和Controller的测试

(一)springboot中测试的基础知识 (1)添加starter-test依赖,范围指定为test,只在执行测试时生效 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> 完整po

Java语言的基础知识

第三章 1.在java源文件编辑器中,选择某个成员变量,然后按住shift+alt+j,Eclipse会自动添加JavaDoc文档注释结构,如果选择的是方法,还会自动添加参数名称. 2.Java语言规定标示符是由任意的字母.下划线.美元符号和数字组成,并且第一个字符不能使数字,标示符不能使java中的保留关键字. 3.在Java语言中允许使用汉字或其他语言文字作为变量名,如int 年龄 =21;在程序运行时不会报错,但建议尽量不要使用这些语言作为变量. 4.java用关键字final来声明常量,