最近工作上收到一个测试问题,在小米4等部分机型上应用容易闪退。然后查到原因是内存溢出,这里记录一下。
错误信息:
然后定位到GL2JNIView这个类
根据错误信息可以知道是创建线程时出现内存溢出,然后再看一下YUVThread
class YUVBufferThread extends Thread {
private YUVBuffer yuvBuf;
private boolean isStopThread;
public void stopThread(){
isStopThread = true;
}
@Override
public void run() {
while (GL2JNIView.this.startReceiveBuf && !this.isStopThread) {
try {
if (mBufQueue != null){
yuvBuf = mBufQueue.take();
}
if (yuvBuf != null) {
synchronized (lockObj) {
if (!m_is3d) {
if (y != null && u != null && v != null) {
GL2JNIView.this.y.clear();
GL2JNIView.this.u.clear();
GL2JNIView.this.v.clear();
yuvBuf.buf.position(0);
yuvBuf.buf.get(yByteArr, 0, yByteArr.length);
yuvBuf.buf.get(uByteArr, 0, uByteArr.length);
yuvBuf.buf.get(vByteArr, 0, vByteArr.length);
yuvBuf.buf.position(0);
GL2JNIView.this.y.put(yByteArr, 0, yByteArr.length);
GL2JNIView.this.u.put(uByteArr, 0, uByteArr.length);
GL2JNIView.this.v.put(vByteArr, 0, vByteArr.length);
}
} else {
int size = yuvBuf.buf.limit();
if (m_disOld != true && yuvByteArr != null /*&& size>=yByteArr.length+uByteArr.length+vByteArr.length*/)//m_disOld
{
yuvBuf.buf.position(0);
yuvBuf.buf.get(yuvByteArr, 0, yByteArr.length + uByteArr.length + vByteArr.length);
yuvBuf.buf.position(0);
}
}
yuvBuf = null;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
问题在这行代码:
yuvBuf = mBufQueue.take();
这里使用了一个LinkedBlockingQueue队列不断的取出YUV数据,这里使用take()方式取数据就出现了问题,当队列里面没有元素时,它会阻塞线程从而导致线程不能退出。
下面贴一下take
的源码:
/**
* Retrieves and removes the head of this queue, waiting if necessary
* until an element becomes available.
*
* @return the head of this queue
* @throws InterruptedException if interrupted while waiting
*/
E take() throws InterruptedException;
除了take方法,还有poll方法,同样看一下源码注释:
/**
* Retrieves and removes the head of this queue, waiting up to the
* specified wait time if necessary for an element to become available.
*/
E poll(long timeout, TimeUnit unit)
throws InterruptedException;
这个方法能设置阻塞时间,所以这里使用poll方法代替take就能解决问题了。
总结##
在开发中要多去看源码,这样我们才能更好的理解没一个方法的作用,从而使用正确的Api来实现我们的需求。