java基础

本文深入探讨Java类加载过程,包括Javac编译、JVM加载.class文件的机制,以及ClassLoader的角色。同时,详细讲解了Class、Method、Field的使用,反射的基本操作,和类加载器的层次结构与工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java基础

  • Javac 编译Java文件成为。class文件
  • javap 是jdk自带的反编译工具

JVM 如何加载.class文件

  • ClassLoader: 依据特定的格式将文件加载到内存
  • Execution Engine: 对命令进行解释
  • Nactive Interface: 融合不同开发语言的原生库为Java所用
  • Runtime Data Area: Java内存空间模型

反射

Class:

  • 是一个类; 一个描述类的类.
  • 封装了描述方法的 Method,
  • 描述字段的 Filed,
  • 描述构造器的 Constructor 等属性.

如何得到 Class 对象:

  • Person.class
  • person.getClass()
  • Class.forName(“com.atguigu.javase.Person”)

Method:

如何获取 Method
  • getDeclaredMethods: 得到 Method 的数组.
  • getDeclaredMethod(String methondName, Class … parameterTypes)
如何调用 Method
  • 如果方法时 private 修饰的, 需要先调用 Method 的 setAccessible(true), 使其变为可访问
  • method.invoke(obj, Object … args);

Field:

如何获取 Field:
  • getField(String fieldName)-
如何获取 Field 的值:
  • setAccessible(true)
  • field.get(Object obj)
如何设置 Field 的值:
  • field.set(Obejct obj, Object val)

ClassLoader

BootStrapClassLoader(引导类加载器)

  • 处于类加载器层次结构的最高层,负责 sun.boot.class.path 路径下类的加载,默认为 jre/lib 目录下的核心 API 或 -Xbootclasspath 选项指定的 jar 包。

ExtClassLoader (扩展类加载器)

  • 加载路径为 java.ext.dirs,默认为 jre/lib/ext 目录或者 -Djava.ext.dirs 指定目录下的 jar 包加载。

AppClassLoader(系统类加载器)

  • 加载路径为 java.class.path,默认为环境变量 CLASSPATH 中设定的值。也可以通过 -classpath 选型进行指定。

用户自定义 ClassLoader

  • 可以根据用户的需要定制自己的类加载过程,在运行期进行指定类的动态实时加载。

双亲委托

  • 每个classLoader都从自己已经加载的类中查询是否存在需要的类,如果存在直接返回已经加载的类,每个类加载器都有自己的加载缓存,当一个类被加载后,会直接放入缓存
  • 当前classLoader中不存在,则委托给父加载器去加载,依次递归,一直到bootstrp ClassLoader
  • 如果没有则从对应得目录中加载,从最高层向下加载;

优势

  • 保证一个类的全局唯一性

类的加载

  • 当程序主动使用某一个类时,如果该类没被加载到内存中,系统会经过加载,连接,初始化三个步骤来对类进行初始化, 一般JVM会连续完成三个步骤,所以三个各步骤统称为 类的加载或类初始化
类加载
  • 类的加载时指将类的class 文件读入内存,并为之创建一个java.lang.Class对象,当程序使用任何类的时候 系统都会为之建立一个java.lang.Class对象

类的连接

  • 当类被加载之后,系统为之生成一个对应得Class对象,接着将会进入连接阶段,连接阶段把类的二进制文件数据合并到JRE中
验证
  • 验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致
准备

类准备阶段则负责为类的类变量分配内存,并设置默认初始值

解析

将类的二进制数据中的符号引用替换为直接引用

对象分配规则

  • 对象优先分配在Eden区,如果Eden区没有足够的空间时候,虚拟机执行一次Minor GC。
  • 大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)这样做的目的是避免Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)
  • 长期存活的对象进入老年代,虚拟机为每个对象定义了一个年龄计数器,如果对象经过一次Minor GC 那么对象会进入Survivor区,之后每经过一次Minor GC ,那么对象的年龄增加1,直到达到阈值,对象进入老年代
  • 动态判断对象的年龄.如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或者等于该年龄的对象可以直接进入老年代
  • 空间分配担保。每次进行Minor Gc的时候,JVM会计算Survior区移至老年区的对象的平均大小,如果这个值大于老年区的剩余价值大小进行一次FullGC, 如果小于 ,检查HandlePromotionFailure设置,如果true则只进行进行Monitor GC,如果false 则进行fullGC

LoadClass和forName的区别

  • 类的加载过程分为 加载—链接(链接又分为验证,准备,解析三个阶段)—初始化

  • Class.forName得到的是已经初始化完成的,即类的加载过程已经完成了

  • 而Class.loadClass得到的class是还没有链接的,即只是通过了类加载过程的加载阶段,通过ClassLoader加载class加载文件字节码,将其放在运行时数据区的方法区内,在堆区创建一个java.lang.Class对象(用来封装类在方法区内的数据结构)

  • 在spring IOC中 大量使用这种加载方式,木的还是为了提高加载速度,而剩余的阶段则等到实际使用到类的时候才执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值