Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion java-bigquery-jdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,12 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED</argLine>
<!--
java.nio is opened for Arrow's off-heap memory access. java.util.logging is opened
so BigQueryJdbcCustomLoggerTest can read the JDK-internal child-logger list and
assert that driver objects do not leak logger registrations.
-->
<argLine>--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED --add-opens=java.logging/java.util.logging=ALL-UNNAMED</argLine>
</configuration>
</plugin>
<plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
import java.util.Map;

class BigQueryCallableStatement extends BigQueryPreparedStatement implements CallableStatement {
private final BigQueryJdbcCustomLogger LOG = new BigQueryJdbcCustomLogger(this.toString());
private static final BigQueryJdbcCustomLogger LOG =
new BigQueryJdbcCustomLogger(BigQueryCallableStatement.class.getName());
private boolean lastReadWasNull = false;

private Object getParameterAndTrackNull(int parameterIndex) throws SQLException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@
*/
public class BigQueryConnection extends BigQueryNoOpsConnection {

private final BigQueryJdbcCustomLogger LOG = new BigQueryJdbcCustomLogger(this.toString());
private static final BigQueryJdbcCustomLogger LOG =
new BigQueryJdbcCustomLogger(BigQueryConnection.class.getName());
String connectionClassName = this.toString();
private final String connectionId;
private static final String DEFAULT_JDBC_TOKEN_VALUE = "Google-BigQuery-JDBC-Driver";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
* @see BigQueryStatement
*/
class BigQueryDatabaseMetaData implements DatabaseMetaData {
final BigQueryJdbcCustomLogger LOG = new BigQueryJdbcCustomLogger(this.toString());
static final BigQueryJdbcCustomLogger LOG =
new BigQueryJdbcCustomLogger(BigQueryDatabaseMetaData.class.getName());
private static final String DATABASE_PRODUCT_NAME = "Google BigQuery";
private static final String DATABASE_PRODUCT_VERSION = "2.0";
private static final String DRIVER_NAME = "GoogleJDBCDriverForGoogleBigQuery";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ protected BigQueryJdbcCustomLogger(String name, String resourceBundleName) {

public BigQueryJdbcCustomLogger(String name) {
this(name, null);
this.setParent(BigQueryJdbcRootLogger.getRootLogger());
}

private void logWithCaller(Level level, Supplier<String> msgSupplier) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
import javax.sql.StatementEventListener;

class BigQueryPooledConnection implements PooledConnection {
private final BigQueryJdbcCustomLogger LOG = new BigQueryJdbcCustomLogger(this.toString());
private static final BigQueryJdbcCustomLogger LOG =
new BigQueryJdbcCustomLogger(BigQueryPooledConnection.class.getName());

private String id; // Mainly for internal use
private Connection bqConnection;
Expand Down Expand Up @@ -165,7 +166,8 @@ public void removeStatementEventListener(StatementEventListener arg0) {
// This class notifies the listeners or calls the listner notification methods
// provided by the pooled connection.
static class BigQueryPooledConnectionWrapper implements Connection {
private final BigQueryJdbcCustomLogger LOG = new BigQueryJdbcCustomLogger(this.toString());
private static final BigQueryJdbcCustomLogger LOG =
new BigQueryJdbcCustomLogger(BigQueryPooledConnectionWrapper.class.getName());
private Connection bqConnectionDelegate;
private BigQueryPooledConnection pooledConnection;
private boolean closed = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@
*/
public class BigQueryStatement extends BigQueryNoOpsStatement {

private final BigQueryJdbcCustomLogger LOG = new BigQueryJdbcCustomLogger(this.toString());
private static final BigQueryJdbcCustomLogger LOG =
new BigQueryJdbcCustomLogger(BigQueryStatement.class.getName());
public static final int DEFAULT_BUFFER_SIZE = BigQuerySettings.DEFAULT_NUM_BUFFERED_ROWS * 2;
static final int DEFAULT_ARROW_BUFFER_SIZE = 32;
private static final String DEFAULT_DATASET_NAME = "_google_jdbc";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
* registered with a naming service based on the Java™ Naming and Directory (JNDI) API.
*/
public class DataSource implements javax.sql.DataSource {
private final BigQueryJdbcCustomLogger LOG = new BigQueryJdbcCustomLogger(this.toString());
private static final BigQueryJdbcCustomLogger LOG =
new BigQueryJdbcCustomLogger(DataSource.class.getName());
private String URL;
static final ImmutableSet<Integer> VALID_JOB_CREATION_MODES = ImmutableSet.of(1, 2);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
import javax.sql.PooledConnection;

public class PooledConnectionListener implements ConnectionEventListener {
private final BigQueryJdbcCustomLogger LOG = new BigQueryJdbcCustomLogger(this.toString());
private static final BigQueryJdbcCustomLogger LOG =
new BigQueryJdbcCustomLogger(PooledConnectionListener.class.getName());
private String id; // Mainly for internal use
private LinkedBlockingDeque<PooledConnection> connectionPool;
private Long connectionPoolSize = 0L;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.FieldList;
Expand All @@ -37,6 +39,7 @@
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.apache.arrow.vector.util.JsonStringArrayList;
import org.apache.arrow.vector.util.JsonStringHashMap;
import org.junit.jupiter.api.AfterEach;
Expand All @@ -49,6 +52,8 @@ public class BigQueryJdbcCustomLoggerTest extends BigQueryJdbcLoggingBaseTest {
private BigQueryJdbcCustomLogger logger;
private TestHandler testHandler;

private static final int OBJECT_COUNT = 1_000;

private static class TestHandler extends Handler {
private final List<LogRecord> records = new ArrayList<>();

Expand Down Expand Up @@ -579,4 +584,69 @@ public void testNestedArrayInJsonStructConnectionIdPropagation() throws Exceptio
"Log from Nested JSON Array",
() -> nestedArray.LOG.fine("Log from Nested JSON Array"));
}

@Test
public void testLoggerIsParentedToDriverRootLogger() {
assertSame(
BigQueryJdbcRootLogger.getRootLogger(),
new BigQueryJdbcCustomLogger("ParentCheck").getParent());
}

@Test
public void testCreatingStatementsDoesNotRegisterChildLoggers() throws Exception {
BigQueryConnection connection = mock(BigQueryConnection.class);
doReturn("leak-test-connection").when(connection).getConnectionId();
doReturn(BigQueryConnection.SessionState.empty()).when(connection).getSessionStateSnapshot();

Logger rootLogger = BigQueryJdbcRootLogger.getRootLogger();
// Warm up so that any one-time, class-level logger is registered before we measure.
new BigQueryStatement(connection);
int childrenBefore = childLoggerCount(rootLogger);

for (int i = 0; i < OBJECT_COUNT; i++) {
new BigQueryStatement(connection);
}

assertEquals(
childrenBefore,
childLoggerCount(rootLogger),
"Creating "
+ OBJECT_COUNT
+ " statements must not register additional child loggers on the driver root logger");
}

@Test
public void testCreatingDatabaseMetaDataDoesNotRegisterChildLoggers()
throws ReflectiveOperationException {
BigQueryConnection connection = mock(BigQueryConnection.class);
doReturn("leak-test-connection").when(connection).getConnectionId();

Logger rootLogger = BigQueryJdbcRootLogger.getRootLogger();
new BigQueryDatabaseMetaData(connection);
int childrenBefore = childLoggerCount(rootLogger);

for (int i = 0; i < OBJECT_COUNT; i++) {
new BigQueryDatabaseMetaData(connection);
}

assertEquals(
childrenBefore,
childLoggerCount(rootLogger),
"Creating "
+ OBJECT_COUNT
+ " DatabaseMetaData objects must not register additional child loggers on the driver"
+ " root logger");
}

/**
* Reads the JDK-internal {@code Logger.kids} list. This field is private to {@code java.logging},
* so the surefire {@code argLine} opens {@code java.util.logging} to the test classpath.
*/
private static int childLoggerCount(Logger logger) throws ReflectiveOperationException {
// Qualified because this file already imports com.google.cloud.bigquery.Field.
java.lang.reflect.Field kids = Logger.class.getDeclaredField("kids");
kids.setAccessible(true);
List<?> children = (List<?>) kids.get(logger);
return children == null ? 0 : children.size();
}
}
Loading