1. 垃圾回收
JVM运行环境中垃圾对象的定义:
一个对象创建后被放置在JVM的堆内存(heap)中,当永远不再引用这个对象时,它将被JVM在堆内存(heap)中回收。被创建的对象不能再生,同时也没法通过程序语句释放它们。
不可到达的对象被JVM视为垃圾对象,JVM将给这些对象打上标记,然后清扫回收它们,并将散碎的内存单元收集整合。
JVM管理的两种类型的内存:
堆内存(heap),主要存储程序在运行时创建或实例化的对象与变量。
栈内存(stack),主要存储程序代码中声明为静态(static)(或非静态)的方法。
堆内存(heap)通常情况下被分为两个区域:新对象(new object)区域与老对象(old object)区域。
新对象区域:
又可细分为Eden区域、From区域与To区域。
Eden区域保存新创建的对象。当该区域中的对象满了后,JVM系统将做可达性测试,主要任务是检测有哪些对象由根集合出发是不可到达的,这些对象就可被JVM回收,且将所有的活动对象从Eden区域拷到To区域,此时有一些对象将发生状态交换,有的对象就从To区域被转移到From区域,此时From区域就有了对象。
该过程执行期间,JVM的性能非常低下,会严重影响到正在运行的应用的性能。
老对象区域:
在老对象区域中的对象仍有一个较长的生命周期。经过一段时间后,被转入老对象区域的对象就变成了垃圾对象,此时它们被打上相应的标记,JVM将自动回收它们。
建议不要频繁强制系统做垃圾回收,因为JVM会利用有限的系统资源,优先完成垃圾回收工作,致使应用无法快速响应来自用户端的请求,这样会影响系统的整体性能。
2. JVM中对象的生命周期
对象的整个生命周期大致分为7个阶段:创建(creation)、应用(using)、不可视(invisible)、不可到达(unreachable)、可收集(collected)、终结(finalized)、释放(free)。
1) 创建阶段
系统通过下面步骤,完成对象的创建:
a) 为对象分配存储空间
b) 开始构造对象
c) 递归调用其超类的构造方法
d) 进行对象实例初始化与变量初始化
e) 执行构造方法体
在创建对象时的几个关键应用规则:
• 避免在循环体中创建对象,即使该对象占用内存空间不大
• 尽量及时使对象符合垃圾回收标准
• 不要采用过深的继承层次
• 访问本地变量优于访问类中的变量
关于“在循环体中创建对象”,如下方式会在内存中产生大量的对象引用,浪费大量的内存空间,增大了系统做垃圾回收的负荷:
而如下方式,仅在内存中保存一份对该对象的引用:
另外,不要对一个对象进行多次初始化,这同样会带来较大的内存开销,降低系统性能。
2) 应用阶段
该阶段是对象得以表现自身能力的阶段,即是对象整个生命周期中证明自身“存在价值”的时期。此时对象具备下列特征:
a) 系统至少维护着对象的一个强引用(Strong Reference)
b) 所有对该对象的引用全是强引用(除非我们显示使用了软引用(Soft Reference)、弱引用(Weak Reference)或虚引用(Phantom Reference))
软引用
主要特点是具有较强的引用功能。只有当内存不够时,才回收这类内存。另外,这些引用对象还能保证在Java抛出OutOfMemory异常前,被置为null。它可用于实现一些常用资源的缓存,保证最大限度的使用内存而不引起OutOfMemory。
例:
软引用技术使Java应用能更好地管理内存,稳定系统,防止系统内存溢出,避免系统崩溃。在处理一些占用内存较大,且声明周期较长,但使用并不频繁的对象时,应尽量应用该技术。
但某些时候对软引用的使用会降低应用的运行效率与性能,如:应用软引用的对象的初始化过程较耗时,或对象的状态在运行过程中发生了变化,都会给重新创建对象与初始化对象带来不同程度的麻烦。
弱引用
与软引用对象的最大不同在于:GC在进行回收时,需通过算法检查是否回收软引用对象,而对于弱引用对象,GC总是进行回收。故弱引用对象拥有更短的生命周期,更易更快被GC回收。
虽然GC在运行时一定回收弱引用对象,但是负责关系的弱对象群常常需要好几次GC的运行才能完成。弱引用对象常用于Map数据结构中,引用占用内存空间较大的对象,一旦该对象的强引用为null,GC能快速回收该对象空间。
例:
虚引用
用途较少,主要用于辅助finalize方法。虚对象指一些执行完了finalize方法,且为不可达对象,但还未被GC回收的对象。这种对象可辅助finalize进行一些后期的回收工作,通过覆盖Reference的clear方法增强资源回收机制的灵活性。
注意:实际程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,因为软引用能加上JVM对垃圾内存的回收速度,能维护系统的运行安全,防止内存溢出等。
3) 不可视阶段
对象经历应用阶段后,便处于不可视阶段,说明我们在其他区域的代码中已不可再引用它,其强引用已消失。如:本地变量超出其可视范围。
例:
若一个对象已使用完,且在其可视区域不再使用,应主动将其设置为null。针对上面的例子,可主动添加obj = null;这样一行代码,强制将obj置为null。这样的意义是,帮助JVM及时发现这个垃圾对象,且可以及时回收该对象所占用的系统资源。
4) 不可到达阶段
处于不可到达阶段的对象,都是要被GC回收的预备对象,但此时该对象并不能被GC直接回收。其实所有垃圾回收算法所面临的问题是相同的——找出由分配器分配的,但用户程序不可到达的内存块。
5) 可收集阶段、终结阶段与释放阶段
此时JVM就可以直接回收对象了,而对象可能处于下面三种情况:
a) GC发现该对象已不可到达
b) finalize方法已被执行
c) 对象空间已被重用
3. Java中的析构方法finalize
Java中的finalize()与C++中的析构函数的职能极为类似。
虽然我们可以在一个Java类调用其父类的finalize方法,但由于该方法未自动实现递归调用,我们必须手动实现,因此该方法的最后一个语句通常是super.finalize()语句。通过这种方式,我们能实现从下到上finalize的迭代调用,即先释放用户类自身的资源,再释放父类资源。通过可在finalize()中释放一些不易控制,且非常重要的资源,如:一些I/O操作,数据的连接。
finalize()最终由JVM中的垃圾回收器调用,其调用时间是不确定或不及时的,调用时机对我们来说是不可控的。因此,有时我们需要通过其他手段释放系统资源,如声明一个destroy(),在该方法中添加释放系统资源的处理代码。虽然我们可以通过调用自定义的destroy()释放系统资源,但最好将对destroy()的调用放入当前类的finalize()中,因为这样更保险、安全。在类深度继承的情况下,这种方法就显得更有效了。
例:
MyTest的运行结果:
create a
create b
release b
release a
初始化B对象时,其构造器产生了递归调用,由父类开始依次调用,而在调用B对象的destroy()时,系统产生了与初始化调用相反的递归调用,释放资源是由子类开始的。由此可见,在设计类时,应尽可能避免在类的默认构造器中创建、初始化大量对象,或执行某种复杂、耗时的运算逻辑。
4. 数组的创建
如果数组中所保存的元素占用内存空间较大,或数组本身长度较长,我们可采用软引用的技术来引用数组,以“提醒”JVM及时回收垃圾内存,维护系统的稳定性。
例:
JVM根据运行时的内存资源的使用情况,来把握是否回收该对象,释放内存。虽然这样会对应用程序产生一些影响(如当需要使用该数组对象时,该对象被回收了),但却能保证应用整体的稳健性,达到合理使用系统内存的目的。
5. 共享静态变量存储空间
静态变量生命周期较长,不易被系统回收。因此如果不合理使用静态变量,会造成大量的内存浪费。建议在具备下列全部条件的情况下,尽量使用静态变量:
1) 变量所包含的对象体积较大,占用内存较多
2) 变量所包含的对象生命周期较长
3) 变量所包含的对象数据稳定
4) 该类的对象实例有对该变量所包含的对象的共享需求
6. 对象重用与GC
通常我们把用来缓存对象的容器对象成为对象池(Object Pool)。对象池通过对其所保存对象的共享与重用,缩减了应用线程反复重建、装载对象的过程所需的时间,有效避免了频繁GC带来的巨大系统开销,能大大提高应用性能,减少内存需求。
但如果长时间将对象保存在对象池中,即驻留在内存中,而这些对象又不被经常使用,无疑会造成内存资源浪费,又或者该对象在对象池中遭到破坏,若不对其及时清除会非常麻烦。因此,若决定使用对象池技术,需要采取相应的手段清除遭到破坏的对象,甚至在某些情况下需要清除对象池中所有对象。或者可为对象池中的每个对象分配一个时间戳,设定对象的过期时间,对象过期则及时将其从内存中清除。可以专门创建一个线程来清除此类对象。
例:
7. transient变量
在做远程方法调用(RMI)类的应用开发时,应该会遇到transient变量与Serializable接口,之所以要对象实现Serializable接口,是因为这样就可以从远程环境以对象流的方式,将对象传递到相应的调用环境中,但有时这些被传递的对象的一些属性并不需要被传递,因为这些数据成员对于应用需求而言是无关紧要的,那么这些属性变量就可被声明为transient。被声明为transient的变量是不会被传递的,这样能节约调用方的内存资源,减少网络开销,提高系统性能。这个transient变量所携带的数据量越大(如数据量较大的数组),其效用越大。
8. JVM内存参数调优
-XX:NewSize,设置新对象成产堆内存(set new generation heap size)
通常该选项数值为1024的整数倍且大于1MB。取值规则为,取最大堆内存(maximum heap size)的1/4。
-XX:MaxNewSize,设置最大新对象生产堆内存(set maximum new generation heap size)
其功用同-XX: NewSize。
-Xms,设置堆内存池的最小值(set minimum heap size)
要求系统为堆内存池分配内存空间的最小值。通常该选项数值为1024的整数倍且大于1MB。取值规则为,取与最大堆内存(-Xmx)相同的值,以降低GC的频度。
-Xmx,设置堆内存池的最小值(set maximum heap size)
要求系统为堆内存池分配内存空间的最大值。通常该选项数值为1024的整数倍且大于1MB。取值规则为,取与最大堆内存(-Xms)相同的值,以降低GC的频度。
例:
java –XX:NewSize=128m –XX:MaxNewSize=128m –Xms512m –Xmx512m MyApp
9. Java程序设计中有关内存管理的其他经验
1) 尽早释放无用对象的引用,加速GC的工作
2) 尽量少用finalize()。finalize()是Java给程序员提供一个释放对象或资源的机会,但会加大GC的工作量
3) 对常用到的图片,可采用SoftReference
4) 注意集合数据类型,包括数组、树、图、链表等数据结构,它们对GC来说,回收更复杂。另外,注意一些全局变量、静态变量,它们易引起悬挂对象,造成内存浪费
5) 尽量避免在类的默认构造器中创建、初始化大量的对象,防止在调用其子类的构造器时造成不必要的内存资源浪费
6) 尽量避免强制系统做GC(通过显式调用System.gc()),增长系统GC的最终时间,降低系统性能
7) 尽量避免显式申请数组空间,当不得不显式申请时,尽量准确估计出其合理值
8) 在做远程方法调用(RMI)类应用开发时,尽量使用transient变量
9) 在合适的场景下使用对象池技术以提高系统性能,缩减系统内存开销,但需注意对象池的尺寸不宜过大,及时清除无效对象释放内存资源
JVM运行环境中垃圾对象的定义:
一个对象创建后被放置在JVM的堆内存(heap)中,当永远不再引用这个对象时,它将被JVM在堆内存(heap)中回收。被创建的对象不能再生,同时也没法通过程序语句释放它们。
不可到达的对象被JVM视为垃圾对象,JVM将给这些对象打上标记,然后清扫回收它们,并将散碎的内存单元收集整合。
JVM管理的两种类型的内存:
堆内存(heap),主要存储程序在运行时创建或实例化的对象与变量。
栈内存(stack),主要存储程序代码中声明为静态(static)(或非静态)的方法。
堆内存(heap)通常情况下被分为两个区域:新对象(new object)区域与老对象(old object)区域。
新对象区域:
又可细分为Eden区域、From区域与To区域。
Eden区域保存新创建的对象。当该区域中的对象满了后,JVM系统将做可达性测试,主要任务是检测有哪些对象由根集合出发是不可到达的,这些对象就可被JVM回收,且将所有的活动对象从Eden区域拷到To区域,此时有一些对象将发生状态交换,有的对象就从To区域被转移到From区域,此时From区域就有了对象。
该过程执行期间,JVM的性能非常低下,会严重影响到正在运行的应用的性能。
老对象区域:
在老对象区域中的对象仍有一个较长的生命周期。经过一段时间后,被转入老对象区域的对象就变成了垃圾对象,此时它们被打上相应的标记,JVM将自动回收它们。
建议不要频繁强制系统做垃圾回收,因为JVM会利用有限的系统资源,优先完成垃圾回收工作,致使应用无法快速响应来自用户端的请求,这样会影响系统的整体性能。
2. JVM中对象的生命周期
对象的整个生命周期大致分为7个阶段:创建(creation)、应用(using)、不可视(invisible)、不可到达(unreachable)、可收集(collected)、终结(finalized)、释放(free)。
1) 创建阶段
系统通过下面步骤,完成对象的创建:
a) 为对象分配存储空间
b) 开始构造对象
c) 递归调用其超类的构造方法
d) 进行对象实例初始化与变量初始化
e) 执行构造方法体
在创建对象时的几个关键应用规则:
• 避免在循环体中创建对象,即使该对象占用内存空间不大
• 尽量及时使对象符合垃圾回收标准
• 不要采用过深的继承层次
• 访问本地变量优于访问类中的变量
关于“在循环体中创建对象”,如下方式会在内存中产生大量的对象引用,浪费大量的内存空间,增大了系统做垃圾回收的负荷:
for (int i = 0; i < 1000; i++) { Object obj = new Object(); ... }
而如下方式,仅在内存中保存一份对该对象的引用:
Object obj = null; for (int i = 0; i < 1000; i++) { obj = new Object(); ... }
另外,不要对一个对象进行多次初始化,这同样会带来较大的内存开销,降低系统性能。
2) 应用阶段
该阶段是对象得以表现自身能力的阶段,即是对象整个生命周期中证明自身“存在价值”的时期。此时对象具备下列特征:
a) 系统至少维护着对象的一个强引用(Strong Reference)
b) 所有对该对象的引用全是强引用(除非我们显示使用了软引用(Soft Reference)、弱引用(Weak Reference)或虚引用(Phantom Reference))
软引用
主要特点是具有较强的引用功能。只有当内存不够时,才回收这类内存。另外,这些引用对象还能保证在Java抛出OutOfMemory异常前,被置为null。它可用于实现一些常用资源的缓存,保证最大限度的使用内存而不引起OutOfMemory。
例:
… import java.lang.ref.SoftReference; … A a = new A(); …// 使用a SoftReference sr = new SoftReference(a);// 使用完了a,将它设置为软引用类型 a = null;// 释放强引用 … // 下次使用时 if (sr != null) { a = sr.get(); } else { // GC由于内存资源不足,系统已回收了a的软引用,故需重新装载 a = new A(); sr = new SoftReference(a); } …
软引用技术使Java应用能更好地管理内存,稳定系统,防止系统内存溢出,避免系统崩溃。在处理一些占用内存较大,且声明周期较长,但使用并不频繁的对象时,应尽量应用该技术。
但某些时候对软引用的使用会降低应用的运行效率与性能,如:应用软引用的对象的初始化过程较耗时,或对象的状态在运行过程中发生了变化,都会给重新创建对象与初始化对象带来不同程度的麻烦。
弱引用
与软引用对象的最大不同在于:GC在进行回收时,需通过算法检查是否回收软引用对象,而对于弱引用对象,GC总是进行回收。故弱引用对象拥有更短的生命周期,更易更快被GC回收。
虽然GC在运行时一定回收弱引用对象,但是负责关系的弱对象群常常需要好几次GC的运行才能完成。弱引用对象常用于Map数据结构中,引用占用内存空间较大的对象,一旦该对象的强引用为null,GC能快速回收该对象空间。
例:
… import java.lang.ref.WeakReference; … A a = new A(); …// 使用a WeakReference wr = new WeakReference(a);// 使用完了a,将它设置为弱引用类型 a = null;// 释放强引用 … // 下次使用时 if (wr != null) { a = wr.get(); } else { a = new A(); wr = new WeakReference(a); } …
虚引用
用途较少,主要用于辅助finalize方法。虚对象指一些执行完了finalize方法,且为不可达对象,但还未被GC回收的对象。这种对象可辅助finalize进行一些后期的回收工作,通过覆盖Reference的clear方法增强资源回收机制的灵活性。
注意:实际程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,因为软引用能加上JVM对垃圾内存的回收速度,能维护系统的运行安全,防止内存溢出等。
3) 不可视阶段
对象经历应用阶段后,便处于不可视阶段,说明我们在其他区域的代码中已不可再引用它,其强引用已消失。如:本地变量超出其可视范围。
例:
public void process() { try { Object obj = new Object(); obj.doSomething(); } catch (Exception e) { e.printStackTrace(); } while (isLoop) {// … loops forever // 该区域对应obj对象来说已是不可视的了 // obj. doSomething(); 在编译时会引发错误 } }
若一个对象已使用完,且在其可视区域不再使用,应主动将其设置为null。针对上面的例子,可主动添加obj = null;这样一行代码,强制将obj置为null。这样的意义是,帮助JVM及时发现这个垃圾对象,且可以及时回收该对象所占用的系统资源。
4) 不可到达阶段
处于不可到达阶段的对象,都是要被GC回收的预备对象,但此时该对象并不能被GC直接回收。其实所有垃圾回收算法所面临的问题是相同的——找出由分配器分配的,但用户程序不可到达的内存块。
5) 可收集阶段、终结阶段与释放阶段
此时JVM就可以直接回收对象了,而对象可能处于下面三种情况:
a) GC发现该对象已不可到达
b) finalize方法已被执行
c) 对象空间已被重用
3. Java中的析构方法finalize
Java中的finalize()与C++中的析构函数的职能极为类似。
虽然我们可以在一个Java类调用其父类的finalize方法,但由于该方法未自动实现递归调用,我们必须手动实现,因此该方法的最后一个语句通常是super.finalize()语句。通过这种方式,我们能实现从下到上finalize的迭代调用,即先释放用户类自身的资源,再释放父类资源。通过可在finalize()中释放一些不易控制,且非常重要的资源,如:一些I/O操作,数据的连接。
finalize()最终由JVM中的垃圾回收器调用,其调用时间是不确定或不及时的,调用时机对我们来说是不可控的。因此,有时我们需要通过其他手段释放系统资源,如声明一个destroy(),在该方法中添加释放系统资源的处理代码。虽然我们可以通过调用自定义的destroy()释放系统资源,但最好将对destroy()的调用放入当前类的finalize()中,因为这样更保险、安全。在类深度继承的情况下,这种方法就显得更有效了。
例:
public class A { Object a = null; public A() { a = new Object(); System.out.println("create a"); } protected void destroy() { a = null; System.out.println("release a"); } protected void finalize() throws Throwable { destroy(); super.finalize();// 递归调用父类的finalize() } } public class B extends A { Object b = null; public B() { b = new Object(); System.out.println("create b"); } protected void destroy() { b = null; System.out.println("release b"); super.destroy(); } protected void finalize() throws Throwable { destroy(); super.finalize();// 递归调用父类的finalize() } } public class MyTest { B obj = null; public MyTest() { obj = new B(); } protected void destroy() { if (obj != null) { obj.destroy(); } else { System.out.println("obj already released"); } } public static void main(String[] args) { MyTest mt = new MyTest(); mt.destroy(); } }
MyTest的运行结果:
create a
create b
release b
release a
初始化B对象时,其构造器产生了递归调用,由父类开始依次调用,而在调用B对象的destroy()时,系统产生了与初始化调用相反的递归调用,释放资源是由子类开始的。由此可见,在设计类时,应尽可能避免在类的默认构造器中创建、初始化大量对象,或执行某种复杂、耗时的运算逻辑。
4. 数组的创建
如果数组中所保存的元素占用内存空间较大,或数组本身长度较长,我们可采用软引用的技术来引用数组,以“提醒”JVM及时回收垃圾内存,维护系统的稳定性。
例:
char[] obj = new char[1000000]; SoftReference ref = new SoftReference(obj);
JVM根据运行时的内存资源的使用情况,来把握是否回收该对象,释放内存。虽然这样会对应用程序产生一些影响(如当需要使用该数组对象时,该对象被回收了),但却能保证应用整体的稳健性,达到合理使用系统内存的目的。
5. 共享静态变量存储空间
静态变量生命周期较长,不易被系统回收。因此如果不合理使用静态变量,会造成大量的内存浪费。建议在具备下列全部条件的情况下,尽量使用静态变量:
1) 变量所包含的对象体积较大,占用内存较多
2) 变量所包含的对象生命周期较长
3) 变量所包含的对象数据稳定
4) 该类的对象实例有对该变量所包含的对象的共享需求
6. 对象重用与GC
通常我们把用来缓存对象的容器对象成为对象池(Object Pool)。对象池通过对其所保存对象的共享与重用,缩减了应用线程反复重建、装载对象的过程所需的时间,有效避免了频繁GC带来的巨大系统开销,能大大提高应用性能,减少内存需求。
但如果长时间将对象保存在对象池中,即驻留在内存中,而这些对象又不被经常使用,无疑会造成内存资源浪费,又或者该对象在对象池中遭到破坏,若不对其及时清除会非常麻烦。因此,若决定使用对象池技术,需要采取相应的手段清除遭到破坏的对象,甚至在某些情况下需要清除对象池中所有对象。或者可为对象池中的每个对象分配一个时间戳,设定对象的过期时间,对象过期则及时将其从内存中清除。可以专门创建一个线程来清除此类对象。
例:
class CleanUpThread extends Thread { private ObjectPool pool; private long sleepTime; CleanUpThread(ObjectPool pool, long sleepTime) { this.pool = pool; this.sleepTime = sleepTime; } public void run() { while (true) { try { sleep(sleepTime); } catch (InterruptedException e) { …// 相应处理 } pool.cleanUp(); } } }
7. transient变量
在做远程方法调用(RMI)类的应用开发时,应该会遇到transient变量与Serializable接口,之所以要对象实现Serializable接口,是因为这样就可以从远程环境以对象流的方式,将对象传递到相应的调用环境中,但有时这些被传递的对象的一些属性并不需要被传递,因为这些数据成员对于应用需求而言是无关紧要的,那么这些属性变量就可被声明为transient。被声明为transient的变量是不会被传递的,这样能节约调用方的内存资源,减少网络开销,提高系统性能。这个transient变量所携带的数据量越大(如数据量较大的数组),其效用越大。
8. JVM内存参数调优
-XX:NewSize,设置新对象成产堆内存(set new generation heap size)
通常该选项数值为1024的整数倍且大于1MB。取值规则为,取最大堆内存(maximum heap size)的1/4。
-XX:MaxNewSize,设置最大新对象生产堆内存(set maximum new generation heap size)
其功用同-XX: NewSize。
-Xms,设置堆内存池的最小值(set minimum heap size)
要求系统为堆内存池分配内存空间的最小值。通常该选项数值为1024的整数倍且大于1MB。取值规则为,取与最大堆内存(-Xmx)相同的值,以降低GC的频度。
-Xmx,设置堆内存池的最小值(set maximum heap size)
要求系统为堆内存池分配内存空间的最大值。通常该选项数值为1024的整数倍且大于1MB。取值规则为,取与最大堆内存(-Xms)相同的值,以降低GC的频度。
例:
java –XX:NewSize=128m –XX:MaxNewSize=128m –Xms512m –Xmx512m MyApp
9. Java程序设计中有关内存管理的其他经验
1) 尽早释放无用对象的引用,加速GC的工作
2) 尽量少用finalize()。finalize()是Java给程序员提供一个释放对象或资源的机会,但会加大GC的工作量
3) 对常用到的图片,可采用SoftReference
4) 注意集合数据类型,包括数组、树、图、链表等数据结构,它们对GC来说,回收更复杂。另外,注意一些全局变量、静态变量,它们易引起悬挂对象,造成内存浪费
5) 尽量避免在类的默认构造器中创建、初始化大量的对象,防止在调用其子类的构造器时造成不必要的内存资源浪费
6) 尽量避免强制系统做GC(通过显式调用System.gc()),增长系统GC的最终时间,降低系统性能
7) 尽量避免显式申请数组空间,当不得不显式申请时,尽量准确估计出其合理值
8) 在做远程方法调用(RMI)类应用开发时,尽量使用transient变量
9) 在合适的场景下使用对象池技术以提高系统性能,缩减系统内存开销,但需注意对象池的尺寸不宜过大,及时清除无效对象释放内存资源
相关推荐
4. **内存管理与垃圾回收**:JAVA的自动内存管理是通过垃圾回收机制实现的,学习笔记会解释如何理解和使用这个机制,以及如何避免内存泄漏。 5. **集合框架**:JAVA集合框架是存放和操作对象的容器,包括List、Set...
"Java学习笔记——良葛格"是一份专为初学者设计的教程资料,由良葛格精心编写,旨在帮助读者掌握JDK5.0版本的Java基础知识。JDK(Java Development Kit)是Java开发的核心工具集,包含了编译器、调试器和运行环境等...
Java 私塾课堂笔记——WebService WebService 是一种技术,使应用程序可以以与平台和编程语言无关的方式进行相互通信。它是一个软件接口,描述了一组可以在网络上通过标准化的 XML 消息传递访问的操作。WebService ...
编程学习笔记——初级 这篇笔记主要涵盖了初学者在北大青鸟学习编程时涉及的基础知识,包括DOS命令、Java和C#的基础、SQL Server的基本概念以及HTML基础等内容。以下是各个主题的详细说明: 1. DOS命令: DOS是...
Thinking in Java 自学笔记——第一章 对象导论 本章节总结了面向对象程序设计(Object-oriented Programming, OOP)的基本概念和原则,以帮助读者更好地理解 Java 编程语言。以下是对标题、描述、标签和部分内容的...
总的来说,“Java JDK 6学习笔记——ppt简体版”全面介绍了Java编程语言的基础知识和JDK 6的关键特性,结合配套的代码示例,是系统学习和掌握Java开发的宝贵资料。无论你是Java初学者还是寻求提升的老手,都能从中...
这份"Java JDK 6学习笔记——ppt简体版"提供了关于这个关键版本的详细教程,适合初学者和有一定经验的开发者来深入理解Java编程。 首先,我们要了解Java JDK是什么。Java Development Kit,简称JDK,是Oracle公司...
在Java编程语言中,NIO(New Input/Output)是一个重要的特性,它为开发者提供了非阻塞I/O操作的能力,极大地提高了程序的性能。本文主要关注的是Java NIO中的ByteBuffer,一个关键的数据容器,用于在通道(Channel)...
Java JDK 6学习笔记是为Java初学者量身定制的一份宝贵资料,它涵盖了Java编程的基础概念、语法以及核心特性。这份PPT简体版旨在帮助读者快速掌握Java开发的基本技能,逐步成为一名合格的Java程序员。 Java JDK...
Java反射机制是Java编程语言中的一个强大特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这个特性使得Java具有了高度的灵活性和动态性,尤其是在处理对象、类、接口以及它们之间的关系...
### Thinking in Java 自学笔记——第二章 一切皆对象 #### 重要概念解析 ##### 2.1 用引用操纵对象 在Java中,一切都被视为对象,这意味着无论是字符串、数字还是其他数据类型都可以被视为对象来进行操作。当...
Java学习笔记——异常 在Java编程中,异常处理是一项至关重要的技能,它允许开发者优雅地处理程序运行时可能遇到的问题,防止程序意外终止,并提供有用的反馈信息。异常是程序执行过程中遇到的不正常情况,例如除以...
11. **JVM内存管理**:了解Java虚拟机(JVM)的工作原理,包括堆内存、栈内存、方法区等,以及垃圾回收机制,对于优化程序性能至关重要。 12. **设计模式**:设计模式是解决常见软件设计问题的经验总结,如单例模式...
Java JDK 6学习笔记——PPT简体版是针对初学者和有经验的开发者们的一份宝贵资源,它深入浅出地介绍了Java编程语言的核心概念和技术。这份资料以PPT的形式呈现,使得学习过程更加直观易懂,同时包含了课程中的源代码...