软引用的回收策略在不同的JVM实现会略有不同,javadoc中说明: Virtual machine implementations are, however, encouraged to bias against clearing recently-created or recently-used soft references. 也就是说JVM不仅仅只会考虑当前内存情况,还会考虑软引用所指向的referent最近使用情况和创建时间来综合决定是否回收该referent。
public class WeakReference extends Reference {
public WeakReference(T referent) {
super(referent);
}
public WeakReference(T referent, ReferenceQueue super T> q) {
super(referent, q);
}
}
WeakReference(T referent, ReferenceQueue super T> q):与上面的构造方法比较,多了个ReferenceQueue,在对象被回收后,会把弱引用对象,也就是WeakReference对象或者其子类的对象,放入队列ReferenceQueue中,注意不是被弱引用的对象,被弱引用的对象已经被回收了。
使用示例见: 关于Java中的WeakReference -
Reference && ReferenceQueue
Reference
public abstract class Reference {
//即Reference所包装的引用对象
private T referent; /* Treated specially by GC */
//ReferenceQueue本身通过链表实现队列,ReferenceQueue对象同时保存了一个Reference类型的head节点,Reference封装了next字段,这样就是可以组成一个单向链表。
volatile ReferenceQueue super T> queue;
/* When active: NULL
* pending: this
* Enqueued: next reference in queue (or this if last)
* Inactive: this
*/
@SuppressWarnings("rawtypes")
Reference next;
/* 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
*/
//由jvm调用
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.
*/
private static Reference
Reference对象有四种状态:
active GC会特殊对待此状态的引用,一旦被引用的对象的可达性发生变化(如失去强引用,只剩弱引用,可以被回收),GC会将引用放入pending队列并将其状态改为pending状态
/* High-priority thread to enqueue pending References */
private static class ReferenceHandler extends Thread {
...
public void run() {
while (true) {
tryHandlePending(true);
}
}
}
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;
}
}
}
ReferenceQueue super Object> q = r.queue;
if (q != ReferenceQueue.NULL) q.enqueue(r);
return true;
}
Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism. Phantom Reference can be used in situations, where sometime using finalize() is not sensible thing to do.This reference type differs from the other types defined in java.lang.ref Package because it isn’t meant to be used to access the object, but as a signal that the object has already been finalized, and the garbage collector is ready to reclaim its memory.
final class Finalizer extends FinalReference {
private static ReferenceQueue queue = new ReferenceQueue<>();
private static Finalizer unfinalized = null;
private static final Object lock = new Object();
/* Invoked by VM */
static void register(Object finalizee) {
new Finalizer(finalizee);
}
private Finalizer(Object finalizee) {
super(finalizee, queue);
add();
}
private void add() {
synchronized (lock) {
if (unfinalized != null) {
this.next = unfinalized;
unfinalized.prev = this;
}
unfinalized = this;
}
}
private static class FinalizerThread extends Thread {
private volatile boolean running;
FinalizerThread(ThreadGroup g) {
super(g, "Finalizer");
}
public void run() {
if (running)
return;
// Finalizer thread starts before System.initializeSystemClass
// is called. Wait until JavaLangAccess is available
while (!VM.isBooted()) {
// delay until VM completes initialization
VM.awaitBooted();
}
final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
running = true;
for (;;) {
try {
Finalizer f = (Finalizer)queue.remove();
f.runFinalizer(jla);
} catch (InterruptedException x) {
// ignore and continue //finalize方法抛异常时不处理
}
}
}
}
private void runFinalizer(JavaLangAccess jla) {
synchronized (this) {
if (hasBeenFinalized()) return;
remove();
}
try {
Object finalizee = this.get();
if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
jla.invokeFinalize(finalizee);
/* Clear stack slot containing this variable, to decrease
the chances of false retention with a conservative GC */
finalizee = null;
}
} catch (Throwable x) { }
super.clear();
}
其中: // Finalizer thread starts before System.initializeSystemClass is called. Wait until JavaLangAccess is available 表示System.initializeSystemClass初始后sun.misc.VM#booted=true,才往下执行,否则等待。 java中System类简介(转) - 沧海一滴 - 博客园 使用JavaLangAccess和SharedSecrets来获取JVM中的实例 - yums467的专栏 - CSDN博客
public final class System {
/* register the natives via the static initializer.
*
* VM will invoke the initializeSystemClass method to complete
* the initialization for this class separated from clinit.
* Note that to use properties set by the VM, see the constraints
* described in the initializeSystemClass method.
*/
private static native void registerNatives();
static {
registerNatives();
}
private static void initializeSystemClass() {
// register shared secrets
setJavaLangAccess();
...
// Subsystems that are invoked during initialization can invoke
// sun.misc.VM.isBooted() in order to avoid doing things that should
// wait until the application class loader has been set up.
// IMPORTANT: Ensure that this remains the last initialization action!
sun.misc.VM.booted();
}
原题链接:#136 Single Number
要求:
给定一个整型数组,其中除了一个元素之外,每个元素都出现两次。找出这个元素
注意:算法的时间复杂度应为O(n),最好不使用额外的内存空间
难度:中等
分析:
题目限定了线性的时间复杂度,同时不使用额外的空间,即要求只遍历数组一遍得出结果。由于异或运算 n XOR n = 0, n XOR 0 = n,故将数组中的每个元素进
java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2281)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:
Velocity出现的目的用于简化基于MVC的web应用开发,用于替代JSP标签技术,那么Velocity如何访问Java代码.本篇继续以Velocity三http://bit1129.iteye.com/blog/2106142中的例子为基础,
POJO
package com.tom.servlets;
public
今天看org.jboss.netty.example.http.file.HttpStaticFileServerHandler.java
可以直接往channel里面写入一个FileRegion对象,而不需要相应的encoder:
//pipeline(没有诸如“FileRegionEncoder”的handler):
public ChannelPipeline ge
Zero Clipboard的实现原理
Zero Clipboard 利用透明的Flash让其漂浮在复制按钮之上,这样其实点击的不是按钮而是 Flash ,这样将需要的内容传入Flash,再通过Flash的复制功能把传入的内容复制到剪贴板。
Zero Clipboard的安装方法
首先需要下载 Zero Clipboard的压缩包,解压后把文件夹中两个文件:ZeroClipboard.js
4.1 @Order
Spring 4.2 利用@Order控制配置类的加载顺序
4.2 演示
两个演示bean
package com.wisely.spring4_2.order;
public class Demo1Service {
}
package com.wisely.spring4_2.order;
public class