*
* 虚引用在实现一个对象被回收之前必须做清理操作是很有用的,比finalize()方法更灵活
*/
public static void phantom() throws Exception
{
Object obj = new Object(); //强引用
ReferenceQueue
Reference
A Reference instance is in one of four possible internal states: 引用实例处于四种可能的内部状态之一:
Active: Some time after the collector detects that the reachability of the referent has changed to the appropriate state, it changes the instance's state to either Pending or Inactive, depending upon whether or not the instance was registered with a queue when it was created. In the former case it also adds the instance to the pending-Reference list. Newly-created instances are Active. 活跃状态
Pending: An element of the pending-Reference list, waiting to be enqueued by the Reference-handler thread. Unregistered instances are never in this state. 等待加入队列
Enqueued: An element of the queue with which the instance was registered when it was created. When an instance is removed from its ReferenceQueue, it is made Inactive. Unregistered instances are never in this state. 已经加入到队列
Inactive: Nothing more to do. Once an instance becomes Inactive its state will never change again. 最后的状态
Active: queue = ReferenceQueue with which instance is registered, or ReferenceQueue.NULL if it was not registered with a queue; next = null. 当Reference对象的queue = ReferenceQueue 或者ReferenceQueue.NULL next=null 表明 Reference对象在Active状态。
Pending: queue = ReferenceQueue with which instance is registered; next = this 当Reference对象的queue = ReferenceQueue next=this 表明 Reference对象在Pending状态。就是等待被添加到队列中的状态。
Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance in queue, or this if at end of list. 当Reference对象的queue = ReferenceQueue.ENQUEUED; next= Following instance in queue 或者 this 表明 Reference对象在Enqueued状态。表明已经被添加到了队列中。
Inactive: queue = ReferenceQueue.NULL; next = this. 这个表示把reference从队列中给删除了。
// 被包装的对象。
private T referent; /* Treated specially by GC */
// 队列。
volatile ReferenceQueue queue;
/* When active: NULL
* pending: this
* Enqueued: next reference in queue (or this if last)
* Inactive: this
*/
@SuppressWarnings("rawtypes")
Reference next; // 结合ReferenceQueue. enqueue方法来看。
/* When active: next element in a discovered reference list maintained by GC (or this if last)
* pending: next element in the pending list (or null if last)
* otherwise: NULL
*/
// 虚拟机直接控制
transient private Reference discovered; /* used by VM */
/* List of References waiting to be enqueued. The collector adds
* References to this list, while the Reference-handler thread removes
* them. This list is protected by the above lock object. The
* list uses the discovered field to link its elements.
*/
//垃圾回收器把reference对象添加到这个list, 而Reference-handler thread 将删除它们。这个list通过discovered field to link its elements.
private static Reference pending = null;
static boolean tryHandlePending(boolean waitForNotify) {
Reference r;
Cleaner c;
try {
synchronized (lock) {
if (pending != null) {
r = pending;
// 'instanceof' might throw OutOfMemoryError sometimes
// so do this before un-linking 'r' from the 'pending' chain...
c = r instanceof Cleaner ? (Cleaner) r : null;
// unlink 'r' from 'pending' chain
pending = r.discovered;
r.discovered = null;
} else {
// The waiting on the lock may cause an OutOfMemoryError
// because it may try to allocate exception objects.
if (waitForNotify) {
lock.wait();
}
// retry if waited
return waitForNotify;
}
}
} catch (OutOfMemoryError x) {
// Give other threads CPU time so they hopefully drop some live references
// and GC reclaims some space.
// Also prevent CPU intensive spinning in case 'r instanceof Cleaner' above
// persistently throws OOME for some time...
Thread.yield();
// retry
return true;
} catch (InterruptedException x) {
// retry
return true;
}
// Fast path for cleaners
if (c != null) {
c.clean();
return true;
}
ReferenceQueue q = r.queue;
if (q != ReferenceQueue.NULL) q.enqueue(r);
return true;
}
static {
ThreadGroup tg = Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread handler = new ReferenceHandler(tg, "Reference Handler");
/* If there were a special system-only priority greater than
* MAX_PRIORITY, it would be used here
*/
handler.setPriority(Thread.MAX_PRIORITY);
handler.setDaemon(true);
handler.start();
// provide access in SharedSecrets
SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
@Override
public boolean tryHandlePendingReference() {
return tryHandlePending(false);
}
});
}
ReferenceQueue
boolean enqueue(Reference r) { /* Called only by Reference class */
synchronized (lock) {
// Check that since getting the lock this reference hasn't already been
// enqueued (and even then removed)
ReferenceQueue queue = r.queue; // reference实例的注册的队列
if ((queue == NULL) || (queue == ENQUEUED)) {
return false;
}
assert queue == this;
r.queue = ENQUEUED;// reference对象已经入队了。标记。
// 插入第一个节点 head ---> head
// 插入第二个节点 head ---> next
r.next = (head == null) ? r : head; // Reference.next字段
head = r;
queueLength++;
if (r instanceof FinalReference) {
sun.misc.VM.addFinalRefCount(1);
}
lock.notifyAll();
return true;
}
}
删除节点
@SuppressWarnings("unchecked")
private Reference reallyPoll() { /* Must hold lock */
Reference r = head;
if (r != null) {
head = (r.next == r) ?
null :
r.next; // Unchecked due to the next field having a raw type in Reference
r.queue = NULL; // reference对象被移除出队列,标识。
r.next = r;
queueLength--;
if (r instanceof FinalReference) {
sun.misc.VM.addFinalRefCount(-1);
}
return r;
}
return null;
}
// 有就删除,没有就算
public Reference poll() {
if (head == null)
return null;
synchronized (lock) {
return reallyPoll();
}
}
// 有就删除, 没有的话, 等待新节点的插入, 然后删除新节点。
public Reference remove(long timeout)
throws IllegalArgumentException, InterruptedException
{
if (timeout < 0) {
throw new IllegalArgumentException("Negative timeout value");
}
synchronized (lock) {
Reference r = reallyPoll();
if (r != null) return r;
long start = (timeout == 0) ? 0 : System.nanoTime();
for (;;) {
lock.wait(timeout); // 等待新节点的插入
r = reallyPoll();
if (r != null) return r;
if (timeout != 0) {
long end = System.nanoTime();
timeout -= (end - start) / 1000_000;
if (timeout <= 0) return null;
start = end;
}
}
}
}
这里写点抛砖引玉,希望大家能把自己整理的问题及解决方法晾出来,Mark一下,利人利己。
出现问题先搜一下文档上有没有,再看看度娘有没有,再看看论坛有没有。有报错要看日志。下面简单罗列下常见的问题,大多文档上都有提到的。
1、repeated column width is largerthan paper width:
这个看这段话应该是很好理解的。比如做的模板页面宽度只能放
这个问题我实在是为整个 springsource 的员工蒙羞
如果大家使用 spring 控制事务,使用 Open Session In View 模式,
com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.
简单模拟实现数据库连接池
实例1:
package com.bijian.thread;
public class DB {
//private static final int MAX_COUNT = 10;
private static final DB instance = new DB();
private int count = 0;
private i
using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace WindowsFormsApplication1
{
Configuring Spring and JTA without full Java EE
http://spring.io/blog/2011/08/15/configuring-spring-and-jta-without-full-java-ee/
Spring doc -Transaction Management
http://docs.spring.io/spri