1.java数组
java数组初始化分为 静态初始化和动态初始化。
静态初始化,由程序员显示的指定每个数组元素的初始值,由系统决定数组的长度。
动态初始化,程序员只指定数组的长度,由系统为数组元素分配初始值,默认为0。
这两种个初始化不能并存,也就是说即指定数组的长度,又给数组分配每个元素的值。例如,int[] array = new int[5]{1,2,3,4,5};
一旦数组初始化后,内存空间分配即结束,后面只能个改变其元素的值,不能改变数组的长度。
定义数组的时候不一定要进行初始化,因为java的数组是引用类型,它并不是数组对象本身,只要让输入变量指向有效数组对象即可使用。
所有局部变量都是放在栈内存里面保存的,不管是基本类型的变量,还是引用类型的变量,都是存储在各自的方法栈区中,但是引用类型变量所引用的对象则总是存储在堆内存里的。
2.java对象
实例变量和类变量
实例变量:没有使用static修饰的成员变量是实例变量。
类变量:使用static修饰的成员变量是类变量。
在同一个JVM内,每个类只对应一个Class对象,但是每个类可以创建多个实例,所以可有有多个块实例内存,但是只有一块内存存放类。同时类变量的初始化时机比实例变量初始化要早。
父类构造器
在初始化子类的时候,系统首先会初始化父类的静态代码块、非静态代码块、构造器,然后再执行子类的静态代码块、匿名代码块和构造器。
子类调用父类的构造器分三种:1、super,2、this,3、没有super和this,直接调用父类的无参数构造器。(super和this只能写在构造器第一行,所以,这两者只能出现其中之一,而且也只能调用一次)
内存中的实例
当程序创建一个子类对象时,系统不仅会为该类中定义的实例变量分配内存,也会为其父类中定义的所有实例变量分配内存,即使子类定义了与父类中同名的实例变量,所以出现了super这个词,来区分子类实例变量和方法与父类之间的调用。
final变量
fianl类变量只能在定义final类变量时指定初始值或者在静态初始化块中为final类变量指定初始化值。
final类变量不能在构造函数和非静态初始化块中指定初始值。此外,final变量和其他变量不一样,其他变量都是在代码执行或者构造函数里初始化,但是final在编译时就直接把具体的值当变量使用。
3.java垃圾回收机制
java引用
java的引用分四种引用:1、强引用,2、软引用,3、弱引用,虚引用。
强引用:一个类实例被一个变量引用,并且可以通过变量访问该实例,这就是强引用。
被强引用的对象是绝对不会被java垃圾回收机制回收,即使内存非常紧张,这也是导致java内存泄漏的重要原因之一。
软引用:软引用需要通过SoftReference类来实现,在内存充足的情况下是不会被回收的,只有到系统内存不足时,才会被回收。
弱引用:弱引用通过WeakReference类来实现,级别比软引用更低,当系统垃圾回收时,不管系统内存是否充足,都会在垃圾回收时及时被回收掉。
虚引用:虚引用主要作用是跟踪对象被垃圾回收的状态,通过PhantomReference实现同时需要联合ReferenceQueue(引用队列)使用。
和其他引用不同的是虚引用无法获取它的引用对象。把软引用、弱引用和引用队列联合使用时,系统在回收引用对象后,把对应的引用添加到引用对列中,但是虚引用是在回收之前,加到引用对列中。
垃圾回收方式
串行回收:一个进程或者CPU执行垃圾回收操作。在运行Java程序的时候,使用-XX:+UseSerialGC。
并行回收:多个进程或者CPU并行执行垃圾回收操作,效率高,会增加内存碎片。在运行Java程序的时候,使用-XX:+UseParallelOldGC,可以通过-XX:ParallelGCThreads=size来设置并行线程数量。
垃圾回收过程
并发回收:在不影响程序运行的情况下回收垃圾,需要处理应用程序之间的冲突。
停止程序回收:在执行垃圾回收的时候会先停止程序的运行,然后进行回收垃圾。
垃圾回收基本算法
复制:将堆内分成两个相同的空间,从根开始访问每一个关联的可达对象,将空间A的可达对象全部复制到空间B,然后回收整个A空间。
缺点:需要额外的内存空间。
标记清除(Mark Sweep):先遍历整个空间,将可达对象进行标记,再遍历整个空间,将所有未标记的对象进行回收。
缺点:产生内存碎片。
标记压缩(Mark Sweep Compact):先遍历整个空间,将可达对象进行标记,再将所有可达对象搬迁到一起,在清除其他对象内存高。
堆内存的分代回收机制
Young代:这个代分Eden区和Survior区,绝大多数对象先分配到Eden区中,Survivor区中的对象都至少在Young代经历过一次垃圾回收,再被转移到Old代之前会先保留在Survivor区。因为Young代的对象数量相对比较少,所以发挥复制算法。在复制的时候,会先将Eden和第一个Survivor复制到第二个Survior区中,然后清空Eden和第一个Survivor区。
Old代:当对象在Young代中经过多次垃圾回收,都没有被回收掉,则这个对象就会被转移到Old代中。因为Old代中得对象很少会被清除,所以不需要经常性的去进行回收,此外也导致了Old代的空间会越来越大,这就需要Old代一般会采用标记压缩。
Permanent代:主要用于装在Class、方法等信息,默认为64M,垃圾回收机制一般不会回收该代中得对象,例如Spring、Hibernate等AOP动态生成类库,往往会产生大量的动态代理类,所以需要更多的Permanet代内存。
4.java内存设置
-Xmx256m: 设置虚拟机堆内存最大容量
-Xms128m: 设置虚拟机堆内存的初始容量
-XX:MinHeapFreeRatio=40:设置堆内存最小空闲比,默认:40
-XX:MaxHeapFreeRatio=70:设置堆内存最大空闲比,默认:70
-XX:NewRatio=2:设置Young/Old内存比
-XX:NewSize=52M:设置Young代内存默认容量
-XX:SurvivorRatio=8:设置Young代中eden/survivor的比例
-XX:MaxNewSize=128M 设置Young代内存最大容量
-XX:PermSize=52M,设置Permanent代内存默认容量
-XX:MaxPermSize=64M,设置Permanent代内存最大容量
更多参考
http://www.omybug.com/2014/06/15/Java%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6/