Reported in thread http://forum.jogamp.org/How-to-retain-a-CLBuffer-possibly-calling-clRetainMemObject-td4036615.html#a4036637 Desired usage example: try { CLProgram program = context.createProgram(Resize.class.getResourceAsStream("/kernels.cl")).build(); CLKernel kernel1 = program.createCLKernel("kernel1"); CLKernel kernel2 = program.createCLKernel("kernel2"); CLCommandQueue queue = device.createCommandQueue(); try { CLBuffer<IntBuffer> clBuffer = context.createIntBuffer(samples.length, Mem.READ_WRITE); clBuffer.registerDestructorCallback(new DebugRelease("clBuffer")); CLBuffer<IntBuffer> clBufferResult = context.createIntBuffer(samples.length, Mem.READ_WRITE); clBufferResult.registerDestructorCallback(new DebugRelease("clBufferResult")); clBuffer.getBuffer().put(samples).flip(); try { // I would expect the following to be possible calling // clRetainMemObject on //clBuffer.retain(); queue.putWriteBuffer(clBuffer, true); kernel1.rewind().putArg(clBuffer).putArg(clBufferResult).putArg(samples.length); globalWidth=samples.length; queue.put1DRangeKernel(kernel1, 0, globalWidth, workGroupWidth); queue.putReadBuffer(clBufferResult, true); //Ideally this line should not be needed queue.putReadBuffer(clBuffer, true); IntBuffer intBuffer = clBufferResult.getBuffer(); // ....process results from first kernel clBufferResult.release(); //Ideally this line should not be needed //clBuffer.release(); //ShortBuffer tempBuffer = (ShortBuffer) clBuffer.getBuffer().rewind(); //clBuffer = context.createShortBuffer(samples.length, Mem.READ_WRITE); //clBuffer.getBuffer().put(tempBuffer).rewind(); //queue.putWriteBuffer(clBuffer, true); //... do work on host here kernel2.rewind().putArg(clBuffer).putArg(samples.length); queue.put1DRangeKernel(kernel2, 0, globalWidth, workGroupWidth); queue.putReadBuffer(clBuffer, true); // ...use result } finally { //release the buffer we retained earlier clBuffer.release(); } } finally { queue.release(); } } finally { context.release(); }