JVM和内存管理

JVM和内存管理浅理解

1.1 JVM

ClassLoader包括bootstrap classloader(启动类加载器,加载核心API),ExtClassLoader(加载扩展API),AppClassLoader(加载自定义类,即CLASSPATH设置目录中的Class)。

ClassLoader加载流程

运行一个程序时,JVM启动,运行bootstrap classloader,然后调用ExtClassLoader,最后加载AppClassLoader。

重要方法
  • ClassLoader.loadClass()为ClassLoader的入口函数。
    定义:
	Class loadClass(String name, boolean resolve);

name为JVM加载的类,如Foo或java.lang.Object。resolve参数告诉方法是否需要解析类。

  • forName
    类似loadClass方法,用来加载class,loadClass resolve参数默认为false,即不解析类,也不初始化类,forName则相反。

1.2 i++

i++,++i,i–,--i,是 i 的自增/减先后的区别。
几个实例可以说明的很清楚。

int i,j,k,m,n=0;
i = i++ + ++i + ++i;
j = ++j + j++ + j++;
k = k++ + k++ + ++k;
n=m++;
m=++n;

’i++‘等自增视作一条执行语句,其后的‘+’是运算符。
第二行代码求解i为例。
计算过程:
i=0+2+3=5
先执行i++,i此时为0,执行到’+'号时,i++自增完成,i此时为1,再执行++i,i此时为2,再执行++i,i此时为3。
同理,求解j,k,n,m的计算过程如下:
j=1+1+2=4
k=0+1+3=4
n=0
m=1

1.3 运算符和异常

运算符

三目运算:s=a?b:c;等价于if a : s=b; else s=c;
其中‘:’的右方数据类型自动转换为左方数据类型,当左方数据类型为常量时,右方可维持原数据类型。

位运算符:& && | ||
位运算中 & 和 | 作为与或(二进制)处理。
在布尔逻辑运算中,& 和 &&等价,| 同理。区别是 && || 为短路运算,& |为非短路运算。

异常

final、finally、finalize 三者区别

  • final
    final类不可被继承,不能派生新子类;
    final方法或变量可保证在调用过程中不被改变,即不能修改和重写。
  • finally
    在异常处理时提供finally块来执行清除操作。try→cathch→finally
  • finalize
    释放共享资源等清理工作。在垃圾收集器从内存清除之前。

反射

反射(Reflection)主要是指程序可以访问、检测、和修改它自身的状态或行为的一类应用。

1.4 传递与引用

传值与传引用

对于基本类型变量,JAVA是传值的副本;
对于对象型变量,JAVA是传引用的副本。
(String 是对象型变量)
(C++中,当参数是引用类型时,传递的是真实引用而非副本。)

输入/输出流

JAVA的IO操作中有面向字节(Byte)和面向字符(Character)两种方法。
面向字节
以8位为单位对二进制数据操作。均为InputStream和OutputStream的子类。
InputStream和OutputStream为后缀的是字节流。
面向字符
以字符为单位操作。读文件将二进制数据转化为字符,写文件将字符转化为二进制数据。均为Reader和Writer的子类。
Reader和Writer为后缀的是字符流。

序列化

实现序列化能将一个实现了Serializable接口的对象转换成一组byte,后期恢复byte数据即可重构对象。
可以实现轻量级持久化(lightweight persistence)。程序两次调用间对象还活着。通过读写磁盘。
重要功能

  • 实现JAVA的远程方法调用(Remote Method Invocation, RMI):像调自己机器的对象一样去调用其它机器的对象。
  • JavaBean:状态信息的保存。

二、JAVA内存管理

2.1 垃圾收集

Java在创建对象时会自动分配内存,并当该对象的引用不存在时释放这部分内存。
垃圾回收线程是低优先级的,在正常情况下是不会执行的,只有在虚
拟机空闲或者当前堆内存不足时,才会触发执行。
垃圾回收机制:System类中的静态方法 gc(),可运行垃圾收集器,运行在JVM中。调用该方法是发起申请,执行情况未知,即不一定立即回收。
最好使用 protected void finalize() throws Throwable来手动强制终止对象,或者自定义finalize的方法。

JVM虚拟机的具体实现机制-面试

2.2 内存管理

JVM 分为堆区栈区,还有方法区,初始化的对象实例放在堆里面,引用放在栈里面, class 类信息常量池(static 常量和 static 变量)等放在方法区。
堆里面分为新生代老生代(java8 取消了永久代,采用了Metaspace),新生代包含Eden+Survivor区,Survivor区里面分为 fromto 区。
内存回收时,如果用的是复制算法,从 from 复制到 to,当经过一次或者多次 GC 之后,存活下来的对象会被移动。
当 JVM 内存不够用的时候,会触发 FGC(Full GC),清理 JVM 老年区。当新生区满了之后会触发 MGC(Minor GC),先把存活的对象放到其中一个 Survice区,然后进行垃圾清理。因为如果仅仅清理需要删除的对象,这样会导致内存碎片,因此一般会把 Eden 进行完全的清理,然后整理内存。那么下次 GC 的时候, 就会使用下一个 Survive,这样循环使用。
常用的内存调试工具:jmap、jstack、jhat
jmap 查看内存信息,jstack 查看当前栈的情况,jhat 查看 dump 堆信息。

内存泄漏

未释放无用的已分配的内存就可能造成内存泄漏。

检查内存泄漏方法:

  1. 使用Xcode自带的leaks动态检查内存泄漏:
    选择Xcode -> Open Developer Tool -> Instruments -> Leaks工具
  2. 使用代码(重写dealloc方法)
    Leaks工具虽然强大,但是它不能检测到block循环引用导致的内存泄漏,这种情况一般需要自行排查问题,傻瓜式方法是重写对象的dealloc方法来监测对象是否正常释放,来确认没有形成循环引用。

理论依据是:访问内存时,通过比较访问的内存和程序实际分配的内存,验证内存访问的有效性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值