由于线上问题是由大量的WeakOrderQueue$Link对象引起的,而这些对象都是unreachable,为了研究线上问题的原因,尝试重新构建出WeakOrderQueue$Link的unreachable。
仓库:https://github.com/shangjianan2/testNetty.git
代码
主代码
package test.recycler;
import io.netty.util.Recycler;
import io.netty.util.concurrent.FastThreadLocalThread;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* -XX:MaxTenuringThreshold=0 -Xms256m -Xmx256m -Xmn512k
*/
public class RecycleMultiThread3 {
private static final Recycler<User> RECYCLER = new Recycler<User>() {
//没有对象的时候,新建一个对象, 会传入一个handler,在Recycler池里,所有的对象都会转成DefaultHandle对象
@Override
protected User newObject(Handle<User> handle) {
return new User(handle);
}
};
private static Object lock = new Object();
private static class User {
private final Recycler.Handle<User> handle;
public User(Recycler.Handle<User> handle) {
this.handle = handle;
}
public void recycle() {
//通过handler进行对象的回收
handle.recycle(this);
}
}
public static void main(String[] args) throws Exception {
new RecycleMultiThread3().test();
new RecycleMultiThread3().test();
new RecycleMultiThread3().test();
new RecycleMultiThread3().test();
new RecycleMultiThread3().test();
new RecycleMultiThread3().test();
new RecycleMultiThread3().test();
new RecycleMultiThread3().test();
System.out.println("main over");
while (true) {
Thread.sleep(1000);
System.out.println("1");
}
}
public void test() throws Exception {
ConcurrentLinkedQueue<User> q = new ConcurrentLinkedQueue();
final int size = 160;
System.out.println("begin");
final List<User> list1 = new ArrayList<User>();
FastThreadLocalThread thread = new FastThreadLocalThread(new Runnable() {
@Override
public void run() {
Thread t = Thread.currentThread();
for (int i = 0; i < size; ++i) {
q.add(RECYCLER.get());
}
FastThreadLocalThread thread2 = new FastThreadLocalThread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < size; ++i) {
User poll = q.poll();
poll.recycle();
}
System.out.println("thread2 over");
}
});
thread2.start();
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//触发young gc
for (int i = 0; i < 5; ++i) {
YoungGC.gc();
}
//产生不可达
for (int i = 0; i < size; ++i) {
q.add(RECYCLER.get());
}
//触发young gc
for (int i = 0; i < 5; ++i) {
YoungGC.gc();
}
System.out.println("1111");
}
});
thread.start();
thread.join();
System.out.println("=======================over===================================");
}
}
负责young gc的代码
package test.recycler;
public class YoungGC {
public static class A {
public long[] aa = new long[128];//1k
}
public static void main(String[] args) throws InterruptedException {
System.out.println("hello world!");
for (int i = 0;; ++i) {
gc();
Thread.sleep(1000);
System.out.println(i);
}
}
public static void gc() {
for (int i = 0; i < 512; ++i) {
A a = new A();
}
}
}
使用代码时注意配置jvm参数:-XX:MaxTenuringThreshold=0 -Xms256m -Xmx256m -Xmn512k
分析堆内存
上图显示有八个不可达对象,对应着八个线程。下面的Link节点虽然没显示unreachable,但是实际上他们的头节点都是那八个unreachable对象,所以他们当中大部分是不可达的。
但是也不是说所有的Link节点都是这种简单的引用状态。Netty中一旦Link链表建立,即使Link链表中所有存储的对象都被消耗,Netty缓冲池中的一些指针也会指向链表中最后一个Link。这种Link有一个特点,就是
Retained Heap
特别小