• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #18822

07 Sep 2023 08:15PM UTC coverage: 88.321% (+0.02%) from 88.302%
#18822

push

github-actions

ejona86
netty: Touch ByteBuf when message framing has been decoded

When a memory leak occurs, it is really helpful to have access records
to understand where the buffer was being held when it leaked. retain()
when we create the NettyReadableBuffer already creates an access record
the ByteBuf, so here we track when the ByteBuf is passed to another
thread.

See #8330

30349 of 34362 relevant lines covered (88.32%)

0.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.59
/../netty/src/main/java/io/grpc/netty/NettyReadableBuffer.java
1
/*
2
 * Copyright 2014 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc.netty;
18

19
import com.google.common.base.Preconditions;
20
import io.grpc.internal.AbstractReadableBuffer;
21
import io.netty.buffer.ByteBuf;
22
import java.io.IOException;
23
import java.io.OutputStream;
24
import java.nio.ByteBuffer;
25

26
/**
27
 * A {@link java.nio.Buffer} implementation that is backed by a Netty {@link ByteBuf}. This class
28
 * does not call {@link ByteBuf#retain}, so if that is needed it should be called prior to creating
29
 * this buffer.
30
 */
31
class NettyReadableBuffer extends AbstractReadableBuffer {
32
  private final ByteBuf buffer;
33
  private boolean closed;
34

35
  NettyReadableBuffer(ByteBuf buffer) {
1✔
36
    this.buffer = Preconditions.checkNotNull(buffer, "buffer");
1✔
37
  }
1✔
38

39
  ByteBuf buffer() {
40
    return buffer;
1✔
41
  }
42

43
  @Override
44
  public int readableBytes() {
45
    return buffer.readableBytes();
1✔
46
  }
47

48
  @Override
49
  public void skipBytes(int length) {
50
    buffer.skipBytes(length);
×
51
  }
×
52

53
  @Override
54
  public int readUnsignedByte() {
55
    return buffer.readUnsignedByte();
1✔
56
  }
57

58
  @Override
59
  public void readBytes(byte[] dest, int index, int length) {
60
    buffer.readBytes(dest, index, length);
1✔
61
  }
1✔
62

63
  @Override
64
  public void readBytes(ByteBuffer dest) {
65
    buffer.readBytes(dest);
1✔
66
  }
1✔
67

68
  @Override
69
  public void readBytes(OutputStream dest, int length) {
70
    try {
71
      buffer.readBytes(dest, length);
1✔
72
    } catch (IOException e) {
×
73
      throw new RuntimeException(e);
×
74
    }
1✔
75
  }
1✔
76

77
  @Override
78
  public NettyReadableBuffer readBytes(int length) {
79
    return new NettyReadableBuffer(buffer.readRetainedSlice(length));
1✔
80
  }
81

82
  @Override
83
  public boolean hasArray() {
84
    return buffer.hasArray();
×
85
  }
86

87
  @Override
88
  public byte[] array() {
89
    return buffer.array();
×
90
  }
91

92
  @Override
93
  public int arrayOffset() {
94
    return buffer.arrayOffset() + buffer.readerIndex();
×
95
  }
96

97
  @Override
98
  public void touch() {
99
    buffer.touch();
×
100
  }
×
101

102
  @Override
103
  public boolean markSupported() {
104
    return true;
×
105
  }
106

107
  @Override
108
  public void mark() {
109
    buffer.markReaderIndex();
1✔
110
  }
1✔
111

112
  @Override
113
  public void reset() {
114
    buffer.resetReaderIndex();
1✔
115
  }
1✔
116

117
  @Override
118
  public boolean byteBufferSupported() {
119
    return buffer.nioBufferCount() > 0;
1✔
120
  }
121

122
  @Override
123
  public ByteBuffer getByteBuffer() {
124
    return buffer.nioBufferCount() == 1 ? buffer.nioBuffer() : buffer.nioBuffers()[0];
1✔
125
  }
126

127
  /**
128
   * If the first call to close, calls {@link ByteBuf#release} to release the internal Netty buffer.
129
   */
130
  @Override
131
  public void close() {
132
    // Don't allow slices to close. Also, only allow close to be called once.
133
    if (!closed) {
1✔
134
      closed = true;
1✔
135
      buffer.release();
1✔
136
    }
137
  }
1✔
138
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc