- 浏览: 566618 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
a1641693970:
还不错,学习了
BeanUtils使用总结(二)LazyDynaBean -
zjfshowtime:
很好的办法,学习了。
ORA-28001: the password has expired -
ya654277yo:
哦,多谢分享
Apache整合Tomcat后get方式提交中文乱码问题解决 -
foolkeeper:
nice !!
jvm内存参数设定 -
tracy821:
谢谢了,找了好久才找到
关于Spring 声明式事务处理时,throws exception不回滚的问题
Java 2 平台引入了 java.lang.ref
包,其中包括的类可以让您引用对象,而不将它们留在内存中。这些类还提供了与垃圾收集器(garbage collector)之间有限的交互。
Peter Haggar 在本文中分析了 SoftReference
、WeakReference
和 PhantomReference
类的功能和行为,并就这些类的使用给出了一些编程风格上的建议。
当在 Java 2 平台中首次引入 java.lang.ref
包(其中包含 SoftReference
、WeakReference
和 PhantomReference
类)时,它的实用性显然被过分夸大了。它包含的类可能是有用的,但这些类具有的某些局限性会使它们显得不是很有吸引力,而且其应用程序也将特别局限于解决一类特定的问题。
垃圾收集概述
引用类的主要功能就是能够引用仍可以被垃圾收集器回收的对象。在引入引用类之前,我们只能使用强引用(strong reference)。举例来说,下面一行代码显示的就是强引用 obj
:
|
obj
这个引用将引用堆中存储的一个对象。只要 obj
引用还存在,垃圾收集器就永远不会释放用来容纳该对象的存储空间。
当 obj
超出范围或被显式地指定为 null
时,垃圾收集器就认为没有对这个对象的其它引用,也就可以收集它了。然而您还需要注意一个重要的细节:仅凭对象可以被收集并不意味着垃圾收集器的一次指定运行就能够回收它。由于各种垃圾收集算法有所不同,某些算法会更频繁地分析生存期较短的对象,而不是较老、生存期较长的对象。因此,一个可供收集的对象可能永远也不会被回收。如果程序在垃圾收集器释放对象之前结束,这种情况就可能会出现。因此,概括地说,您永远无法保证可供收集的对象总是会被垃圾收集器收集。
这些信息对于您分析引用类是很重要的。由于垃圾收集有着特定的性质,所以引用类实际上可能没有您原来想像的那么有用,尽管如此,它们对于特定问题来说还是很有用的类。软引用(soft reference)、弱引用(weak reference)和虚引用(phantom reference)对象提供了三种不同的方式来在不妨碍收集的情况下引用堆对象。每种引用对象都有不同的行为,而且它们与垃圾收集器之间的交互也有所不同。此外,这几个新的引用类都表现出比典型的强引用“更弱”的引用形式。而且,内存中的一个对象可以被多个引用(可以是强引用、软引用、弱引用或虚引用)引用。在进一步往下讨论之前,让我们来看看一些术语:
-
强可及对象(strongly reachable):可以通过强引用访问的对象。
-
软可及对象(softly reachable):不是强可及对象,并且能够通过软引用访问的对象。
-
弱可及对象(weakly reachable):不是强可及对象也不是软可及对象,并且能够通过弱引用访问的对象。
-
虚可及对象(phantomly reachable):不是强可及对象、软可及对象,也不是弱可及对象,已经结束的,可以通过虚引用访问的对象。
-
清除:将引用对象的 referent 域设置为
null
,并将引用类在堆中引用的对象声明为可结束的。
SoftReference 类 SoftReference
类的一个典型用途就是用于内存敏感的高速缓存。SoftReference
的原理是:在保持对对象的引用时保证在 JVM 报告内存不足情况之前将清除所有的软引用。关键之处在于,垃圾收集器在运行时可能会(也可能不会)释放软可及对象。对象是否被释放取决于垃圾收集器的算法以及垃圾收集器运行时可用的内存数量。
WeakReference 类 WeakReference
类的一个典型用途就是规范化映射(canonicalized mapping)。另外,对于那些生存期相对较长而且重新创建的开销也不高的对象来说,弱引用也比较有用。关键之处在于,垃圾收集器运行时如果碰到了弱可及对象,将释放 WeakReference
引用的对象。然而,请注意,垃圾收集器可能要运行多次才能找到并释放弱可及对象。
PhantomReference 类 PhantomReference
类只能用于跟踪对被引用对象即将进行的收集。同样,它还能用于执行 pre-mortem 清除操作。PhantomReference
必须与 ReferenceQueue
类一起使用。需要 ReferenceQueue
是因为它能够充当通知机制。当垃圾收集器确定了某个对象是虚可及对象时,PhantomReference
对象就被放在它的 ReferenceQueue
上。将 PhantomReference
对象放在 ReferenceQueue
上也就是一个通知,表明 PhantomReference
对象引用的对象已经结束,可供收集了。这使您能够刚好在对象占用的内存被回收之前采取行动。
垃圾收集器和引用交互
垃圾收集器每次运行时都可以随意地释放不再是强可及的对象占用的内存。如果垃圾收集器发现了软可及对象,就会出现下列情况:
-
SoftReference
对象的 referent 域被设置为null
,从而使该对象不再引用heap
对象。
-
SoftReference
引用过的heap
对象被声明为finalizable
。
- 当
heap
对象的finalize()
方法被运行而且该对象占用的内存被释放,SoftReference
对象就被添加到它的ReferenceQueue
(如果后者存在的话)。
如果垃圾收集器发现了弱可及对象,就会出现下列情况:
-
WeakReference
对象的 referent 域被设置为null
,从而使该对象不再引用heap
对象。
-
WeakReference
引用过的heap
对象被声明为finalizable
。
- 当
heap
对象的finalize()
方法被运行而且该对象占用的内存被释放时,WeakReference
对象就被添加到它的ReferenceQueue
(如果后者存在的话)。
如果垃圾收集器发现了虚可及对象,就会出现下列情况:
-
PhantomReference
引用过的heap
对象被声明为finalizable
。
- 与软引用和弱引用有所不同,
PhantomReference
在堆对象被释放之前就被添加到它的ReferenceQueue
。(请记住,所有的PhantomReference
对象都必须用经过关联的ReferenceQueue
来创建。)这使您能够在堆对象被回收之前采取行动。
请考虑清单 1 中的代码。图 1 说明了这段代码的执行情况。
清单 1. 使用 WeakReference 及 ReferenceQueue 的示例代码
|
|
obj
这个引用将引用堆中存储的一个对象。只要 obj
引用还存在,垃圾收集器就永远不会释放用来容纳该对象的存储空间。
当 obj
超出范围或被显式地指定为 null
时,垃圾收集器就认为没有对这个对象的其它引用,也就可以收集它了。然而您还需要注意一个重要的细节:仅凭对象可以被收集并不意味着垃圾收集器的一次指定运行就能够回收它。由于各种垃圾收集算法有所不同,某些算法会更频繁地分析生存期较短的对象,而不是较老、生存期较长的对象。因此,一个可供收集的对象可能永远也不会被回收。如果程序在垃圾收集器释放对象之前结束,这种情况就可能会出现。因此,概括地说,您永远无法保证可供收集的对象总是会被垃圾收集器收集。
这些信息对于您分析引用类是很重要的。由于垃圾收集有着特定的性质,所以引用类实际上可能没有您原来想像的那么有用,尽管如此,它们对于特定问题来说还是很有用的类。软引用(soft reference)、弱引用(weak reference)和虚引用(phantom reference)对象提供了三种不同的方式来在不妨碍收集的情况下引用堆对象。每种引用对象都有不同的行为,而且它们与垃圾收集器之间的交互也有所不同。此外,这几个新的引用类都表现出比典型的强引用“更弱”的引用形式。而且,内存中的一个对象可以被多个引用(可以是强引用、软引用、弱引用或虚引用)引用。在进一步往下讨论之前,让我们来看看一些术语:
-
强可及对象(strongly reachable):可以通过强引用访问的对象。
-
软可及对象(softly reachable):不是强可及对象,并且能够通过软引用访问的对象。
-
弱可及对象(weakly reachable):不是强可及对象也不是软可及对象,并且能够通过弱引用访问的对象。
-
虚可及对象(phantomly reachable):不是强可及对象、软可及对象,也不是弱可及对象,已经结束的,可以通过虚引用访问的对象。
-
清除:将引用对象的 referent 域设置为
null
,并将引用类在堆中引用的对象声明为可结束的。
SoftReference 类 SoftReference
类的一个典型用途就是用于内存敏感的高速缓存。SoftReference
的原理是:在保持对对象的引用时保证在 JVM 报告内存不足情况之前将清除所有的软引用。关键之处在于,垃圾收集器在运行时可能会(也可能不会)释放软可及对象。对象是否被释放取决于垃圾收集器的算法以及垃圾收集器运行时可用的内存数量。
WeakReference 类 WeakReference
类的一个典型用途就是规范化映射(canonicalized mapping)。另外,对于那些生存期相对较长而且重新创建的开销也不高的对象来说,弱引用也比较有用。关键之处在于,垃圾收集器运行时如果碰到了弱可及对象,将释放 WeakReference
引用的对象。然而,请注意,垃圾收集器可能要运行多次才能找到并释放弱可及对象。
PhantomReference 类 PhantomReference
类只能用于跟踪对被引用对象即将进行的收集。同样,它还能用于执行 pre-mortem 清除操作。PhantomReference
必须与 ReferenceQueue
类一起使用。需要 ReferenceQueue
是因为它能够充当通知机制。当垃圾收集器确定了某个对象是虚可及对象时,PhantomReference
对象就被放在它的 ReferenceQueue
上。将 PhantomReference
对象放在 ReferenceQueue
上也就是一个通知,表明 PhantomReference
对象引用的对象已经结束,可供收集了。这使您能够刚好在对象占用的内存被回收之前采取行动。
垃圾收集器和引用交互
垃圾收集器每次运行时都可以随意地释放不再是强可及的对象占用的内存。如果垃圾收集器发现了软可及对象,就会出现下列情况:
-
SoftReference
对象的 referent 域被设置为null
,从而使该对象不再引用heap
对象。
-
SoftReference
引用过的heap
对象被声明为finalizable
。
- 当
heap
对象的finalize()
方法被运行而且该对象占用的内存被释放,SoftReference
对象就被添加到它的ReferenceQueue
(如果后者存在的话)。
如果垃圾收集器发现了弱可及对象,就会出现下列情况:
-
WeakReference
对象的 referent 域被设置为null
,从而使该对象不再引用heap
对象。
-
WeakReference
引用过的heap
对象被声明为finalizable
。
- 当
heap
对象的finalize()
方法被运行而且该对象占用的内存被释放时,WeakReference
对象就被添加到它的ReferenceQueue
(如果后者存在的话)。
如果垃圾收集器发现了虚可及对象,就会出现下列情况:
-
PhantomReference
引用过的heap
对象被声明为finalizable
。
- 与软引用和弱引用有所不同,
PhantomReference
在堆对象被释放之前就被添加到它的ReferenceQueue
。(请记住,所有的PhantomReference
对象都必须用经过关联的ReferenceQueue
来创建。)这使您能够在堆对象被回收之前采取行动。
请考虑清单 1 中的代码。图 1 说明了这段代码的执行情况。
清单 1. 使用 WeakReference 及 ReferenceQueue 的示例代码
|
图 1. 执行了清单 1 中行 //1、//2 和 //3 的代码之后的对象布局
图 1 显示了每行代码执行后各对象的状态。行 //1 创建 MyObject
对象,而行 //2 则创建 ReferenceQueue
对象。行 //3 创建引用其引用对象 MyObject
的 WeakReference
对象,还创建它的 ReferenceQueue
。请注意,每个对象引用(obj
、rq
及 wr
)都是强引用。要利用这些引用类,您必须取消对 MyObject
对象的强引用,方法是将 obj
设置为 null
。前面说过,如果不这样做,对象 MyObject
永远都不会被回收,引用类的任何优点都会被削弱。
每个引用类都有一个 get()
方法,而 ReferenceQueue
类有一个 poll()
方法。get()
方法返回对被引用对象的引用。在 PhantomReference
上调用 get()
总是会返回 null
。这是因为 PhantomReference
只用于跟踪收集。poll()
方法返回已被添加到队列中的引用对象,如果队列中没有任何对象,它就返回 null
。因此,执行清单 1 之后再调用 get()
和 poll()
的结果可能是:
|
现在我们假定垃圾收集器开始运行。由于 MyObject
对象没有被释放,所以 get()
和 poll()
方法将返回同样的值;obj
仍然保持对该对象进行强引用。实际上,对象布局还是没有改变,和图 1 所示的差不多。然而,请考虑下面的代码:
|
在这段代码执行后,对象布局就如图 2 所示:
图 2. obj = null; 和垃圾收集器运行后的对象布局
现在,调用 get()
和 poll()
将产生与前面不同的结果:
|
这种情况表明,MyObject
对象(对它的引用原来是由 WeakReference
对象进行的)不再可用。这意味着垃圾收集器释放了 MyObject
占用的内存,从而使 WeakReference
对象可以被放在它的 ReferenceQueue
上。这样,您就可以知道当 WeakReference
或 SoftReference
类的 get()
方法返回 null
时,就有一个对象被声明为 finalizable
,而且可能(不过不一定)被收集。只有当 heap
对象完全结束而且其内存被回收后,WeakReference
或 SoftReference
才会被放到与其关联的 ReferenceQueue
上。清单 2 显示了一个完整的可运行程序,它展示了这些原理中的一部分。这段代码本身就颇具说明性,它含有很多注释和打印语句,可以帮助您理解。
清单 2. 展示引用类原理的完整程序
import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; class MyObject { protected void finalize() throws Throwable { System.out.println("In finalize method for this object: " + this); } } class ReferenceUsage { public static void main(String args[]) { hold(); release(); } public static void hold() { System.out.println("Example of incorrectly holding a strong " + "reference"); //Create an object MyObject obj = new MyObject(); System.out.println("object is " + obj); //Create a reference queue ReferenceQueue rq = new ReferenceQueue(); //Create a weakReference to obj and associate our reference queue WeakReference wr = new WeakReference(obj, rq); System.out.println("The weak reference is " + wr); //Check to see if it's on the ref queue yet System.out.println("Polling the reference queue returns " + rq.poll()); System.out.println("Getting the referent from the " + "weak reference returns " + wr.get()); System.out.println("Calling GC"); System.gc(); System.out.println("Polling the reference queue returns " + rq.poll()); System.out.println("Getting the referent from the " + "weak reference returns " + wr.get()); } public static void release() { System.out.println(""); System.out.println("Example of correctly releasing a strong " + "reference"); //Create an object MyObject obj = new MyObject(); System.out.println("object is " + obj); //Create a reference queue ReferenceQueue rq = new ReferenceQueue(); //Create a weakReference to obj and associate our reference queue WeakReference wr = new WeakReference(obj, rq); System.out.println("The weak reference is " + wr); //Check to see if it's on the ref queue yet System.out.println("Polling the reference queue returns " + rq.poll()); System.out.println("Getting the referent from the " + "weak reference returns " + wr.get()); System.out.println("Set the obj reference to null and call GC"); obj = null; System.gc(); System.out.println("Polling the reference queue returns " + rq.poll()); System.out.println("Getting the referent from the " + "weak reference returns " + wr.get()); } }
用途和风格
这些类背后的原理就是避免在应用程序执行期间将对象留在内存中。相反,您以软引用、弱引用或虚引用的方式引用对象,这样垃圾收集器就能够随意地释放对象。当您希望尽可能减小应用程序在其生命周期中使用的堆内存大小时,这种用途就很有好处。您必须记住,要使用这些类,您就不能保留对对象的强引用。如果您这么做了,那就会浪费这些类所提供的任何好处。
另外,您必须使用正确的编程风格以检查收集器在使用对象之前是否已经回收了它,如果已经回收了,您首先必须重新创建该对象。这个过程可以用不同的编程风格来完成。选择错误的风格会导致出问题。请考虑清单 3 中从 WeakReference
检索被引用对象的代码风格:
清单 3. 检索被引用对象的风格
|
研究了这段代码之后,请看看清单 4 中从 WeakReference
检索被引用对象的另一种代码风格:
清单 4. 检索被引用对象的另一种风格
|
请比较这两种风格,看看您能否确定哪种风格一定可行,哪一种不一定可行。清单 3 中体现出的风格不一定在所有情况下都可行,但清单 4 的风格就可以。清单 3 中的风格不够好的原因在于,if
块的主体结束之后 obj
不一定是非空值。请考虑一下,如果垃圾收集器在清单 3 的行 //1 之后但在行 //2 执行之前运行会怎样。recreateIt()
方法将重新创建该对象,但它会被 WeakReference
引用,而不是强引用。因此,如果收集器在行 //2 在重新创建的对象上施加一个强引用之前运行,对象就会丢失,wr.get()
则返回 null
。
清单 4 不会出现这种问题,因为行 //1 重新创建了对象并为其指定了一个强引用。因此,如果垃圾收集器在该行之后(但在行 //2 之前)运行,该对象就不会被回收。然后,行 //2 将创建对 obj
的 WeakReference
。在使用这个 if
块之后的 obj
之后,您应该将 obj
设置为 null
,从而让垃圾收集器能够回收这个对象以充分利用弱引用。清单 5 显示了一个完整的程序,它将展示刚才我们描述的风格之间的差异。(要运行该程序,其运行目录中必须有一个“temp.fil”文件。
清单 5. 展示正确的和不正确的编程风格的完整程序。
import java.io.*; import java.lang.ref.*; class ReferenceIdiom { public static void main(String args[]) throws FileNotFoundException { broken(); correct(); } public static FileReader recreateIt() throws FileNotFoundException { return new FileReader("temp.fil"); } public static void broken() throws FileNotFoundException { System.out.println("Executing method broken"); FileReader obj = recreateIt(); WeakReference wr = new WeakReference(obj); System.out.println("wr refers to object " + wr.get()); System.out.println("Now, clear the reference and run GC"); //Clear the strong reference, then run GC to collect obj. obj = null; System.gc(); System.out.println("wr refers to object " + wr.get()); //Now see if obj was collected and recreate it if it was. obj = (FileReader)wr.get(); if (obj == null) { System.out.println("Now, recreate the object and wrap it in a WeakReference"); wr = new WeakReference(recreateIt()); System.gc(); //FileReader object is NOT pinned...there is no //strong reference to it. Therefore, the next //line can return null. obj = (FileReader)wr.get(); } System.out.println("wr refers to object " + wr.get()); } public static void correct() throws FileNotFoundException { System.out.println(""); System.out.println("Executing method correct"); FileReader obj = recreateIt(); WeakReference wr = new WeakReference(obj); System.out.println("wr refers to object " + wr.get()); System.out.println("Now, clear the reference and run GC"); //Clear the strong reference, then run GC to collect obj obj = null; System.gc(); System.out.println("wr refers to object " + wr.get()); //Now see if obj was collected and recreate it if it was. obj = (FileReader)wr.get(); if (obj == null) { System.out.println("Now, recreate the object and wrap it in a WeakReference"); obj = recreateIt(); System.gc(); //FileReader is pinned, this will not affect //anything. wr = new WeakReference(obj); } System.out.println("wr refers to object " + wr.get()); } }
总结
如果使用得当,引用类还是很有用的。然而,由于它们所依赖的垃圾收集器行为有时候无法预知,所以其实用性就会受到影响。能否有效地使用它们还取决于是否应用了正确的编程风格;关键在于您要理解这些类是如何实现的以及如何对它们进行编程。
发表评论
-
BCD Conversion in java
2016-03-31 23:39 1785/** * Copyright 2010 Firat ... -
在java代码中获取JVM参数
2014-04-08 11:16 14197近日关注性能调优,关注JMX,发现java.lang.man ... -
GC日志分析配置与工具
2013-05-08 11:32 1311-verbose:gc(打印GC日志) -Xloggc:( ... -
java 实现HTTP PROXY
2012-12-06 17:21 7530日常应用中使用过很多次代理,主要停留在配置级别。 近期无意看 ... -
运行时获取方法调用堆栈信息(java)
2012-09-14 10:53 9646前几日系统流程回调时,一个方法莫名其妙被调用,无法定位调用点。 ... -
EL表达式在tomcat7.0下的new关键字不能使用
2012-08-24 17:25 4014最近生产系统部署个小应用,服务器选型tomcat7.0,一直运 ... -
xfire设置连接超时问题
2012-08-01 17:25 5099近期使用xfire作为客户端访问WS,结果因为目标主机假死 ... -
将多个对象写到一个文件
2012-07-20 17:08 1185来看一段ObjectOutputStream构造方法的源代码 ... -
多线程学习笔记:synchronized
2011-12-15 17:32 807Java语言的关键字,当它 ... -
(转)使用 Eclipse Memory Analyzer 检测内存泄漏问题
2011-12-14 18:10 1091本文是关于在开发 Talend RCP 过程中碰 ... -
多线程学习笔记:thread 线程中的sleep()、wait()、yield()、join()
2011-12-14 17:46 12421.sleep()方法 在指定时间内让当前正在执行的线程暂 ... -
jconsole监控JVM
2011-12-12 17:46 1523本地监控: Jconsole [processed] ... -
Java 6 JVM参数选项大全(中文版)
2011-11-03 15:19 993本文 是基于最新的SUN官方 文档Java SE 6 ... -
Java实现远程屏幕监视
2011-10-19 17:40 696Robot robot = new Robot(); / ... -
java线程池 常用方法
2011-09-24 22:52 1347在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于 ... -
JAVA 调用Web Service的方法
2011-08-15 10:28 11161.使用HttpClient 用到的jar文件:comm ... -
JVM监控工具--jvmstat
2011-08-02 15:42 1232首先就是下载这个工具链接:http://java.sun.co ... -
java性能优化
2011-07-18 15:19 1071一、避免在循环条件中 ... -
jvm内存参数设定
2011-07-17 20:30 1322在开发java应用时经常出 ... -
怎样解决Java内存泄漏
2011-07-15 11:38 1423解决Java 内存泄漏 Java内存泄漏是每个 ...
相关推荐
《Java EE实用开发指南:基于Weblogic+EJB3+Struts2+Hibernate+Spring》是一本讲解如何使用Weblogicl0.3+EJB3+JPA+Struts2+Hibernate+Spring开发Java Web应用程序的实用性图书,书中在具体讲解SSH2开发技术的同时,...
国内知名的高端IT技术作家,已出版《Spring 2.0宝典》、《基于J2EE的Ajax宝典》、《轻量级J2EE企业应用实战》、《Struts 2权威指南》、《Ruby On Rails敏捷开发最佳实践》等著作。 目录: 第0章 学习Java...
使用Validate类 强制一个测试用例失败 设置automation speed 访问测试用例和测试套件的上下文 高级代码示例 如何做基于图像的自动化 如何查找和比较图像 处理意外出现的对话框 [数据连接器] 管理数据源 数据...
, 基于最新Java SE 8,完整且准确地阐述Java编程语言及其规范,是深度了解Java语言及其技术细节的权威参考书。, 本书由Java技术的发明者编写,是Java编程语言的权威性技术指南。如果你想知道Java语言构造的精确含义...
Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。 当Velocity应用于web开发时,界面设计人员可以和java程序开发人员...
第2部分 在两层客户/服务器结构中使用JDBC和SQL 第5章 使用JDBC和SQL创建表 5.1 创建数据库 5.2 使用表 5.2.1 记录和字段、行和列 5.2.2 SQL数据类型 5.2.3 完整性约束 5.3 创建表 5.4 使用JDBC创建表 ...
第2部分 在两层客户/服务器结构中使用JDBC和SQL 第5章 使用JDBC和SQL创建表 5.1 创建数据库 5.2 使用表 5.2.1 记录和字段、行和列 5.2.2 SQL数据类型 5.2.3 完整性约束 5.3 创建表 5.4 使用JDBC创建表 ...
[Mandatory]禁止使用已弃用的类或方法。 注意:例如,应使用decode(String source, Stringencode)而不是已弃用的方法decode(StringencodeStr)。一旦接口被弃用,接口提供者就有义务提供新的接口。同时,客户端程序员...
3.2.6 使用快速修正功能来修改Java错误..... 82 3.2.7 重构..... 83 3.2.8 使用代码模板..... 86 3.2.9 字符串外部化..... 87 3.2.10 生成Javadoc.. 88 3.2.11 在不同的JRE下编写 Java代码..... 90 3.2.12 编译...
Tcl解释器已经从Unix平台移植到了DOS、Windows、OS/2、NT以及Macintosh环境中,而TK工具包也从X window系统移植到了Windows和Macintosh环境中。 1988年,当我在Berkeley做ousterhout教授的博士生时,第一次听说了...
第2部分 在两层客户/服务器结构中使用JDBC和SQL 第5章 使用JDBC和SQL创建表 5.1 创建数据库 5.2 使用表 5.2.1 记录和字段、行和列 5.2.2 SQL数据类型 5.2.3 完整性约束 5.3 创建表 5.4 使用JDBC创建表 ...
第2部分 在两层客户/服务器结构中使用JDBC和SQL 第5章 使用JDBC和SQL创建表 5.1 创建数据库 5.2 使用表 5.2.1 记录和字段、行和列 5.2.2 SQL数据类型 5.2.3 完整性约束 5.3 创建表 5.4 使用JDBC创建表 ...
青云 API Java封装库 使用指南 背景介绍 Fit2Cloud是一个建立在IaaS之上的云管理及DevOps协作平台,帮助开发人员、测试人员以及运维人员实现应用全生命周期的自动化管理,包括创建环境、软件安装、代码部署、自动...
Velocity是一个基于Java的模版引擎。它允许web 页面设计者引用JAVA代码预定义的方法。Web 设计者可以根据MVC模式和JAVA程序员并行工作,这意味着Web设计者可以单独专注于设计良好的站点,而程序员则可单独专注于编写...
这意味着,在学会了ANTLR语法之后,你就可以重回自己熟悉的Java领域来实现真正的语言类应用程序。 ANTLR 3的LL(*)语法分析策略不如ANTLR 4的ALL(*)强大,所以ANTLR 3为了能够正确识别输入的文本,有时候不得不进行...
《JavaScript权威指南(第6版)》主要讲述的内容涵盖JavaScript语言本身,以及Web浏览器所实现的JavaScript API。本书第6版涵盖了HTML5和ECMAScript 5,很多章节完全重写,增加了当今Web开发的最佳实践的内容,新增...
velocity学习指南 Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。
本文的容就是设计一个基于java的考试系统,可以基本实现学生、教师以及管理员所需 要的功能。在系统的设计中,学生通过登入系统,实时提交解答。系统能保存结果,供 教师披阅,并能自动根据条件对客观题进行判分,...
Velocity是基于Java的模板引擎。它允许Web页面开发者引用Java代码中定义的方法。Web设计者可以和Java程序开发者并行开发遵循MVC模式的Web站点。这意味着,Web设计者可以将精力放在好的Web站点设计上,而Java程序...