内存,反射

1.JVM内存

  • 方法区:
    • 线程共享
    • 用于存放常量,静态变量,以及被虚拟机加载的类的信息,即就是编译器编译后的代码
    • 称为永久代
    • 当一个类的所有实例被回收,那么就会将其回收
    • 方法区无法满足内存分配时,抛出OutOfMemoryError
    • jdk1.8之后方法区的常量存储被转移到了堆空间
  • java堆:
    • 线程共享
    • 存放所有的对象实例和数组
    • 垃圾回收的主要区域
    • 分为新生代、老年代、永久代(java8废弃了,替换为了本地内存)
    • 新生代:用于存储刚创建的对象
    • 永久代:对象一直没有被回收,生存的足够长老年对象就被移入永久区
    • 无法满足内存分配时,抛出OutOfMemoryError
  • 虚拟机栈(jvm栈):
    • 线程私有,与线程同一时间创建
    • 每个方法创建时,都会创建一个来存储方法的变量
    • 大小可以是固定的,也可以是动态扩展的
    • 如果请求的栈深度大于最大可用深度,抛出StackOverflowError,
    • 栈动态扩展,但是没有内存空间支持,测抛出OutOfMerroyError
  • 本地方法区:
    • 也叫本地方法栈
    • 是为jvm使用到对本地方法服务(由c/c++编写的)
    • hotSpot虚拟机(java一个最常见的虚拟机)将本地方法栈和jvm栈合二为一了
  • 程序计数器:
    • 当超过CPU数量,线程之间就要抢夺CPU时间资源,因此每个线程要有一个独立的程序计数器
    • 线程私有
    • 执行java方法,计数器记录正在执行的java字节码地址
    • 执行的是native方法(c/c++写的代码),则计数器为空

2.GC机制中垃圾回收算法

  • 标记清除法
    • 从根节点开始标记所有可到达对象,没有标记的即为垃圾对象,执行清除
    • 回收之后空间是不连续的
    • 实现容易,比较严重的问题是容易产生内存碎片化,如果需要一个较大对象分配空间时,无法找到足够大的空间
  • 复制算法
    • 将内存容量划分为大小相等的两块,每次只用其中的一块,
    • 当这一块用完了,就将还存活的对象复制到另外一块上面,
    • 然后再把已使用的空间一次清理掉
    • 实现简单,运行高效切不容易产生内存碎片
    • 对于内存空间的使用做出了高昂的代价,因为能够使用的内存缩减到了原来的一半
    • 如果存活对象很多,那么复制算法的效率会大大降低
  • 标记压缩法
    • 适用于老年代(存活对象多于垃圾对象)
    • 标记后不复制,而是将存活的对象压缩到内存的一端
    • 清理边界外的所有对象
    • 效率慢,移动内存空间会对用户产生速度的影响
  • 分代收集算法
    • 目前大部分jvm垃圾收集器采用的算法
    • 根据对象存活的声明周期将内存分为若干个不同的区域,
    • 将堆划分为老年代(每次垃圾收集时,只有少量的对象需要回收,老年代采用标记压缩算法)、新生代(每次回收都有大量的对象需要被回收,新生代,采用复制算法)
    • 堆空间之外还有一个永久代,对于永久代回收的是废弃的常量和无用的类
    • java8之前该区域位于方法区,java8之后替换到了堆空间

3.类加载机制

*.class文件装载到jvm的过程,将其放在运行时数据区的方法区,然后在堆中创建一个java.long.Class对象,用来封装类在方法区的数据结构,最终就是位于堆中的Class对象,Class对象封装了类在方法区的数据结构,并且向程序员提供了数据接口的接口

五个部分:加载、(验证、准备、解析)这3个也叫连接、初始化

  • 加载:获取class对象,不一定非要从一个class文件获取,还可以从zip包中读取,也可以在运行时计算生成(动态代理),也可以由其他文件生成(比如jsp文件转换成对应的class类)

  • 连接

    • 验证:确保class文件字节流中包含的信息复合当前虚拟机的要求,并不会危害虚拟机自身安全,验证方式:文件格式验证、元数据验证、字节码验证、符号引用验证
    • 准备:正式为类变量分配空间,在方法区中分配这些变量所使用的内存空间
    • 解析:将虚拟机常量池中的符号引用替换为直接引用的过程
  • 初始化:执行java程序代码,执行类构造器方法的过程,方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的,虚拟机会败在方法之前,父类的方法已经执行完毕,如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成方法

类加载器:
  • BootStrapClassLoader:由c++编写而成,负责搜寻JRE目录中的Class或lib目录下的jar文件,(rt.jar)系统参数指定,即就是jdk内置的类
  • ExtensionClassLoader:找第三方jar包,是否存在,存在就加载
  • APPClassLoader:看自己写的类是够存在,若存在加载

4.反射

因为java在运行时不可修改,因此java提供了反射机制,在运行期间可以通过反射机制动态获取对象所属类的具体信息,反射:就是将一个类中的所有成分反射成为对应的java类

class类

任何一个类被装载在jvm中时,都会在堆中生成一个表示该原始类型的class对象,,获取一个class对象:

  • 对象.getClass();
  • 类名.class
  • Class.,forName(类路径);

使用反射创建对象:

  • 先获取一个class对象
  • 对象.newInstrance();

反射获取类中的成分:

1.属性
  • getFied()、getDeclareField()、获取单个属性
  • getFieds()、getDeclareFields()、获取属性数组

Field类的常用方法:

  • getName()
  • getType()
  • getaModifirs()获取属性的修饰符
  • setAccessable:设置属性的可访问性
  • set:为属性设置值
2.构造方法

和属性一样就是关键部分变成了Constructor

Constructor类的常用方法:

  • newInstance(参数数组);根据提供的参数实例化对象
3.方法

关键字换成了Method,

常见方法:

  • invoke(执行那个对象,方法需要传递的参数值);通过提供的参数执行执行对象的方法

反射成分中都有:

  • setAccessable:设置成分的可访问性

5.注解

代码的特殊标记:这些标记可以再编译,类加载,运行时被读取

自定义注解
public @interface <注解名>{
    
    <属性定义>
    
}

属性支持类型:

  • 整数类型
  • 浮点数
  • 字符串类型
  • 布尔类型
  • 枚举类型
  • 注解类型
  • 以上所有的数组类型
元注解

注解上面加注解

  • @Retention 描述注解被保留的阶段(通常都是Runtime)
    • Source:仅在编译期间
    • Class:字节码文件中(默认就是这里)
    • Runtime:运行期间的字节码文件中
  • @Target 描述注解的作用范围
    • 类、接口、枚举(Type)
    • 字段上(Field)
    • 方法(Method)
    • 构造器(Constructor)
    • 包(package)
    • 参数(parameter)
    • 局部变量(Local_variable)
    • 注解(Annotation_Type)
    • 泛型Type_parameter
    • 使用泛型时Type_User
    • 不限定范围,则全局可用
  • @Documented生成api时,注解保留
  • Inherited(继承):如果有子类继承含有这个注解的类,那么该类的注解也会作用在子类上
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值