From e05c892271902ccdeb7ebd31eb3d1ea3c289be5f Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Tue, 14 Jan 2020 11:11:06 -0800 Subject: [PATCH 01/37] Begin 0.42.0 --- dd-trace-java.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-trace-java.gradle b/dd-trace-java.gradle index 96b93f05b7..0252c35a52 100644 --- a/dd-trace-java.gradle +++ b/dd-trace-java.gradle @@ -16,7 +16,7 @@ def isCI = System.getenv("CI") != null allprojects { group = 'com.datadoghq' - version = '0.41.0' + version = '0.42.0-SNAPSHOT' if (isCI) { buildDir = "${rootDir}/workspace/${projectDir.path.replace(rootDir.path, '')}/build/" From e31cbd6c89bfff105f6da5030bd7457e1f709d43 Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Tue, 14 Jan 2020 17:05:05 -0800 Subject: [PATCH 02/37] Add Builder to DDTracer Deprecate previous constructors. --- .../trace/agent/tooling/TracerInstaller.java | 2 +- .../trace/agent/test/AgentTestRunner.java | 2 +- .../java/datadog/opentracing/DDTracer.java | 87 ++++++++++++++--- .../resolver/DDTracerResolver.java | 2 +- .../groovy/OT31ApiTest.groovy | 2 +- .../groovy/OT33ApiTest.groovy | 2 +- .../opentracing/DDSpanBuilderTest.groovy | 4 +- .../DDSpanSerializationTest.groovy | 4 +- .../datadog/opentracing/DDSpanTest.groovy | 6 +- .../opentracing/PendingTraceTest.groovy | 6 +- .../datadog/opentracing/SpanFactory.groovy | 4 +- .../opentracing/TraceCorrelationTest.groovy | 2 +- .../opentracing/TraceInterceptorTest.groovy | 2 +- .../decorators/SpanDecoratorTest.groovy | 97 +++++++------------ .../decorators/URLAsResourceNameTest.groovy | 2 +- .../propagation/B3HttpInjectorTest.groovy | 2 +- .../DatadogHttpInjectorTest.groovy | 2 +- .../HaystackHttpInjectorTest.groovy | 2 +- .../propagation/HttpInjectorTest.groovy | 2 +- .../groovy/datadog/trace/DDTracerTest.groovy | 31 +++--- .../sampling/RateByServiceSamplerTest.groovy | 6 +- .../groovy/DDApiIntegrationTest.groovy | 2 +- 22 files changed, 154 insertions(+), 117 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/TracerInstaller.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/TracerInstaller.java index a9d9e04041..88370ab63b 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/TracerInstaller.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/TracerInstaller.java @@ -11,7 +11,7 @@ public class TracerInstaller { public static synchronized void installGlobalTracer() { if (Config.get().isTraceEnabled()) { if (!io.opentracing.util.GlobalTracer.isRegistered()) { - final DDTracer tracer = new DDTracer(); + final DDTracer tracer = DDTracer.builder().build(); try { io.opentracing.util.GlobalTracer.register(tracer); datadog.trace.api.GlobalTracer.registerIfAbsent(tracer); diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/AgentTestRunner.java b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/AgentTestRunner.java index 894caba16f..6c93f4cc66 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/AgentTestRunner.java +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/AgentTestRunner.java @@ -95,7 +95,7 @@ public abstract class AgentTestRunner extends DDSpecification { return result; } }; - TEST_TRACER = new DDTracer(TEST_WRITER); + TEST_TRACER = DDTracer.builder().writer(TEST_WRITER).build(); GlobalTracerUtils.registerOrReplaceGlobalTracer((Tracer) TEST_TRACER); GlobalTracer.registerIfAbsent((datadog.trace.api.Tracer) TEST_TRACER); } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java index ae5a0c4301..28389f839e 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java @@ -96,28 +96,68 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace private final HttpCodec.Injector injector; private final HttpCodec.Extractor extractor; + public static class Builder { + public Builder() { + // Apply the default values from config. + withConfig(Config.get()); + } + + public Builder writer(final Writer writer) { + if (this.writer != null && this.writer != writer) { + // Try to avoid leaking resources + this.writer.close(); + } + this.writer = writer; + return this; + } + + public Builder withProperties(final Properties properties) { + return withConfig(Config.get(properties)); + } + + public Builder withConfig(final Config config) { + serviceName(config.getServiceName()); + writer(Writer.Builder.forConfig(config)); + sampler(Sampler.Builder.forConfig(config)); + injector(HttpCodec.createInjector(config)); + extractor(HttpCodec.createExtractor(config, config.getHeaderTags())); + localRootSpanTags(config.getLocalRootSpanTags()); + defaultSpanTags(config.getMergedSpanTags()); + serviceNameMappings(config.getServiceMapping()); + taggedHeaders(config.getHeaderTags()); + partialFlushMinSpans(config.getPartialFlushMinSpans()); + return this; + } + } + /** By default, report to local agent and collect all traces. */ + @Deprecated public DDTracer() { this(Config.get()); } + @Deprecated public DDTracer(final String serviceName) { this(serviceName, Config.get()); } + @Deprecated public DDTracer(final Properties config) { this(Config.get(config)); } + @Deprecated public DDTracer(final Config config) { this(config.getServiceName(), config); } // This constructor is already used in the wild, so we have to keep it inside this API for now. + @Deprecated public DDTracer(final String serviceName, final Writer writer, final Sampler sampler) { this(serviceName, writer, sampler, Config.get().getLocalRootSpanTags()); } + @Deprecated private DDTracer(final String serviceName, final Config config) { this( serviceName, @@ -132,6 +172,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace } /** Visible for testing */ + @Deprecated DDTracer( final String serviceName, final Writer writer, @@ -148,10 +189,12 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace 0); } + @Deprecated public DDTracer(final Writer writer) { this(Config.get(), writer); } + @Deprecated public DDTracer(final Config config, final Writer writer) { this( config.getServiceName(), @@ -164,9 +207,6 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace config.getPartialFlushMinSpans()); } - /** - * @deprecated Use {@link #DDTracer(String, Writer, Sampler, Map, Map, Map, Map, int)} instead. - */ @Deprecated public DDTracer( final String serviceName, @@ -188,9 +228,6 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace Config.get().getPartialFlushMinSpans()); } - /** - * @deprecated Use {@link #DDTracer(String, Writer, Sampler, Map, Map, Map, Map, int)} instead. - */ @Deprecated public DDTracer( final String serviceName, @@ -211,6 +248,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace Config.get().getPartialFlushMinSpans()); } + @Deprecated public DDTracer( final String serviceName, final Writer writer, @@ -220,6 +258,34 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace final Map serviceNameMappings, final Map taggedHeaders, final int partialFlushMinSpans) { + this( + serviceName, + writer, + sampler, + HttpCodec.createInjector(Config.get()), + HttpCodec.createExtractor(Config.get(), taggedHeaders), + localRootSpanTags, + defaultSpanTags, + serviceNameMappings, + taggedHeaders, + partialFlushMinSpans); + } + + @lombok.Builder(builderClassName = "Builder") + // These field names must be stable to ensure the builder api is stable. + private DDTracer( + final String serviceName, + final Writer writer, + final Sampler sampler, + final HttpCodec.Injector injector, + final HttpCodec.Extractor extractor, + final Map localRootSpanTags, + final Map defaultSpanTags, + final Map serviceNameMappings, + final Map taggedHeaders, + final int partialFlushMinSpans) { + + assert writer != null; assert localRootSpanTags != null; assert defaultSpanTags != null; assert serviceNameMappings != null; @@ -227,13 +293,16 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace this.serviceName = serviceName; this.writer = writer; - this.writer.start(); this.sampler = sampler; + this.injector = injector; + this.extractor = extractor; this.localRootSpanTags = localRootSpanTags; this.defaultSpanTags = defaultSpanTags; this.serviceNameMappings = serviceNameMappings; this.partialFlushMinSpans = partialFlushMinSpans; + this.writer.start(); + shutdownCallback = new ShutdownHook(this); try { Runtime.getRuntime().addShutdownHook(shutdownCallback); @@ -241,10 +310,6 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace // The JVM is already shutting down. } - // TODO: we have too many constructors, we should move to some sort of builder approach - injector = HttpCodec.createInjector(Config.get()); - extractor = HttpCodec.createExtractor(Config.get(), taggedHeaders); - if (this.writer instanceof DDAgentWriter && sampler instanceof DDAgentResponseListener) { ((DDAgentWriter) this.writer).addResponseListener((DDAgentResponseListener) this.sampler); } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java b/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java index 571323780b..1522978d21 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java @@ -16,7 +16,7 @@ public class DDTracerResolver extends TracerResolver { Tracer resolve(final Config config) { if (config.isTraceResolverEnabled()) { log.info("Creating DDTracer with DDTracerResolver"); - return new DDTracer(); + return DDTracer.builder().withConfig(config).build(); } else { log.info("DDTracerResolver disabled"); return null; diff --git a/dd-trace-ot/src/ot31CompatabilityTest/groovy/OT31ApiTest.groovy b/dd-trace-ot/src/ot31CompatabilityTest/groovy/OT31ApiTest.groovy index dc0dd2d99e..a08b90a9f1 100644 --- a/dd-trace-ot/src/ot31CompatabilityTest/groovy/OT31ApiTest.groovy +++ b/dd-trace-ot/src/ot31CompatabilityTest/groovy/OT31ApiTest.groovy @@ -17,7 +17,7 @@ class OT31ApiTest extends DDSpecification { static final WRITER = new ListWriter() @Subject - Tracer tracer = new DDTracer(WRITER) + Tracer tracer = DDTracer.builder().writer(WRITER).build() def "test startActive"() { when: diff --git a/dd-trace-ot/src/ot33CompatabilityTest/groovy/OT33ApiTest.groovy b/dd-trace-ot/src/ot33CompatabilityTest/groovy/OT33ApiTest.groovy index 3e8d3811e3..371b11dada 100644 --- a/dd-trace-ot/src/ot33CompatabilityTest/groovy/OT33ApiTest.groovy +++ b/dd-trace-ot/src/ot33CompatabilityTest/groovy/OT33ApiTest.groovy @@ -13,7 +13,7 @@ class OT33ApiTest extends DDSpecification { static final WRITER = new ListWriter() @Subject - Tracer tracer = new DDTracer(WRITER) + Tracer tracer = DDTracer.builder().writer(WRITER).build() def "test start"() { when: diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy index 8ab6c32d0e..c55df14468 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy @@ -16,7 +16,7 @@ class DDSpanBuilderTest extends DDSpecification { def writer = new ListWriter() def config = Config.get() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() def "build simple span"() { setup: @@ -458,7 +458,7 @@ class DDSpanBuilderTest extends DDSpecification { setup: System.setProperty("dd.trace.span.tags", tagString) def config = new Config() - tracer = new DDTracer(config, writer) + tracer = DDTracer.builder().withConfig(config).writer(writer).build() def span = tracer.buildSpan("op name").withServiceName("foo").start() expect: diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanSerializationTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanSerializationTest.groovy index 630da87044..757f562cb0 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanSerializationTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanSerializationTest.groovy @@ -40,7 +40,7 @@ class DDSpanSerializationTest extends DDSpecification { expected.put("trace_id", 1l) def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() final DDSpanContext context = new DDSpanContext( 1G, @@ -81,7 +81,7 @@ class DDSpanSerializationTest extends DDSpecification { setup: def objectMapper = new ObjectMapper(new MessagePackFactory()) def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() def context = new DDSpanContext( value, value, diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanTest.groovy index bd87fc452a..88de2df8df 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanTest.groovy @@ -17,8 +17,8 @@ class DDSpanTest extends DDSpecification { def writer = new ListWriter() def sampler = new RateByServiceSampler() - def tracer = new DDTracer(DEFAULT_SERVICE_NAME, writer, sampler, [:]) - + def tracer = DDTracer.builder().writer(writer).sampler(sampler).build() + def "getters and setters"() { setup: final DDSpanContext context = @@ -91,7 +91,7 @@ class DDSpanTest extends DDSpecification { when: final String resourceName = "fake" final String serviceName = "myService" - span = new DDTracer() + span = DDTracer.builder().build() .buildSpan(opName) .withResourceName(resourceName) .withServiceName(serviceName) diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy index 8242e6ffd5..b987e5227f 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy @@ -23,7 +23,7 @@ class PendingTraceTest extends DDSpecification { PendingTraceTest.this.traceCount.incrementAndGet() } } - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() BigInteger traceId = BigInteger.valueOf(System.identityHashCode(this)) @@ -195,7 +195,7 @@ class PendingTraceTest extends DDSpecification { def properties = new Properties() properties.setProperty(PARTIAL_FLUSH_MIN_SPANS, "1") def config = Config.get(properties) - def tracer = new DDTracer(config, writer) + def tracer = DDTracer.builder().withConfig(config).writer(writer).build() def trace = new PendingTrace(tracer, traceId, [:]) def rootSpan = SpanFactory.newSpanOf(trace) def child1 = tracer.buildSpan("child1").asChildOf(rootSpan).start() @@ -241,7 +241,7 @@ class PendingTraceTest extends DDSpecification { def properties = new Properties() properties.setProperty(PARTIAL_FLUSH_MIN_SPANS, "1") def config = Config.get(properties) - def tracer = new DDTracer(config, writer) + def tracer = DDTracer.builder().withConfig(config).writer(writer).build() def trace = new PendingTrace(tracer, traceId, [:]) def rootSpan = SpanFactory.newSpanOf(trace) def child1 = tracer.buildSpan("child1").asChildOf(rootSpan).start() diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/SpanFactory.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/SpanFactory.groovy index c2ff699e80..5b1028c969 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/SpanFactory.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/SpanFactory.groovy @@ -8,7 +8,7 @@ class SpanFactory { static DDSpan newSpanOf(long timestampMicro, String threadName = Thread.currentThread().name) { def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() def currentThreadName = Thread.currentThread().getName() Thread.currentThread().setName(threadName) def context = new DDSpanContext( @@ -70,7 +70,7 @@ class SpanFactory { static DDSpan newSpanOf(String serviceName, String envName) { def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() def context = new DDSpanContext( 1G, 1G, diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/TraceCorrelationTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/TraceCorrelationTest.groovy index b12eee8b44..f20f03f0d5 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/TraceCorrelationTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/TraceCorrelationTest.groovy @@ -10,7 +10,7 @@ class TraceCorrelationTest extends DDSpecification { static final WRITER = new ListWriter() @Shared - DDTracer tracer = new DDTracer(WRITER) + DDTracer tracer = DDTracer.builder().writer(WRITER).build() def scope = tracer.buildSpan("test").startActive(true) diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/TraceInterceptorTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/TraceInterceptorTest.groovy index afc47d5cd4..5ccc3372bd 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/TraceInterceptorTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/TraceInterceptorTest.groovy @@ -12,7 +12,7 @@ import java.util.concurrent.atomic.AtomicBoolean class TraceInterceptorTest extends DDSpecification { def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() def "interceptor is registered as a service"() { expect: diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/SpanDecoratorTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/SpanDecoratorTest.groovy index f1386e4154..ceb265e0ff 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/SpanDecoratorTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/SpanDecoratorTest.groovy @@ -16,7 +16,6 @@ import io.opentracing.tag.Tags import static datadog.trace.api.Config.DEFAULT_SERVICE_NAME import static datadog.trace.api.DDTags.ANALYTICS_SAMPLE_RATE -import static java.util.Collections.emptyMap class SpanDecoratorTest extends DDSpecification { static { @@ -30,7 +29,7 @@ class SpanDecoratorTest extends DDSpecification { System.clearProperty("dd.$Config.SPLIT_BY_TAGS") } } - def tracer = new DDTracer(new LoggingWriter()) + def tracer = DDTracer.builder().writer(new LoggingWriter()).build() def span = SpanFactory.newSpanOf(tracer) def "adding span personalisation using Decorators"() { @@ -55,16 +54,12 @@ class SpanDecoratorTest extends DDSpecification { def "set service name"() { setup: - tracer = new DDTracer( - "wrong-service", - new LoggingWriter(), - new AllSampler(), - "some-runtime-id", - emptyMap(), - emptyMap(), - mapping, - emptyMap() - ) + tracer = DDTracer.builder() + .serviceName("wrong-service") + .writer(new LoggingWriter()) + .sampler(new AllSampler()) + .serviceNameMappings(mapping) + .build() when: def span = tracer.buildSpan("some span").withTag(tag, name).start() @@ -91,16 +86,12 @@ class SpanDecoratorTest extends DDSpecification { def "default or configured service name can be remapped without setting tag"() { setup: - tracer = new DDTracer( - serviceName, - new LoggingWriter(), - new AllSampler(), - "some-runtime-id", - emptyMap(), - emptyMap(), - mapping, - emptyMap() - ) + tracer = DDTracer.builder() + .serviceName(serviceName) + .writer(new LoggingWriter()) + .sampler(new AllSampler()) + .serviceNameMappings(mapping) + .build() when: def span = tracer.buildSpan("some span").start() @@ -138,16 +129,12 @@ class SpanDecoratorTest extends DDSpecification { def "set service name from servlet.context with context '#context' for service #serviceName"() { setup: - tracer = new DDTracer( - serviceName, - new LoggingWriter(), - new AllSampler(), - "some-runtime-id", - emptyMap(), - emptyMap(), - mapping, - emptyMap() - ) + tracer = DDTracer.builder() + .serviceName(serviceName) + .writer(new LoggingWriter()) + .sampler(new AllSampler()) + .serviceNameMappings(mapping) + .build() when: def span = tracer.buildSpan("some span").start() @@ -172,16 +159,12 @@ class SpanDecoratorTest extends DDSpecification { } static createSplittingTracer(tag) { - def tracer = new DDTracer( - "my-service", - new LoggingWriter(), - new AllSampler(), - "some-runtime-id", - emptyMap(), - emptyMap(), - emptyMap(), - emptyMap() - ) + def tracer = DDTracer.builder() + .serviceName("my-service") + .writer(new LoggingWriter()) + .sampler(new AllSampler()) + .build() + // equivalent to split-by-tags: tag tracer.addDecorator(new ServiceNameDecorator(tag, true)) @@ -477,16 +460,11 @@ class SpanDecoratorTest extends DDSpecification { System.setProperty("dd.trace." + PeerServiceDecorator.getSimpleName().toLowerCase() + ".enabled", "false") } - tracer = new DDTracer( - "some-service", - new LoggingWriter(), - new AllSampler(), - "some-runtime-id", - emptyMap(), - emptyMap(), - emptyMap(), - emptyMap() - ) + tracer = DDTracer.builder() + .serviceName("some-service") + .writer(new LoggingWriter()) + .sampler(new AllSampler()) + .build() when: def span = tracer.buildSpan("some span").withTag(Tags.PEER_SERVICE.key, "peer-service").start() @@ -507,16 +485,11 @@ class SpanDecoratorTest extends DDSpecification { System.setProperty("dd.trace." + ServiceNameDecorator.getSimpleName().toLowerCase() + ".enabled", "false") } - tracer = new DDTracer( - "some-service", - new LoggingWriter(), - new AllSampler(), - "some-runtime-id", - emptyMap(), - emptyMap(), - emptyMap(), - emptyMap() - ) + tracer = DDTracer.builder() + .serviceName("some-service") + .writer(new LoggingWriter()) + .sampler(new AllSampler()) + .build() when: def span = tracer.buildSpan("some span").withTag(tag, name).start() diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/URLAsResourceNameTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/URLAsResourceNameTest.groovy index 3c6d6522ec..8f4366c7f5 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/URLAsResourceNameTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/URLAsResourceNameTest.groovy @@ -12,7 +12,7 @@ import spock.lang.Subject class URLAsResourceNameTest extends DDSpecification { def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() @Subject def decorator = new URLAsResourceName() diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/B3HttpInjectorTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/B3HttpInjectorTest.groovy index 227d126b0b..5634abcf96 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/B3HttpInjectorTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/B3HttpInjectorTest.groovy @@ -20,7 +20,7 @@ class B3HttpInjectorTest extends DDSpecification { def "inject http headers"() { setup: def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() final DDSpanContext mockedContext = new DDSpanContext( traceId, diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpInjectorTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpInjectorTest.groovy index 80f361ae9a..b8433cc226 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpInjectorTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpInjectorTest.groovy @@ -22,7 +22,7 @@ class DatadogHttpInjectorTest extends DDSpecification { def "inject http headers"() { setup: def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() final DDSpanContext mockedContext = new DDSpanContext( traceId, diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HaystackHttpInjectorTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HaystackHttpInjectorTest.groovy index eee64fd8ce..d9f9276eeb 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HaystackHttpInjectorTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HaystackHttpInjectorTest.groovy @@ -20,7 +20,7 @@ class HaystackHttpInjectorTest extends DDSpecification { def "inject http headers"() { setup: def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() final DDSpanContext mockedContext = new DDSpanContext( traceId, diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HttpInjectorTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HttpInjectorTest.groovy index aa1cefbf39..9aed342a91 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HttpInjectorTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HttpInjectorTest.groovy @@ -25,7 +25,7 @@ class HttpInjectorTest extends DDSpecification { def spanId = 2G def writer = new ListWriter() - def tracer = new DDTracer(writer) + def tracer = DDTracer.builder().writer(writer).build() final DDSpanContext mockedContext = new DDSpanContext( traceId, diff --git a/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy b/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy index 5a7ac705c5..19ed3b7e83 100644 --- a/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy @@ -40,7 +40,7 @@ class DDTracerTest extends DDSpecification { def "verify defaults on tracer"() { when: - def tracer = new DDTracer() + def tracer = DDTracer.builder().build() then: tracer.serviceName == "unnamed-java-app" @@ -63,7 +63,7 @@ class DDTracerTest extends DDSpecification { System.setProperty(PREFIX + HEALTH_METRICS_ENABLED, "true") when: - def tracer = new DDTracer(new Config()) + def tracer = DDTracer.builder().withConfig(new Config()).build() then: tracer.writer.monitor instanceof Monitor.StatsD @@ -75,7 +75,7 @@ class DDTracerTest extends DDSpecification { setup: System.setProperty(PREFIX + PRIORITY_SAMPLING, "false") when: - def tracer = new DDTracer(new Config()) + def tracer = DDTracer.builder().withConfig(new Config()).build() then: tracer.sampler instanceof AllSampler } @@ -85,7 +85,7 @@ class DDTracerTest extends DDSpecification { System.setProperty(PREFIX + WRITER_TYPE, "LoggingWriter") when: - def tracer = new DDTracer(new Config()) + def tracer = DDTracer.builder().withConfig(new Config()).build() then: tracer.writer instanceof LoggingWriter @@ -98,8 +98,7 @@ class DDTracerTest extends DDSpecification { System.setProperty(PREFIX + HEADER_TAGS, mapString) when: - def config = new Config() - def tracer = new DDTracer(config) + def tracer = DDTracer.builder().withConfig(new Config()).build() // Datadog extractor gets placed first def taggedHeaders = tracer.extractor.extractors[0].taggedHeaders @@ -117,7 +116,7 @@ class DDTracerTest extends DDSpecification { def "verify overriding host"() { when: System.setProperty(PREFIX + key, value) - def tracer = new DDTracer(new Config()) + def tracer = DDTracer.builder().withConfig(new Config()).build() then: tracer.writer instanceof DDAgentWriter @@ -132,7 +131,7 @@ class DDTracerTest extends DDSpecification { def "verify overriding port"() { when: System.setProperty(PREFIX + key, value) - def tracer = new DDTracer(new Config()) + def tracer = DDTracer.builder().withConfig(new Config()).build() then: tracer.writer instanceof DDAgentWriter @@ -148,7 +147,7 @@ class DDTracerTest extends DDSpecification { def "Writer is instance of LoggingWriter when property set"() { when: System.setProperty(PREFIX + "writer.type", "LoggingWriter") - def tracer = new DDTracer(new Config()) + def tracer = DDTracer.builder().withConfig(new Config()).build() then: tracer.writer instanceof LoggingWriter @@ -173,7 +172,7 @@ class DDTracerTest extends DDSpecification { def "Shares TraceCount with DDApi with #key = #value"() { setup: System.setProperty(PREFIX + key, value) - final DDTracer tracer = new DDTracer(new Config()) + final DDTracer tracer = DDTracer.builder().build() expect: tracer.writer instanceof DDAgentWriter @@ -187,7 +186,7 @@ class DDTracerTest extends DDSpecification { def "root tags are applied only to root spans"() { setup: - def tracer = new DDTracer('my_service', new ListWriter(), new AllSampler(), '', ['only_root': 'value'], [:], [:], [:]) + def tracer = DDTracer.builder().localRootSpanTags(['only_root': 'value']).build() def root = tracer.buildSpan('my_root').start() def child = tracer.buildSpan('my_child').asChildOf(root).start() @@ -204,7 +203,7 @@ class DDTracerTest extends DDSpecification { given: Properties properties = new Properties() properties.setProperty("writer.type", "LoggingWriter") - def tracer = new DDTracer(new Config(properties, Config.get())) + def tracer = DDTracer.builder().withProperties(properties).build() when: def span = tracer.buildSpan("operation").start() @@ -218,7 +217,7 @@ class DDTracerTest extends DDSpecification { given: Properties properties = new Properties() properties.setProperty("writer.type", "LoggingWriter") - def tracer = new DDTracer(new Config(properties, Config.get())) + def tracer = DDTracer.builder().withProperties(properties).build() when: def root = tracer.buildSpan("operation").start() @@ -240,7 +239,7 @@ class DDTracerTest extends DDSpecification { given: Properties properties = new Properties() properties.setProperty("writer.type", "LoggingWriter") - def tracer = new DDTracer(new Config(properties, Config.get())) + def tracer = DDTracer.builder().withProperties(properties).build() def injector = Mock(TextMapInject) when: @@ -261,7 +260,7 @@ class DDTracerTest extends DDSpecification { def "span priority only set after first injection"() { given: def sampler = new ControllableSampler() - def tracer = new DDTracer("serviceName", new LoggingWriter(), sampler) + def tracer = DDTracer.builder().writer(new LoggingWriter()).sampler(sampler).build() def injector = Mock(TextMapInject) when: @@ -294,7 +293,7 @@ class DDTracerTest extends DDSpecification { def "injection doesn't override set priority"() { given: def sampler = new ControllableSampler() - def tracer = new DDTracer("serviceName", new LoggingWriter(), sampler) + def tracer = DDTracer.builder().writer(new LoggingWriter()).sampler(sampler).build() def injector = Mock(TextMapInject) when: diff --git a/dd-trace-ot/src/test/groovy/datadog/trace/api/sampling/RateByServiceSamplerTest.groovy b/dd-trace-ot/src/test/groovy/datadog/trace/api/sampling/RateByServiceSamplerTest.groovy index 7a6b7a6fa9..b5709f1066 100644 --- a/dd-trace-ot/src/test/groovy/datadog/trace/api/sampling/RateByServiceSamplerTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/trace/api/sampling/RateByServiceSamplerTest.groovy @@ -74,7 +74,7 @@ class RateByServiceSamplerTest extends DDSpecification { def "sampling priority set when service later"() { def sampler = new RateByServiceSampler() - def tracer = new DDTracer("serviceName", new LoggingWriter(), sampler) + def tracer = DDTracer.builder().writer(new LoggingWriter()).sampler(sampler).build() sampler.onResponse("test", new ObjectMapper() .readTree('{"rate_by_service":{"service:,env:":1.0,"service:spock,env:":0.0}}')) @@ -103,7 +103,7 @@ class RateByServiceSamplerTest extends DDSpecification { def "setting forced tracing via tag"() { when: def sampler = new RateByServiceSampler() - def tracer = new DDTracer("serviceName", new LoggingWriter(), sampler) + def tracer = DDTracer.builder().writer(new LoggingWriter()).sampler(sampler).build() def span = tracer.buildSpan("root").start() if (tagName) { span.setTag(tagName, tagValue) @@ -122,7 +122,7 @@ class RateByServiceSamplerTest extends DDSpecification { def "not setting forced tracing via tag or setting it wrong value not causing exception"() { setup: def sampler = new RateByServiceSampler() - def tracer = new DDTracer("serviceName", new LoggingWriter(), sampler) + def tracer = DDTracer.builder().writer(new LoggingWriter()).sampler(sampler).build() def span = tracer.buildSpan("root").start() if (tagName) { span.setTag(tagName, tagValue) diff --git a/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy b/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy index 00db0a213d..ff793e9aaf 100644 --- a/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy +++ b/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy @@ -23,7 +23,7 @@ class DDApiIntegrationTest { @Requires({ "true" == System.getenv("CI") || jvm.java8Compatible }) static class DDAgentApiIntegrationV4Test extends DDSpecification { static final WRITER = new ListWriter() - static final TRACER = new DDTracer(WRITER) + static final TRACER = DDTracer.builder().writer(WRITER).build() static final CONTEXT = new DDSpanContext( 1G, 1G, From e351ce523c3f72d750119497ce1e6897fd9b0b6e Mon Sep 17 00:00:00 2001 From: Laplie Anderson Date: Wed, 15 Jan 2020 10:40:46 -0500 Subject: [PATCH 03/37] Update bytebuddy to 1.10.6 --- gradle/dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index d2ca8a288e..6aebc7d7d4 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -15,7 +15,7 @@ ext { groovy : groovyVer, logback : "1.2.3", lombok : "1.18.10", - bytebuddy : "1.10.4", + bytebuddy : "1.10.6", scala : "2.11.12", // Last version to support Java 7 (2.12+ require Java 8+) kotlin : "1.3.50", coroutines : "1.3.0" From a0b1cd4a75c8c6448a75a582f1dec48354ff7510 Mon Sep 17 00:00:00 2001 From: Laplie Anderson Date: Tue, 14 Jan 2020 16:06:07 -0500 Subject: [PATCH 04/37] WeakMap computeIfAbsent --- .../java/datadog/trace/bootstrap/WeakMap.java | 11 +- .../trace/bootstrap/WeakMapTest.groovy | 14 +- .../agent/tooling/ClassLoaderMatcher.java | 174 +++--------------- .../agent/tooling/DDCachingPoolStrategy.java | 42 +++-- .../trace/agent/tooling/WeakMapSuppliers.java | 8 +- .../tooling/muzzle/ReferenceMatcher.java | 34 ++-- .../netty40/AttributeKeys.java | 21 ++- .../netty41/AttributeKeys.java | 21 ++- 8 files changed, 101 insertions(+), 224 deletions(-) diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/WeakMap.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/WeakMap.java index 29b3a5477a..e0c93b24fb 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/WeakMap.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/WeakMap.java @@ -18,7 +18,7 @@ public interface WeakMap { void putIfAbsent(K key, V value); - V getOrCreate(K key, ValueSupplier supplier); + V computeIfAbsent(K key, ValueSupplier supplier); @Slf4j class Provider { @@ -62,8 +62,8 @@ public interface WeakMap { * Supplies the value to be stored and it is called only when a value does not exists yet in the * registry. */ - interface ValueSupplier { - V get(); + interface ValueSupplier { + V get(K key); } class MapAdapter implements WeakMap { @@ -107,11 +107,12 @@ public interface WeakMap { } @Override - public V getOrCreate(final K key, final ValueSupplier supplier) { + public V computeIfAbsent(final K key, final ValueSupplier supplier) { + // We can't use computeIfAbsent since it was added in 1.8. if (!map.containsKey(key)) { synchronized (this) { if (!map.containsKey(key)) { - map.put(key, supplier.get()); + map.put(key, supplier.get(key)); } } } diff --git a/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/WeakMapTest.groovy b/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/WeakMapTest.groovy index 38e3c493e0..77fe229688 100644 --- a/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/WeakMapTest.groovy +++ b/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/WeakMapTest.groovy @@ -10,7 +10,7 @@ class WeakMapTest extends Specification { def "getOrCreate a value"() { when: - def count = sut.getOrCreate('key', supplier) + def count = sut.computeIfAbsent('key', supplier) then: count == 1 @@ -19,8 +19,8 @@ class WeakMapTest extends Specification { def "getOrCreate a value multiple times same class loader same key"() { when: - def count1 = sut.getOrCreate('key', supplier) - def count2 = sut.getOrCreate('key', supplier) + def count1 = sut.computeIfAbsent('key', supplier) + def count2 = sut.computeIfAbsent('key', supplier) then: count1 == 1 @@ -30,8 +30,8 @@ class WeakMapTest extends Specification { def "getOrCreate a value multiple times same class loader different keys"() { when: - def count1 = sut.getOrCreate('key1', supplier) - def count2 = sut.getOrCreate('key2', supplier) + def count1 = sut.computeIfAbsent('key1', supplier) + def count2 = sut.computeIfAbsent('key2', supplier) then: count1 == 1 @@ -39,12 +39,12 @@ class WeakMapTest extends Specification { supplier.counter == 2 } - class CounterSupplier implements WeakMap.ValueSupplier { + class CounterSupplier implements WeakMap.ValueSupplier { def counter = 0 @Override - Integer get() { + Integer get(String ignored) { counter = counter + 1 return counter } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ClassLoaderMatcher.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ClassLoaderMatcher.java index a53eb694f6..ac776607c0 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ClassLoaderMatcher.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ClassLoaderMatcher.java @@ -30,18 +30,9 @@ public class ClassLoaderMatcher { return new ClassLoaderHasClassMatcher(names); } - public static ElementMatcher.Junction.AbstractBase classLoaderHasClassWithField( - final String className, final String fieldName) { - return new ClassLoaderHasClassWithFieldMatcher(className, fieldName); - } - - public static ElementMatcher.Junction.AbstractBase classLoaderHasClassWithMethod( - final String className, final String methodName, final String... methodArgs) { - return new ClassLoaderHasClassWithMethodMatcher(className, methodName, methodArgs); - } - private static class SkipClassLoaderMatcher - extends ElementMatcher.Junction.AbstractBase { + extends ElementMatcher.Junction.AbstractBase + implements WeakMap.ValueSupplier { public static final SkipClassLoaderMatcher INSTANCE = new SkipClassLoaderMatcher(); /* Cache of classloader-instance -> (true|false). True = skip instrumentation. False = safe to instrument. */ private static final WeakMap SKIP_CACHE = newWeakMap(); @@ -74,23 +65,18 @@ public class ClassLoaderMatcher { } private boolean shouldSkipInstance(final ClassLoader loader) { - Boolean cached = SKIP_CACHE.get(loader); - if (null != cached) { - return cached.booleanValue(); - } - synchronized (this) { - cached = SKIP_CACHE.get(loader); - if (null != cached) { - return cached.booleanValue(); - } - final boolean skip = !delegatesToBootstrap(loader); - if (skip) { - log.debug( - "skipping classloader instance {} of type {}", loader, loader.getClass().getName()); - } - SKIP_CACHE.put(loader, skip); - return skip; + return SKIP_CACHE.computeIfAbsent(loader, this); + } + + @Override + public Boolean get(final ClassLoader loader) { + final boolean skip = !delegatesToBootstrap(loader); + if (skip) { + log.debug( + "skipping classloader instance {} of type {}", loader, loader.getClass().getName()); } + + return skip; } /** @@ -121,23 +107,9 @@ public class ClassLoaderMatcher { } } - private static class ClassLoaderNameMatcher - extends ElementMatcher.Junction.AbstractBase { - - private final String name; - - private ClassLoaderNameMatcher(final String name) { - this.name = name; - } - - @Override - public boolean matches(final ClassLoader target) { - return target != null && name.equals(target.getClass().getName()); - } - } - public static class ClassLoaderHasClassMatcher - extends ElementMatcher.Junction.AbstractBase { + extends ElementMatcher.Junction.AbstractBase + implements WeakMap.ValueSupplier { private final WeakMap cache = newWeakMap(); @@ -150,123 +122,21 @@ public class ClassLoaderMatcher { @Override public boolean matches(final ClassLoader target) { if (target != null) { - Boolean result = cache.get(target); - if (result != null) { - return result; - } - synchronized (target) { - result = cache.get(target); - if (result != null) { - return result; - } - for (final String name : names) { - if (target.getResource(Utils.getResourceName(name)) == null) { - cache.put(target, false); - return false; - } - } - cache.put(target, true); - return true; - } + return cache.computeIfAbsent(target, this); } + return false; } - } - - public static class ClassLoaderHasClassWithFieldMatcher - extends ElementMatcher.Junction.AbstractBase { - - private final WeakMap cache = newWeakMap(); - - private final String className; - private final String fieldName; - - private ClassLoaderHasClassWithFieldMatcher(final String className, final String fieldName) { - this.className = className; - this.fieldName = fieldName; - } @Override - public boolean matches(final ClassLoader target) { - if (target != null) { - Boolean result = cache.get(target); - if (result != null) { - return result; - } - synchronized (target) { - result = cache.get(target); - if (result != null) { - return result; - } - try { - final Class aClass = Class.forName(className, false, target); - aClass.getDeclaredField(fieldName); - cache.put(target, true); - return true; - } catch (final ClassNotFoundException e) { - cache.put(target, false); - return false; - } catch (final NoSuchFieldException e) { - cache.put(target, false); - return false; - } + public Boolean get(final ClassLoader target) { + for (final String name : names) { + if (target.getResource(Utils.getResourceName(name)) == null) { + return false; } } - return false; - } - } - public static class ClassLoaderHasClassWithMethodMatcher - extends ElementMatcher.Junction.AbstractBase { - - private final WeakMap cache = newWeakMap(); - - private final String className; - private final String methodName; - private final String[] methodArgs; - - private ClassLoaderHasClassWithMethodMatcher( - final String className, final String methodName, final String... methodArgs) { - this.className = className; - this.methodName = methodName; - this.methodArgs = methodArgs; - } - - @Override - public boolean matches(final ClassLoader target) { - if (target != null) { - Boolean result = cache.get(target); - if (result != null) { - return result; - } - synchronized (target) { - result = cache.get(target); - if (result != null) { - return result; - } - try { - final Class aClass = Class.forName(className, false, target); - final Class[] methodArgsClasses = new Class[methodArgs.length]; - for (int i = 0; i < methodArgs.length; ++i) { - methodArgsClasses[i] = target.loadClass(methodArgs[i]); - } - if (aClass.isInterface()) { - aClass.getMethod(methodName, methodArgsClasses); - } else { - aClass.getDeclaredMethod(methodName, methodArgsClasses); - } - cache.put(target, true); - return true; - } catch (final ClassNotFoundException e) { - cache.put(target, false); - return false; - } catch (final NoSuchMethodException e) { - cache.put(target, false); - return false; - } - } - } - return false; + return true; } } } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java index 6315cabe89..886d742c78 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java @@ -7,6 +7,7 @@ import static net.bytebuddy.agent.builder.AgentBuilder.PoolStrategy; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import datadog.trace.bootstrap.WeakMap; +import java.security.SecureClassLoader; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -28,7 +29,13 @@ import net.bytebuddy.pool.TypePool; * *

See eviction policy below. */ -public class DDCachingPoolStrategy implements PoolStrategy { +public class DDCachingPoolStrategy + implements PoolStrategy, WeakMap.ValueSupplier { + + // Need this because we can't put null into the typePoolCache map. + private static final ClassLoader BOOTSTRAP_CLASSLOADER_PLACEHOLDER = + new SecureClassLoader(null) {}; + private final WeakMap typePoolCache = WeakMap.Provider.newWeakMap(); private final Cleaner cleaner; @@ -40,28 +47,25 @@ public class DDCachingPoolStrategy implements PoolStrategy { @Override public TypePool typePool(final ClassFileLocator classFileLocator, final ClassLoader classLoader) { final ClassLoader key = - BOOTSTRAP_CLASSLOADER == classLoader ? Utils.getBootstrapProxy() : classLoader; - TypePool.CacheProvider cache = typePoolCache.get(key); - if (null == cache) { - synchronized (key) { - cache = typePoolCache.get(key); - if (null == cache) { - if (skipClassLoader().matches(classLoader)) { - // Don't bother creating a cache for a classloader that won't match. - // (avoiding a lot of DelegatingClassLoader instances) - // This is primarily an optimization. - cache = TypePool.CacheProvider.NoOp.INSTANCE; - } else { - cache = EvictingCacheProvider.withObjectType(cleaner, 1, TimeUnit.MINUTES); - } - typePoolCache.put(key, cache); - } - } - } + BOOTSTRAP_CLASSLOADER == classLoader ? BOOTSTRAP_CLASSLOADER_PLACEHOLDER : classLoader; + final TypePool.CacheProvider cache = typePoolCache.computeIfAbsent(key, this); + return new TypePool.Default.WithLazyResolution( cache, classFileLocator, TypePool.Default.ReaderMode.FAST); } + @Override + public TypePool.CacheProvider get(final ClassLoader key) { + if (BOOTSTRAP_CLASSLOADER_PLACEHOLDER != key && skipClassLoader().matches(key)) { + // Don't bother creating a cache for a classloader that won't match. + // (avoiding a lot of DelegatingClassLoader instances) + // This is primarily an optimization. + return TypePool.CacheProvider.NoOp.INSTANCE; + } else { + return EvictingCacheProvider.withObjectType(cleaner, 1, TimeUnit.MINUTES); + } + } + private static class EvictingCacheProvider implements TypePool.CacheProvider { /** A map containing all cached resolutions by their names. */ diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/WeakMapSuppliers.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/WeakMapSuppliers.java index b5830d5460..4677330c55 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/WeakMapSuppliers.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/WeakMapSuppliers.java @@ -41,7 +41,7 @@ class WeakMapSuppliers { public WeakMap get() { final WeakConcurrentMap map = new WeakConcurrentMap<>(false); cleaner.scheduleCleaning(map, MapCleaner.CLEANER, CLEAN_FREQUENCY_SECONDS, TimeUnit.SECONDS); - return new Adapter(map); + return new Adapter<>(map); } private static class MapCleaner implements Cleaner.Adapter { @@ -86,11 +86,11 @@ class WeakMapSuppliers { } @Override - public V getOrCreate(final K key, final ValueSupplier supplier) { + public V computeIfAbsent(final K key, final ValueSupplier supplier) { if (!map.containsKey(key)) { synchronized (this) { if (!map.containsKey(key)) { - map.put(key, supplier.get()); + map.put(key, supplier.get(key)); } } } @@ -103,7 +103,7 @@ class WeakMapSuppliers { @Override public WeakMap get() { - return new Adapter(new WeakConcurrentMap.WithInlinedExpunction()); + return new Adapter<>(new WeakConcurrentMap.WithInlinedExpunction()); } } } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/ReferenceMatcher.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/ReferenceMatcher.java index 4f2ed18bd0..c669646024 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/ReferenceMatcher.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/ReferenceMatcher.java @@ -22,7 +22,8 @@ import net.bytebuddy.pool.TypePool; /** Matches a set of references against a classloader. */ @Slf4j -public class ReferenceMatcher { +public class ReferenceMatcher + implements WeakMap.ValueSupplier> { private final WeakMap> mismatchCache = newWeakMap(); private final Reference[] references; private final Set helperClassNames; @@ -45,7 +46,7 @@ public class ReferenceMatcher { * @return true if all references match the classpath of loader */ public boolean matches(final ClassLoader loader) { - return getMismatchedReferenceSources(loader).size() == 0; + return getMismatchedReferenceSources(loader).isEmpty(); } /** @@ -56,23 +57,22 @@ public class ReferenceMatcher { if (loader == BOOTSTRAP_LOADER) { loader = Utils.getBootstrapProxy(); } - List mismatches = mismatchCache.get(loader); - if (null == mismatches) { - synchronized (loader) { - mismatches = mismatchCache.get(loader); - if (null == mismatches) { - mismatches = new ArrayList<>(0); - for (final Reference reference : references) { - // Don't reference-check helper classes. - // They will be injected by the instrumentation's HelperInjector. - if (!helperClassNames.contains(reference.getClassName())) { - mismatches.addAll(checkMatch(reference, loader)); - } - } - mismatchCache.put(loader, mismatches); - } + + return mismatchCache.computeIfAbsent(loader, this); + } + + @Override + public List get(final ClassLoader loader) { + final List mismatches = new ArrayList<>(0); + + for (final Reference reference : references) { + // Don't reference-check helper classes. + // They will be injected by the instrumentation's HelperInjector. + if (!helperClassNames.contains(reference.getClassName())) { + mismatches.addAll(checkMatch(reference, loader)); } } + return mismatches; } diff --git a/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/AttributeKeys.java b/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/AttributeKeys.java index 12c3f4d906..2bc752548a 100644 --- a/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/AttributeKeys.java +++ b/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/AttributeKeys.java @@ -14,13 +14,14 @@ public class AttributeKeys { private static final WeakMap>> map = WeakMap.Implementation.DEFAULT.get(); - private static final WeakMap.ValueSupplier>> mapSupplier = - new WeakMap.ValueSupplier>>() { - @Override - public Map> get() { - return new ConcurrentHashMap<>(); - } - }; + private static final WeakMap.ValueSupplier>> + mapSupplier = + new WeakMap.ValueSupplier>>() { + @Override + public Map> get(final ClassLoader ignored) { + return new ConcurrentHashMap<>(); + } + }; public static final AttributeKey PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY = @@ -42,9 +43,9 @@ public class AttributeKeys { * while the Attribute class is loaded by a third class loader and used internally for the * cassandra driver. */ - private static AttributeKey attributeKey(String key) { - Map> classLoaderMap = - map.getOrCreate(AttributeKey.class.getClassLoader(), mapSupplier); + private static AttributeKey attributeKey(final String key) { + final Map> classLoaderMap = + map.computeIfAbsent(AttributeKey.class.getClassLoader(), mapSupplier); if (classLoaderMap.containsKey(key)) { return (AttributeKey) classLoaderMap.get(key); } diff --git a/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/AttributeKeys.java b/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/AttributeKeys.java index 7b632be122..916b2ef3b7 100644 --- a/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/AttributeKeys.java +++ b/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/AttributeKeys.java @@ -14,13 +14,14 @@ public class AttributeKeys { private static final WeakMap>> map = WeakMap.Implementation.DEFAULT.get(); - private static final WeakMap.ValueSupplier>> mapSupplier = - new WeakMap.ValueSupplier>>() { - @Override - public Map> get() { - return new ConcurrentHashMap<>(); - } - }; + private static final WeakMap.ValueSupplier>> + mapSupplier = + new WeakMap.ValueSupplier>>() { + @Override + public Map> get(final ClassLoader ignored) { + return new ConcurrentHashMap<>(); + } + }; public static final AttributeKey PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY = @@ -46,9 +47,9 @@ public class AttributeKeys { * while the Attribute class is loaded by a third class loader and used internally for the * cassandra driver. */ - private static AttributeKey attributeKey(String key) { - Map> classLoaderMap = - map.getOrCreate(AttributeKey.class.getClassLoader(), mapSupplier); + private static AttributeKey attributeKey(final String key) { + final Map> classLoaderMap = + map.computeIfAbsent(AttributeKey.class.getClassLoader(), mapSupplier); if (classLoaderMap.containsKey(key)) { return (AttributeKey) classLoaderMap.get(key); } From 075ecb9f376af2d37c3d8fa0d92102e9acf337f6 Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Wed, 15 Jan 2020 09:25:51 -0800 Subject: [PATCH 05/37] Lazy init Writer from config to avoid premature resource allocation. --- .../java/datadog/opentracing/DDTracer.java | 28 +++++++++---------- .../resolver/DDTracerResolver.java | 2 +- .../opentracing/DDSpanBuilderTest.groovy | 2 +- .../opentracing/PendingTraceTest.groovy | 4 +-- .../groovy/datadog/trace/DDTracerTest.groovy | 14 +++++----- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java index 28389f839e..7f182b5aec 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java @@ -97,27 +97,20 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace private final HttpCodec.Extractor extractor; public static class Builder { + public Builder() { // Apply the default values from config. - withConfig(Config.get()); - } - - public Builder writer(final Writer writer) { - if (this.writer != null && this.writer != writer) { - // Try to avoid leaking resources - this.writer.close(); - } - this.writer = writer; - return this; + config(Config.get()); } public Builder withProperties(final Properties properties) { - return withConfig(Config.get(properties)); + return config(Config.get(properties)); } - public Builder withConfig(final Config config) { + public Builder config(final Config config) { + this.config = config; serviceName(config.getServiceName()); - writer(Writer.Builder.forConfig(config)); + // Explicitly skip setting writer to avoid allocating resources prematurely. sampler(Sampler.Builder.forConfig(config)); injector(HttpCodec.createInjector(config)); extractor(HttpCodec.createExtractor(config, config.getHeaderTags())); @@ -259,6 +252,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace final Map taggedHeaders, final int partialFlushMinSpans) { this( + Config.get(), serviceName, writer, sampler, @@ -274,6 +268,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace @lombok.Builder(builderClassName = "Builder") // These field names must be stable to ensure the builder api is stable. private DDTracer( + final Config config, final String serviceName, final Writer writer, final Sampler sampler, @@ -285,14 +280,17 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace final Map taggedHeaders, final int partialFlushMinSpans) { - assert writer != null; assert localRootSpanTags != null; assert defaultSpanTags != null; assert serviceNameMappings != null; assert taggedHeaders != null; this.serviceName = serviceName; - this.writer = writer; + if (writer == null) { + this.writer = Writer.Builder.forConfig(config); + } else { + this.writer = writer; + } this.sampler = sampler; this.injector = injector; this.extractor = extractor; diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java b/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java index 1522978d21..fc12eda4d4 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java @@ -16,7 +16,7 @@ public class DDTracerResolver extends TracerResolver { Tracer resolve(final Config config) { if (config.isTraceResolverEnabled()) { log.info("Creating DDTracer with DDTracerResolver"); - return DDTracer.builder().withConfig(config).build(); + return DDTracer.builder().config(config).build(); } else { log.info("DDTracerResolver disabled"); return null; diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy index c55df14468..8c194c9a5a 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy @@ -458,7 +458,7 @@ class DDSpanBuilderTest extends DDSpecification { setup: System.setProperty("dd.trace.span.tags", tagString) def config = new Config() - tracer = DDTracer.builder().withConfig(config).writer(writer).build() + tracer = DDTracer.builder().config(config).writer(writer).build() def span = tracer.buildSpan("op name").withServiceName("foo").start() expect: diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy index b987e5227f..6613e74706 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy @@ -195,7 +195,7 @@ class PendingTraceTest extends DDSpecification { def properties = new Properties() properties.setProperty(PARTIAL_FLUSH_MIN_SPANS, "1") def config = Config.get(properties) - def tracer = DDTracer.builder().withConfig(config).writer(writer).build() + def tracer = DDTracer.builder().config(config).writer(writer).build() def trace = new PendingTrace(tracer, traceId, [:]) def rootSpan = SpanFactory.newSpanOf(trace) def child1 = tracer.buildSpan("child1").asChildOf(rootSpan).start() @@ -241,7 +241,7 @@ class PendingTraceTest extends DDSpecification { def properties = new Properties() properties.setProperty(PARTIAL_FLUSH_MIN_SPANS, "1") def config = Config.get(properties) - def tracer = DDTracer.builder().withConfig(config).writer(writer).build() + def tracer = DDTracer.builder().config(config).writer(writer).build() def trace = new PendingTrace(tracer, traceId, [:]) def rootSpan = SpanFactory.newSpanOf(trace) def child1 = tracer.buildSpan("child1").asChildOf(rootSpan).start() diff --git a/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy b/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy index 19ed3b7e83..de8e2dcbec 100644 --- a/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy @@ -63,7 +63,7 @@ class DDTracerTest extends DDSpecification { System.setProperty(PREFIX + HEALTH_METRICS_ENABLED, "true") when: - def tracer = DDTracer.builder().withConfig(new Config()).build() + def tracer = DDTracer.builder().config(new Config()).build() then: tracer.writer.monitor instanceof Monitor.StatsD @@ -75,7 +75,7 @@ class DDTracerTest extends DDSpecification { setup: System.setProperty(PREFIX + PRIORITY_SAMPLING, "false") when: - def tracer = DDTracer.builder().withConfig(new Config()).build() + def tracer = DDTracer.builder().config(new Config()).build() then: tracer.sampler instanceof AllSampler } @@ -85,7 +85,7 @@ class DDTracerTest extends DDSpecification { System.setProperty(PREFIX + WRITER_TYPE, "LoggingWriter") when: - def tracer = DDTracer.builder().withConfig(new Config()).build() + def tracer = DDTracer.builder().config(new Config()).build() then: tracer.writer instanceof LoggingWriter @@ -98,7 +98,7 @@ class DDTracerTest extends DDSpecification { System.setProperty(PREFIX + HEADER_TAGS, mapString) when: - def tracer = DDTracer.builder().withConfig(new Config()).build() + def tracer = DDTracer.builder().config(new Config()).build() // Datadog extractor gets placed first def taggedHeaders = tracer.extractor.extractors[0].taggedHeaders @@ -116,7 +116,7 @@ class DDTracerTest extends DDSpecification { def "verify overriding host"() { when: System.setProperty(PREFIX + key, value) - def tracer = DDTracer.builder().withConfig(new Config()).build() + def tracer = DDTracer.builder().config(new Config()).build() then: tracer.writer instanceof DDAgentWriter @@ -131,7 +131,7 @@ class DDTracerTest extends DDSpecification { def "verify overriding port"() { when: System.setProperty(PREFIX + key, value) - def tracer = DDTracer.builder().withConfig(new Config()).build() + def tracer = DDTracer.builder().config(new Config()).build() then: tracer.writer instanceof DDAgentWriter @@ -147,7 +147,7 @@ class DDTracerTest extends DDSpecification { def "Writer is instance of LoggingWriter when property set"() { when: System.setProperty(PREFIX + "writer.type", "LoggingWriter") - def tracer = DDTracer.builder().withConfig(new Config()).build() + def tracer = DDTracer.builder().config(new Config()).build() then: tracer.writer instanceof LoggingWriter From 68ed1da9c61f7c457bd42182b86c7ca92a161be4 Mon Sep 17 00:00:00 2001 From: Laplie Anderson Date: Wed, 15 Jan 2020 12:41:01 -0500 Subject: [PATCH 06/37] Don't call `map.get()` in the `put(..)` case --- .../java/datadog/trace/bootstrap/WeakMap.java | 19 ++++++++++++------- .../trace/agent/tooling/WeakMapSuppliers.java | 19 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/WeakMap.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/WeakMap.java index e0c93b24fb..4486ff4132 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/WeakMap.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/WeakMap.java @@ -109,15 +109,20 @@ public interface WeakMap { @Override public V computeIfAbsent(final K key, final ValueSupplier supplier) { // We can't use computeIfAbsent since it was added in 1.8. - if (!map.containsKey(key)) { - synchronized (this) { - if (!map.containsKey(key)) { - map.put(key, supplier.get(key)); - } - } + if (map.containsKey(key)) { + return map.get(key); } - return map.get(key); + synchronized (this) { + if (map.containsKey(key)) { + return map.get(key); + } else { + final V value = supplier.get(key); + + map.put(key, value); + return value; + } + } } @Override diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/WeakMapSuppliers.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/WeakMapSuppliers.java index 4677330c55..32a16a0b7c 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/WeakMapSuppliers.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/WeakMapSuppliers.java @@ -87,15 +87,20 @@ class WeakMapSuppliers { @Override public V computeIfAbsent(final K key, final ValueSupplier supplier) { - if (!map.containsKey(key)) { - synchronized (this) { - if (!map.containsKey(key)) { - map.put(key, supplier.get(key)); - } - } + if (map.containsKey(key)) { + return map.get(key); } - return map.get(key); + synchronized (this) { + if (map.containsKey(key)) { + return map.get(key); + } else { + final V value = supplier.get(key); + + map.put(key, value); + return value; + } + } } } From 607c8f277ee0bc9aff4c19111741cee935f420f5 Mon Sep 17 00:00:00 2001 From: Laplie Anderson Date: Wed, 15 Jan 2020 13:38:44 -0500 Subject: [PATCH 07/37] Don't copy to byte[], return input stream directly --- .../bootstrap/InternalJarURLHandler.java | 54 +++++-------------- 1 file changed, 13 insertions(+), 41 deletions(-) diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/InternalJarURLHandler.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/InternalJarURLHandler.java index d645b8c722..c26d9de8da 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/InternalJarURLHandler.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/InternalJarURLHandler.java @@ -1,7 +1,6 @@ package datadog.trace.bootstrap; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -24,14 +23,16 @@ public class InternalJarURLHandler extends URLStreamHandler { private JarFile bootstrapJarFile; InternalJarURLHandler(final String internalJarFileName, final URL bootstrapJarLocation) { + final String filePrefix = internalJarFileName + "/"; + try { if (bootstrapJarLocation != null) { - bootstrapJarFile = new JarFile(new File(bootstrapJarLocation.toURI())); + bootstrapJarFile = new JarFile(new File(bootstrapJarLocation.toURI()), false); final Enumeration entries = bootstrapJarFile.entries(); while (entries.hasMoreElements()) { final JarEntry entry = entries.nextElement(); - if (!entry.isDirectory() && entry.getName().startsWith(internalJarFileName + "/")) { + if (!entry.isDirectory() && entry.getName().startsWith(filePrefix)) { filenameToEntry.put(entry.getName().substring(internalJarFileName.length()), entry); } } @@ -41,62 +42,33 @@ public class InternalJarURLHandler extends URLStreamHandler { } if (filenameToEntry.isEmpty()) { - log.warn("Internal jar entries found"); + log.warn("No internal jar entries found"); } } @Override protected URLConnection openConnection(final URL url) throws IOException { - - final byte[] bytes; - final String filename = url.getFile().replaceAll("\\.class$", ".classdata"); if ("/".equals(filename)) { // "/" is used as the default url of the jar // This is called by the SecureClassLoader trying to obtain permissions - bytes = new byte[0]; + + // nullInputStream() is not available until Java 11 + return new InternalJarURLConnection(url, new ByteArrayInputStream(new byte[0])); } else if (filenameToEntry.containsKey(filename)) { final JarEntry entry = filenameToEntry.get(filename); - bytes = getBytes(bootstrapJarFile.getInputStream(entry)); + return new InternalJarURLConnection(url, bootstrapJarFile.getInputStream(entry)); } else { throw new NoSuchFileException(url.getFile(), null, url.getFile() + " not in internal jar"); } - - return new InternalJarURLConnection(url, bytes); - } - - /** - * Standard "copy InputStream to byte[]" implementation using a ByteArrayOutputStream - * - *

IOUtils.toByteArray() or Java 9's InputStream.readAllBytes() could be replacements if they - * were available - * - *

This can be optimized using the JarEntry's size(), but its not always available - * - * @param inputStream stream to read - * @return a byte[] from the inputstream - */ - private static byte[] getBytes(final InputStream inputStream) throws IOException { - final byte[] buffer = new byte[4096]; - - int bytesRead = inputStream.read(buffer, 0, buffer.length); - try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - while (bytesRead != -1) { - outputStream.write(buffer, 0, bytesRead); - - bytesRead = inputStream.read(buffer, 0, buffer.length); - } - - return outputStream.toByteArray(); - } } private static class InternalJarURLConnection extends URLConnection { - private final byte[] bytes; + private final InputStream inputStream; - private InternalJarURLConnection(final URL url, final byte[] bytes) { + private InternalJarURLConnection(final URL url, final InputStream inputStream) { super(url); - this.bytes = bytes; + this.inputStream = inputStream; } @Override @@ -106,7 +78,7 @@ public class InternalJarURLHandler extends URLStreamHandler { @Override public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(bytes); + return inputStream; } @Override From 4915ed9c753b3af827dfefbb798238390e6eb256 Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Wed, 15 Jan 2020 11:22:10 -0800 Subject: [PATCH 08/37] Update muzzle maven URL to use https Also add a test. --- buildSrc/build.gradle.kts | 3 ++ buildSrc/src/main/groovy/MuzzlePlugin.groovy | 2 +- .../src/test/groovy/RangeQueryTest.groovy | 28 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 buildSrc/src/test/groovy/RangeQueryTest.groovy diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index a584dc3928..1ead6ed5d4 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -29,4 +29,7 @@ dependencies { compile("com.google.guava", "guava", "20.0") compile("org.ow2.asm", "asm", "7.0-beta") compile("org.ow2.asm", "asm-tree", "7.0-beta") + + testCompile("org.spockframework", "spock-core", "1.3-groovy-2.5") + testCompile("org.codehaus.groovy", "groovy-all", "2.5.8") } diff --git a/buildSrc/src/main/groovy/MuzzlePlugin.groovy b/buildSrc/src/main/groovy/MuzzlePlugin.groovy index 2f6256ed3f..99ad0b90dd 100644 --- a/buildSrc/src/main/groovy/MuzzlePlugin.groovy +++ b/buildSrc/src/main/groovy/MuzzlePlugin.groovy @@ -35,7 +35,7 @@ class MuzzlePlugin implements Plugin { private static final List MUZZLE_REPOS private static final AtomicReference TOOLING_LOADER = new AtomicReference<>() static { - RemoteRepository central = new RemoteRepository.Builder("central", "default", "http://central.maven.org/maven2/").build() + RemoteRepository central = new RemoteRepository.Builder("central", "default", "https://repo1.maven.org/maven2/").build() MUZZLE_REPOS = new ArrayList(Arrays.asList(central)) } diff --git a/buildSrc/src/test/groovy/RangeQueryTest.groovy b/buildSrc/src/test/groovy/RangeQueryTest.groovy new file mode 100644 index 0000000000..3f6d81d3e6 --- /dev/null +++ b/buildSrc/src/test/groovy/RangeQueryTest.groovy @@ -0,0 +1,28 @@ +import org.eclipse.aether.RepositorySystem +import org.eclipse.aether.RepositorySystemSession +import org.eclipse.aether.artifact.Artifact +import org.eclipse.aether.artifact.DefaultArtifact +import org.eclipse.aether.resolution.VersionRangeRequest +import org.eclipse.aether.resolution.VersionRangeResult +import spock.lang.Specification + +class RangeQueryTest extends Specification { + + RepositorySystem system = MuzzlePlugin.newRepositorySystem() + RepositorySystemSession session = MuzzlePlugin.newRepositorySystemSession(system) + + def "test range request"() { + setup: +// compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.5.0', ext: 'pom' + final Artifact directiveArtifact = new DefaultArtifact("org.codehaus.groovy", "groovy-all", "jar", "[2.5.0,2.5.8)") + final VersionRangeRequest rangeRequest = new VersionRangeRequest() + rangeRequest.setRepositories(MuzzlePlugin.MUZZLE_REPOS) + rangeRequest.setArtifact(directiveArtifact) + + // This call makes an actual network request, which may fail if network access is limited. + final VersionRangeResult rangeResult = system.resolveVersionRange(session, rangeRequest) + + expect: + rangeResult.versions.size() >= 8 + } +} From bcf81823b3110c6a6e83baede7f570d7595ddacd Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Tue, 14 Jan 2020 17:11:25 -0800 Subject: [PATCH 09/37] Add limit to trace scope depth When limit is exceeded, a NoopScope is returned. Allow custom ScopeManager to be provided, with the plan to remove `ScopeContext` customization in the future. --- .../main/java/datadog/trace/api/Config.java | 9 ++++ .../java/datadog/opentracing/DDTracer.java | 16 ++++-- .../scopemanager/ContextualScopeManager.java | 17 ++++++ .../scopemanager/ContinuableScope.java | 8 +++ .../opentracing/scopemanager/DDScope.java | 2 + .../opentracing/scopemanager/SimpleScope.java | 7 +++ .../scopemanager/ScopeManagerTest.groovy | 53 ++++++++++++++++--- 7 files changed, 102 insertions(+), 10 deletions(-) diff --git a/dd-trace-api/src/main/java/datadog/trace/api/Config.java b/dd-trace-api/src/main/java/datadog/trace/api/Config.java index 5ad4842782..c11a344979 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/Config.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/Config.java @@ -76,6 +76,7 @@ public class Config { public static final String HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN = "trace.http.client.split-by-domain"; public static final String DB_CLIENT_HOST_SPLIT_BY_INSTANCE = "trace.db.client.split-by-instance"; public static final String SPLIT_BY_TAGS = "trace.split-by-tags"; + public static final String SCOPE_DEPTH_LIMIT = "trace.scope.depth.limit"; public static final String PARTIAL_FLUSH_MIN_SPANS = "trace.partial.flush.min.spans"; public static final String RUNTIME_CONTEXT_FIELD_INJECTION = "trace.runtime.context.field.injection"; @@ -128,6 +129,7 @@ public class Config { private static final boolean DEFAULT_HTTP_CLIENT_SPLIT_BY_DOMAIN = false; private static final boolean DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE = false; private static final String DEFAULT_SPLIT_BY_TAGS = ""; + private static final int DEFAULT_SCOPE_DEPTH_LIMIT = 100; private static final int DEFAULT_PARTIAL_FLUSH_MIN_SPANS = 1000; private static final String DEFAULT_PROPAGATION_STYLE_EXTRACT = PropagationStyle.DATADOG.name(); private static final String DEFAULT_PROPAGATION_STYLE_INJECT = PropagationStyle.DATADOG.name(); @@ -188,6 +190,7 @@ public class Config { @Getter private final boolean httpClientSplitByDomain; @Getter private final boolean dbClientSplitByInstance; @Getter private final Set splitByTags; + @Getter private final Integer scopeDepthLimit; @Getter private final Integer partialFlushMinSpans; @Getter private final boolean runtimeContextFieldInjection; @Getter private final Set propagationStylesToExtract; @@ -290,6 +293,9 @@ public class Config { new LinkedHashSet<>( getListSettingFromEnvironment(SPLIT_BY_TAGS, DEFAULT_SPLIT_BY_TAGS))); + scopeDepthLimit = + getIntegerSettingFromEnvironment(SCOPE_DEPTH_LIMIT, DEFAULT_SCOPE_DEPTH_LIMIT); + partialFlushMinSpans = getIntegerSettingFromEnvironment(PARTIAL_FLUSH_MIN_SPANS, DEFAULT_PARTIAL_FLUSH_MIN_SPANS); @@ -418,6 +424,9 @@ public class Config { getPropertyListValue( properties, SPLIT_BY_TAGS, new ArrayList<>(parent.splitByTags)))); + scopeDepthLimit = + getPropertyIntegerValue(properties, SCOPE_DEPTH_LIMIT, parent.scopeDepthLimit); + partialFlushMinSpans = getPropertyIntegerValue(properties, PARTIAL_FLUSH_MIN_SPANS, parent.partialFlushMinSpans); diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java index 7f182b5aec..fcf1719302 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java @@ -62,7 +62,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace /** Sampler defines the sampling policy in order to reduce the number of traces for instance */ final Sampler sampler; /** Scope manager is in charge of managing the scopes from which spans are created */ - final ContextualScopeManager scopeManager = new ContextualScopeManager(); + final ScopeManager scopeManager; /** A set of tags that are added only to the application's root span */ private final Map localRootSpanTags; @@ -114,6 +114,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace sampler(Sampler.Builder.forConfig(config)); injector(HttpCodec.createInjector(config)); extractor(HttpCodec.createExtractor(config, config.getHeaderTags())); + scopeManager(new ContextualScopeManager(config.getScopeDepthLimit())); localRootSpanTags(config.getLocalRootSpanTags()); defaultSpanTags(config.getMergedSpanTags()); serviceNameMappings(config.getServiceMapping()); @@ -258,6 +259,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace sampler, HttpCodec.createInjector(Config.get()), HttpCodec.createExtractor(Config.get(), taggedHeaders), + new ContextualScopeManager(Config.get().getScopeDepthLimit()), localRootSpanTags, defaultSpanTags, serviceNameMappings, @@ -274,6 +276,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace final Sampler sampler, final HttpCodec.Injector injector, final HttpCodec.Extractor extractor, + final ScopeManager scopeManager, final Map localRootSpanTags, final Map defaultSpanTags, final Map serviceNameMappings, @@ -294,6 +297,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace this.sampler = sampler; this.injector = injector; this.extractor = extractor; + this.scopeManager = scopeManager; this.localRootSpanTags = localRootSpanTags; this.defaultSpanTags = defaultSpanTags; this.serviceNameMappings = serviceNameMappings; @@ -365,7 +369,9 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace @Deprecated public void addScopeContext(final ScopeContext context) { - scopeManager.addScopeContext(context); + if (scopeManager instanceof ContextualScopeManager) { + ((ContextualScopeManager) scopeManager).addScopeContext(context); + } } /** @@ -386,7 +392,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace } @Override - public ContextualScopeManager scopeManager() { + public ScopeManager scopeManager() { return scopeManager; } @@ -510,7 +516,9 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace @Override public void addScopeListener(final ScopeListener listener) { - scopeManager.addScopeListener(listener); + if (scopeManager instanceof ContextualScopeManager) { + ((ContextualScopeManager) scopeManager).addScopeListener(listener); + } } @Override diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/ContextualScopeManager.java b/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/ContextualScopeManager.java index 9f66c9c2b9..e9b3d80d1e 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/ContextualScopeManager.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/ContextualScopeManager.java @@ -5,18 +5,35 @@ import datadog.trace.context.ScopeListener; import io.opentracing.Scope; import io.opentracing.ScopeManager; import io.opentracing.Span; +import io.opentracing.noop.NoopScopeManager; import java.util.Deque; import java.util.List; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.CopyOnWriteArrayList; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class ContextualScopeManager implements ScopeManager { static final ThreadLocal tlsScope = new ThreadLocal<>(); final Deque scopeContexts = new ConcurrentLinkedDeque<>(); final List scopeListeners = new CopyOnWriteArrayList<>(); + private final int depthLimit; + + public ContextualScopeManager(final int depthLimit) { + this.depthLimit = depthLimit; + } + @Override public Scope activate(final Span span, final boolean finishOnClose) { + final Scope active = active(); + if (active instanceof DDScope) { + final int currentDepth = ((DDScope) active).depth(); + if (depthLimit <= currentDepth) { + log.debug("Scope depth limit exceeded ({}). Returning NoopScope.", currentDepth); + return NoopScopeManager.NoopScope.INSTANCE; + } + } for (final ScopeContext context : scopeContexts) { if (context.inContext()) { return context.activate(span, finishOnClose); diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/ContinuableScope.java b/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/ContinuableScope.java index 43b9e09477..2eda0a0b18 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/ContinuableScope.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/ContinuableScope.java @@ -29,6 +29,8 @@ public class ContinuableScope implements DDScope, TraceScope { private final Continuation continuation; /** Flag to propagate this scope across async boundaries. */ private final AtomicBoolean isAsyncPropagating = new AtomicBoolean(false); + /** depth of scope on thread */ + private final int depth; ContinuableScope( final ContextualScopeManager scopeManager, @@ -51,6 +53,7 @@ public class ContinuableScope implements DDScope, TraceScope { this.finishOnClose = finishOnClose; toRestore = scopeManager.tlsScope.get(); scopeManager.tlsScope.set(this); + depth = toRestore == null ? 0 : toRestore.depth() + 1; for (final ScopeListener listener : scopeManager.scopeListeners) { listener.afterScopeActivated(); } @@ -90,6 +93,11 @@ public class ContinuableScope implements DDScope, TraceScope { return spanUnderScope; } + @Override + public int depth() { + return depth; + } + @Override public boolean isAsyncPropagating() { return isAsyncPropagating.get(); diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/DDScope.java b/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/DDScope.java index a543914ed0..34845c75b1 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/DDScope.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/DDScope.java @@ -7,4 +7,6 @@ import io.opentracing.Span; interface DDScope extends Scope { @Override Span span(); + + int depth(); } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/SimpleScope.java b/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/SimpleScope.java index d620a8420a..750ab00eb7 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/SimpleScope.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/scopemanager/SimpleScope.java @@ -9,6 +9,7 @@ public class SimpleScope implements DDScope { private final Span spanUnderScope; private final boolean finishOnClose; private final DDScope toRestore; + private final int depth; public SimpleScope( final ContextualScopeManager scopeManager, @@ -20,6 +21,7 @@ public class SimpleScope implements DDScope { this.finishOnClose = finishOnClose; toRestore = scopeManager.tlsScope.get(); scopeManager.tlsScope.set(this); + depth = toRestore == null ? 0 : toRestore.depth() + 1; for (final ScopeListener listener : scopeManager.scopeListeners) { listener.afterScopeActivated(); } @@ -48,4 +50,9 @@ public class SimpleScope implements DDScope { public Span span() { return spanUnderScope; } + + @Override + public int depth() { + return depth; + } } diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/scopemanager/ScopeManagerTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/scopemanager/ScopeManagerTest.groovy index 82ca18c95a..7ceb957598 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/scopemanager/ScopeManagerTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/scopemanager/ScopeManagerTest.groovy @@ -8,8 +8,11 @@ import datadog.trace.context.ScopeListener import datadog.trace.util.gc.GCUtils import datadog.trace.util.test.DDSpecification import io.opentracing.Scope +import io.opentracing.ScopeManager import io.opentracing.Span +import io.opentracing.noop.NoopScopeManager import io.opentracing.noop.NoopSpan +import spock.lang.Shared import spock.lang.Subject import spock.lang.Timeout @@ -22,14 +25,19 @@ import java.util.concurrent.atomic.AtomicReference import static java.util.concurrent.TimeUnit.SECONDS class ScopeManagerTest extends DDSpecification { - def latch - def writer - def tracer + @Shared + CountDownLatch latch + @Shared + ListWriter writer + @Shared + DDTracer tracer + + @Shared @Subject - def scopeManager + ScopeManager scopeManager - def setup() { + def setupSpec() { latch = new CountDownLatch(1) final currentLatch = latch writer = new ListWriter() { @@ -37,12 +45,15 @@ class ScopeManagerTest extends DDSpecification { currentLatch.countDown() } } - tracer = new DDTracer(writer) + tracer = DDTracer.builder().writer(writer).build() scopeManager = tracer.scopeManager() } def cleanup() { scopeManager.tlsScope.remove() + scopeManager.scopeContexts.clear() + scopeManager.scopeListeners.clear() + writer.clear() } def "non-ddspan activation results in a simple scope"() { @@ -129,6 +140,36 @@ class ScopeManagerTest extends DDSpecification { false | true } + def "scopemanager returns noop scope if depth exceeded"() { + when: "fill up the scope stack" + Scope scope = null + for (int i = 0; i <= depth; i++) { + scope = scopeManager.activate(NoopSpan.INSTANCE, false) + assert scope instanceof SimpleScope + } + + then: "last scope is still valid" + (scope as SimpleScope).depth() == depth + + when: "activate a scope over the limit" + scope = scopeManager.activate(NoopSpan.INSTANCE, false) + + then: "a noop instance is returned" + scope instanceof NoopScopeManager.NoopScope + + when: "try again for good measure" + scope = scopeManager.activate(NoopSpan.INSTANCE, false) + + then: "still have a noop instance" + scope instanceof NoopScopeManager.NoopScope + + and: "scope stack not effected." + (scopeManager.active() as SimpleScope).depth() == depth + + where: + depth = scopeManager.depthLimit + } + def "ContinuableScope only creates continuations when propagation is set"() { setup: def builder = tracer.buildSpan("test") From bed15079bc0290fdea6a64ab34c2fc338ccf848b Mon Sep 17 00:00:00 2001 From: Laplie Anderson Date: Thu, 16 Jan 2020 11:38:38 -0500 Subject: [PATCH 10/37] Rename Rule Based Sampling properties --- .../main/java/datadog/trace/api/Config.java | 24 +++++++------------ .../trace/common/sampling/Sampler.java | 6 ++--- .../api/sampling/RuleBasedSamplingTest.groovy | 14 +++++------ 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/dd-trace-api/src/main/java/datadog/trace/api/Config.java b/dd-trace-api/src/main/java/datadog/trace/api/Config.java index 5ad4842782..c50d4026fb 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/Config.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/Config.java @@ -65,8 +65,8 @@ public class Config { public static final String TRACE_CLASSES_EXCLUDE = "trace.classes.exclude"; public static final String TRACE_SAMPLING_SERVICE_RULES = "trace.sampling.service.rules"; public static final String TRACE_SAMPLING_OPERATION_RULES = "trace.sampling.operation.rules"; - public static final String TRACE_SAMPLING_DEFAULT_RATE = "trace.sampling.default.rate"; - public static final String TRACE_SAMPLING_RATE_LIMIT = "trace.sampling.rate.limit"; + public static final String TRACE_SAMPLE_RATE = "trace.sample.rate"; + public static final String TRACE_RATE_LIMIT = "trace.rate.limit"; public static final String TRACE_REPORT_HOSTNAME = "trace.report-hostname"; public static final String HEADER_TAGS = "trace.header.tags"; public static final String HTTP_SERVER_ERROR_STATUSES = "http.server.error.statuses"; @@ -149,7 +149,7 @@ public class Config { private static final String DEFAULT_TRACE_METHODS = null; public static final boolean DEFAULT_TRACE_ANALYTICS_ENABLED = false; public static final float DEFAULT_ANALYTICS_SAMPLE_RATE = 1.0f; - public static final double DEFAULT_TRACE_SAMPLING_RATE_LIMIT = 100; + public static final double DEFAULT_TRACE_RATE_LIMIT = 100; public enum PropagationStyle { DATADOG, @@ -222,8 +222,8 @@ public class Config { @Getter private final Map traceSamplingServiceRules; @Getter private final Map traceSamplingOperationRules; - @Getter private final Double traceSamplingDefaultRate; - @Getter private final Double traceSamplingRateLimit; + @Getter private final Double traceSampleRate; + @Getter private final Double traceRateLimit; // Values from an optionally provided properties file private static Properties propertiesFromConfigFile; @@ -349,10 +349,8 @@ public class Config { traceSamplingServiceRules = getMapSettingFromEnvironment(TRACE_SAMPLING_SERVICE_RULES, null); traceSamplingOperationRules = getMapSettingFromEnvironment(TRACE_SAMPLING_OPERATION_RULES, null); - traceSamplingDefaultRate = getDoubleSettingFromEnvironment(TRACE_SAMPLING_DEFAULT_RATE, null); - traceSamplingRateLimit = - getDoubleSettingFromEnvironment( - TRACE_SAMPLING_RATE_LIMIT, DEFAULT_TRACE_SAMPLING_RATE_LIMIT); + traceSampleRate = getDoubleSettingFromEnvironment(TRACE_SAMPLE_RATE, null); + traceRateLimit = getDoubleSettingFromEnvironment(TRACE_RATE_LIMIT, DEFAULT_TRACE_RATE_LIMIT); log.debug("New instance: {}", this); } @@ -484,12 +482,8 @@ public class Config { traceSamplingOperationRules = getPropertyMapValue( properties, TRACE_SAMPLING_OPERATION_RULES, parent.traceSamplingOperationRules); - traceSamplingDefaultRate = - getPropertyDoubleValue( - properties, TRACE_SAMPLING_DEFAULT_RATE, parent.traceSamplingDefaultRate); - traceSamplingRateLimit = - getPropertyDoubleValue( - properties, TRACE_SAMPLING_RATE_LIMIT, parent.traceSamplingRateLimit); + traceSampleRate = getPropertyDoubleValue(properties, TRACE_SAMPLE_RATE, parent.traceSampleRate); + traceRateLimit = getPropertyDoubleValue(properties, TRACE_RATE_LIMIT, parent.traceRateLimit); log.debug("New instance: {}", this); } diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/Sampler.java b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/Sampler.java index 2fbf654bc5..a74e64a0c4 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/Sampler.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/Sampler.java @@ -27,15 +27,15 @@ public interface Sampler { if ((serviceRules != null && !serviceRules.isEmpty()) || (operationRules != null && !operationRules.isEmpty()) - || config.getTraceSamplingDefaultRate() != null) { + || config.getTraceSampleRate() != null) { try { sampler = RuleBasedSampler.build( serviceRules, operationRules, - config.getTraceSamplingDefaultRate(), - config.getTraceSamplingRateLimit()); + config.getTraceSampleRate(), + config.getTraceRateLimit()); } catch (final IllegalArgumentException e) { log.error("Invalid sampler configuration. Using AllSampler", e); sampler = new AllSampler(); diff --git a/dd-trace-ot/src/test/groovy/datadog/trace/api/sampling/RuleBasedSamplingTest.groovy b/dd-trace-ot/src/test/groovy/datadog/trace/api/sampling/RuleBasedSamplingTest.groovy index ad14a52bf1..bdd770244e 100644 --- a/dd-trace-ot/src/test/groovy/datadog/trace/api/sampling/RuleBasedSamplingTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/trace/api/sampling/RuleBasedSamplingTest.groovy @@ -8,9 +8,9 @@ import datadog.trace.common.sampling.RuleBasedSampler import datadog.trace.common.sampling.Sampler import datadog.trace.util.test.DDSpecification -import static datadog.trace.api.Config.TRACE_SAMPLING_DEFAULT_RATE +import static datadog.trace.api.Config.TRACE_RATE_LIMIT +import static datadog.trace.api.Config.TRACE_SAMPLE_RATE import static datadog.trace.api.Config.TRACE_SAMPLING_OPERATION_RULES -import static datadog.trace.api.Config.TRACE_SAMPLING_RATE_LIMIT import static datadog.trace.api.Config.TRACE_SAMPLING_SERVICE_RULES import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP @@ -27,7 +27,7 @@ class RuleBasedSamplingTest extends DDSpecification { def "Rule Based Sampler is not created when just rate limit set"() { when: Properties properties = new Properties() - properties.setProperty(TRACE_SAMPLING_RATE_LIMIT, "50") + properties.setProperty(TRACE_RATE_LIMIT, "50") Sampler sampler = Sampler.Builder.forConfig(properties) then: @@ -46,11 +46,11 @@ class RuleBasedSamplingTest extends DDSpecification { } if (defaultRate != null) { - properties.setProperty(TRACE_SAMPLING_DEFAULT_RATE, defaultRate) + properties.setProperty(TRACE_SAMPLE_RATE, defaultRate) } if (rateLimit != null) { - properties.setProperty(TRACE_SAMPLING_RATE_LIMIT, rateLimit) + properties.setProperty(TRACE_RATE_LIMIT, rateLimit) } when: @@ -139,7 +139,7 @@ class RuleBasedSamplingTest extends DDSpecification { when: Properties properties = new Properties() properties.setProperty(TRACE_SAMPLING_SERVICE_RULES, "service:1") - properties.setProperty(TRACE_SAMPLING_RATE_LIMIT, "1") + properties.setProperty(TRACE_RATE_LIMIT, "1") Sampler sampler = Sampler.Builder.forConfig(properties) DDSpan span1 = SpanFactory.newSpanOf("service", "bar") @@ -165,7 +165,7 @@ class RuleBasedSamplingTest extends DDSpecification { when: Properties properties = new Properties() properties.setProperty(TRACE_SAMPLING_SERVICE_RULES, "service:1,foo:1") - properties.setProperty(TRACE_SAMPLING_RATE_LIMIT, "1") + properties.setProperty(TRACE_RATE_LIMIT, "1") Sampler sampler = Sampler.Builder.forConfig(properties) DDSpan span1 = SpanFactory.newSpanOf("service", "bar") From e24d04e3a56713ed941d5858165ba3d1f2879c1b Mon Sep 17 00:00:00 2001 From: Laplie Anderson Date: Thu, 16 Jan 2020 12:02:21 -0500 Subject: [PATCH 11/37] changes to config test --- .../datadog/trace/api/ConfigTest.groovy | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/dd-trace-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy b/dd-trace-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy index 518d05ce9a..337bd716de 100644 --- a/dd-trace-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy +++ b/dd-trace-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy @@ -40,11 +40,11 @@ import static datadog.trace.api.Config.SPAN_TAGS import static datadog.trace.api.Config.SPLIT_BY_TAGS import static datadog.trace.api.Config.TRACE_AGENT_PORT import static datadog.trace.api.Config.TRACE_ENABLED +import static datadog.trace.api.Config.TRACE_RATE_LIMIT import static datadog.trace.api.Config.TRACE_REPORT_HOSTNAME import static datadog.trace.api.Config.TRACE_RESOLVER_ENABLED -import static datadog.trace.api.Config.TRACE_SAMPLING_DEFAULT_RATE +import static datadog.trace.api.Config.TRACE_SAMPLE_RATE import static datadog.trace.api.Config.TRACE_SAMPLING_OPERATION_RULES -import static datadog.trace.api.Config.TRACE_SAMPLING_RATE_LIMIT import static datadog.trace.api.Config.TRACE_SAMPLING_SERVICE_RULES import static datadog.trace.api.Config.WRITER_TYPE @@ -151,8 +151,8 @@ class ConfigTest extends DDSpecification { prop.setProperty(HEALTH_METRICS_STATSD_PORT, "654") prop.setProperty(TRACE_SAMPLING_SERVICE_RULES, "a:1") prop.setProperty(TRACE_SAMPLING_OPERATION_RULES, "b:1") - prop.setProperty(TRACE_SAMPLING_DEFAULT_RATE, ".5") - prop.setProperty(TRACE_SAMPLING_RATE_LIMIT, "200") + prop.setProperty(TRACE_SAMPLE_RATE, ".5") + prop.setProperty(TRACE_RATE_LIMIT, "200") when: Config config = Config.get(prop) @@ -191,8 +191,8 @@ class ConfigTest extends DDSpecification { config.healthMetricsStatsdPort == 654 config.traceSamplingServiceRules == [a: "1"] config.traceSamplingOperationRules == [b: "1"] - config.traceSamplingDefaultRate == 0.5 - config.traceSamplingRateLimit == 200 + config.traceSampleRate == 0.5 + config.traceRateLimit == 200 } def "specify overrides via system properties"() { @@ -232,8 +232,8 @@ class ConfigTest extends DDSpecification { System.setProperty(PREFIX + HEALTH_METRICS_STATSD_PORT, "654") System.setProperty(PREFIX + TRACE_SAMPLING_SERVICE_RULES, "a:1") System.setProperty(PREFIX + TRACE_SAMPLING_OPERATION_RULES, "b:1") - System.setProperty(PREFIX + TRACE_SAMPLING_DEFAULT_RATE, ".5") - System.setProperty(PREFIX + TRACE_SAMPLING_RATE_LIMIT, "200") + System.setProperty(PREFIX + TRACE_SAMPLE_RATE, ".5") + System.setProperty(PREFIX + TRACE_RATE_LIMIT, "200") when: Config config = new Config() @@ -272,8 +272,8 @@ class ConfigTest extends DDSpecification { config.healthMetricsStatsdPort == 654 config.traceSamplingServiceRules == [a: "1"] config.traceSamplingOperationRules == [b: "1"] - config.traceSamplingDefaultRate == 0.5 - config.traceSamplingRateLimit == 200 + config.traceSampleRate == 0.5 + config.traceRateLimit == 200 } def "specify overrides via env vars"() { From a280ae6b7fe8da892a7261175ecc061608bdc373 Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Fri, 17 Jan 2020 11:05:44 -0800 Subject: [PATCH 12/37] Check for both regular and lowercase names with decorator enabled flags. --- dd-trace-api/src/main/java/datadog/trace/api/Config.java | 3 ++- .../opentracing/decorators/SpanDecoratorTest.groovy | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/dd-trace-api/src/main/java/datadog/trace/api/Config.java b/dd-trace-api/src/main/java/datadog/trace/api/Config.java index c50d4026fb..cbaca72e7e 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/Config.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/Config.java @@ -591,7 +591,8 @@ public class Config { } public boolean isDecoratorEnabled(final String name) { - return getBooleanSettingFromEnvironment("trace." + name.toLowerCase() + ".enabled", true); + return getBooleanSettingFromEnvironment("trace." + name + ".enabled", true) + && getBooleanSettingFromEnvironment("trace." + name.toLowerCase() + ".enabled", true); } /** diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/SpanDecoratorTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/SpanDecoratorTest.groovy index ceb265e0ff..87744428b3 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/SpanDecoratorTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/SpanDecoratorTest.groovy @@ -457,7 +457,7 @@ class SpanDecoratorTest extends DDSpecification { def "disable decorator via config"() { setup: ConfigUtils.updateConfig { - System.setProperty("dd.trace." + PeerServiceDecorator.getSimpleName().toLowerCase() + ".enabled", "false") + System.setProperty("dd.trace.${decorator}.enabled", "false") } tracer = DDTracer.builder() @@ -475,8 +475,13 @@ class SpanDecoratorTest extends DDSpecification { cleanup: ConfigUtils.updateConfig { - System.clearProperty("dd.trace." + PeerServiceDecorator.getSimpleName().toLowerCase() + ".enabled") + System.clearProperty("dd.trace.${decorator}.enabled") } + + where: + decorator | _ + PeerServiceDecorator.getSimpleName().toLowerCase() | _ + PeerServiceDecorator.getSimpleName() | _ } def "disabling service decorator does not disable split by tags"() { From f9e43516ad69d0443e1269e6ca6f9113f8c4bedc Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Tue, 21 Jan 2020 08:29:48 -0800 Subject: [PATCH 13/37] Set timeouts on individual tests and increase overall test timeout. --- .../agent/AgentLoadedIntoBootstrapTest.groovy | 2 ++ .../trace/agent/CustomLogManagerTest.groovy | 2 ++ .../datadog/trace/agent/JMXFetchTest.groovy | 2 ++ .../datadog/trace/agent/LogLevelTest.groovy | 23 ++++++++++--------- gradle/java.gradle | 4 ++-- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/dd-java-agent/src/test/groovy/datadog/trace/agent/AgentLoadedIntoBootstrapTest.groovy b/dd-java-agent/src/test/groovy/datadog/trace/agent/AgentLoadedIntoBootstrapTest.groovy index a3d8d48181..91ee6bae91 100644 --- a/dd-java-agent/src/test/groovy/datadog/trace/agent/AgentLoadedIntoBootstrapTest.groovy +++ b/dd-java-agent/src/test/groovy/datadog/trace/agent/AgentLoadedIntoBootstrapTest.groovy @@ -3,7 +3,9 @@ package datadog.trace.agent import datadog.trace.agent.test.IntegrationTestUtils import jvmbootstraptest.AgentLoadedChecker import spock.lang.Specification +import spock.lang.Timeout +@Timeout(30) class AgentLoadedIntoBootstrapTest extends Specification { def "Agent loads in when separate jvm is launched"() { diff --git a/dd-java-agent/src/test/groovy/datadog/trace/agent/CustomLogManagerTest.groovy b/dd-java-agent/src/test/groovy/datadog/trace/agent/CustomLogManagerTest.groovy index ca1f0be952..665e780b94 100644 --- a/dd-java-agent/src/test/groovy/datadog/trace/agent/CustomLogManagerTest.groovy +++ b/dd-java-agent/src/test/groovy/datadog/trace/agent/CustomLogManagerTest.groovy @@ -4,7 +4,9 @@ import datadog.trace.agent.test.IntegrationTestUtils import jvmbootstraptest.LogManagerSetter import spock.lang.Requires import spock.lang.Specification +import spock.lang.Timeout +@Timeout(30) // Note: this test is fails on IBM JVM, we would need to investigate this at some point @Requires({ !System.getProperty("java.vm.name").contains("IBM J9 VM") }) class CustomLogManagerTest extends Specification { diff --git a/dd-java-agent/src/test/groovy/datadog/trace/agent/JMXFetchTest.groovy b/dd-java-agent/src/test/groovy/datadog/trace/agent/JMXFetchTest.groovy index de5ac7369c..d74195174c 100644 --- a/dd-java-agent/src/test/groovy/datadog/trace/agent/JMXFetchTest.groovy +++ b/dd-java-agent/src/test/groovy/datadog/trace/agent/JMXFetchTest.groovy @@ -6,9 +6,11 @@ import jvmbootstraptest.AgentLoadedChecker import org.junit.Rule import org.junit.contrib.java.lang.system.RestoreSystemProperties import spock.lang.Specification +import spock.lang.Timeout import java.lang.reflect.Method +@Timeout(30) class JMXFetchTest extends Specification { @Rule diff --git a/dd-java-agent/src/test/groovy/datadog/trace/agent/LogLevelTest.groovy b/dd-java-agent/src/test/groovy/datadog/trace/agent/LogLevelTest.groovy index 22d415e43e..5bd2b47b7e 100644 --- a/dd-java-agent/src/test/groovy/datadog/trace/agent/LogLevelTest.groovy +++ b/dd-java-agent/src/test/groovy/datadog/trace/agent/LogLevelTest.groovy @@ -1,11 +1,11 @@ package datadog.trace.agent import datadog.trace.agent.test.IntegrationTestUtils - import jvmbootstraptest.LogLevelChecker import spock.lang.Specification +import spock.lang.Timeout - +@Timeout(30) class LogLevelTest extends Specification { @@ -17,23 +17,25 @@ class LogLevelTest extends Specification { def "dd.trace.debug false"() { expect: IntegrationTestUtils.runOnSeparateJvm(LogLevelChecker.getName() - , ["-Ddd.trace.debug=false","-Ddd.jmxfetch.enabled=false","-Ddd.trace.enabled=false"] as String[] + , ["-Ddd.trace.debug=false", "-Ddd.jmxfetch.enabled=false", "-Ddd.trace.enabled=false"] as String[] , "" as String[] , [:] , true) == 1 } + def "SLF4J DEBUG && dd.trace.debug is false"() { expect: IntegrationTestUtils.runOnSeparateJvm(LogLevelChecker.getName() - , ["-Ddd.trace.debug=false","-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug","-Ddd.jmxfetch.enabled=false","-Ddd.trace.enabled=false"] as String[] + , ["-Ddd.trace.debug=false", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug", "-Ddd.jmxfetch.enabled=false", "-Ddd.trace.enabled=false"] as String[] , "" as String[] , [:] , true) == 0 } + def "dd.trace.debug is false && DD_TRACE_DEBUG is true"() { expect: IntegrationTestUtils.runOnSeparateJvm(LogLevelChecker.getName() - , ["-Ddd.trace.debug=false","-Ddd.jmxfetch.enabled=false","-Ddd.trace.enabled=false"] as String[] + , ["-Ddd.trace.debug=false", "-Ddd.jmxfetch.enabled=false", "-Ddd.trace.enabled=false"] as String[] , "" as String[] , ["DD_TRACE_DEBUG": "true"] , true) == 1 @@ -42,7 +44,7 @@ class LogLevelTest extends Specification { def "dd.trace.debug is true"() { expect: IntegrationTestUtils.runOnSeparateJvm(LogLevelChecker.getName() - , ["-Ddd.trace.debug=true","-Ddd.jmxfetch.enabled=false","-Ddd.trace.enabled=false"] as String[] + , ["-Ddd.trace.debug=true", "-Ddd.jmxfetch.enabled=false", "-Ddd.trace.enabled=false"] as String[] , "" as String[] , [:] , true) == 0 @@ -52,7 +54,7 @@ class LogLevelTest extends Specification { def "DD_TRACE_DEBUG is true"() { expect: IntegrationTestUtils.runOnSeparateJvm(LogLevelChecker.getName() - , ["-Ddd.jmxfetch.enabled=false","-Ddd.trace.enabled=false"] as String[] + , ["-Ddd.jmxfetch.enabled=false", "-Ddd.trace.enabled=false"] as String[] , "" as String[] , ["DD_TRACE_DEBUG": "true"] , true) == 0 @@ -61,18 +63,17 @@ class LogLevelTest extends Specification { def "dd.trace.debug is true && DD_TRACE_DEBUG is false"() { expect: IntegrationTestUtils.runOnSeparateJvm(LogLevelChecker.getName() - , ["-Ddd.trace.debug=true","-Ddd.jmxfetch.enabled=false","-Ddd.trace.enabled=false"] as String[] + , ["-Ddd.trace.debug=true", "-Ddd.jmxfetch.enabled=false", "-Ddd.trace.enabled=false"] as String[] , "" as String[] , ["DD_TRACE_DEBUG": "false"] , true) == 0 } - def "SLF4J DEBUG && DD_TRACE_DEBUG is false"() { expect: IntegrationTestUtils.runOnSeparateJvm(LogLevelChecker.getName() - , ["-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug","-Ddd.jmxfetch.enabled=false","-Ddd.trace.enabled=false"] as String[] + , ["-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug", "-Ddd.jmxfetch.enabled=false", "-Ddd.trace.enabled=false"] as String[] , "" as String[] , ["DD_TRACE_DEBUG": "false"] , true) == 0 @@ -81,7 +82,7 @@ class LogLevelTest extends Specification { def "SLF4J INFO && DD_TRACE_DEBUG is true"() { expect: IntegrationTestUtils.runOnSeparateJvm(LogLevelChecker.getName() - , ["-Ddatadog.slf4j.simpleLogger.defaultLogLevel=info","-Ddd.jmxfetch.enabled=false","-Ddd.trace.enabled=false"] as String[] + , ["-Ddatadog.slf4j.simpleLogger.defaultLogLevel=info", "-Ddd.jmxfetch.enabled=false", "-Ddd.trace.enabled=false"] as String[] , "" as String[] , ["DD_TRACE_DEBUG": "true"] , true) == 1 diff --git a/gradle/java.gradle b/gradle/java.gradle index 22c8dcb7c2..c5d3f1c40b 100644 --- a/gradle/java.gradle +++ b/gradle/java.gradle @@ -332,8 +332,8 @@ for (def env : System.getenv().entrySet()) { } tasks.withType(Test).configureEach { - // All tests must complete within 2 minutes. - timeout = Duration.ofMinutes(2) + // All tests must complete within 3 minutes. + timeout = Duration.ofMinutes(3) // Disable all tests if skipTests property was specified onlyIf { !project.rootProject.hasProperty("skipTests") } From bc72b9271adab3f645fac147ee0d64dbc32da5ad Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Thu, 23 Jan 2020 08:39:06 -0500 Subject: [PATCH 14/37] Update gradle to 6.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1ba7206f88..31a0802f36 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 53026932a8f796bfda97ddea1ddbc284bb524f69 Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Thu, 23 Jan 2020 08:39:17 -0500 Subject: [PATCH 15/37] Update task tree plugin --- dd-trace-java.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-trace-java.gradle b/dd-trace-java.gradle index 0252c35a52..f64130f74b 100644 --- a/dd-trace-java.gradle +++ b/dd-trace-java.gradle @@ -9,7 +9,7 @@ plugins { // Not applying google java format by default because it gets confused by stray java build // files in 'workspace' build directory in CI id 'com.github.sherter.google-java-format' version '0.8' apply false - id 'com.dorongold.task-tree' version '1.4' + id 'com.dorongold.task-tree' version '1.5' } def isCI = System.getenv("CI") != null From be6a7730bf3f508cc4eb4fd190fa22015b4922e4 Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Thu, 23 Jan 2020 09:39:46 -0500 Subject: [PATCH 16/37] Update kotlin version --- gradle/dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 6aebc7d7d4..bea606ba2b 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -17,7 +17,7 @@ ext { lombok : "1.18.10", bytebuddy : "1.10.6", scala : "2.11.12", // Last version to support Java 7 (2.12+ require Java 8+) - kotlin : "1.3.50", + kotlin : "1.3.61", coroutines : "1.3.0" ] From 950389587c47355a06e5d8bbbf5825bf270d0deb Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Thu, 23 Jan 2020 08:39:26 -0500 Subject: [PATCH 17/37] Simplify groovy/scala/kotlin compile dependency hack --- .../instrumentation/java-concurrent/java-concurrent.gradle | 4 +--- gradle/test-with-kotlin.gradle | 5 +++-- gradle/test-with-scala.gradle | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/dd-java-agent/instrumentation/java-concurrent/java-concurrent.gradle b/dd-java-agent/instrumentation/java-concurrent/java-concurrent.gradle index 77de36fba9..f25582a200 100644 --- a/dd-java-agent/instrumentation/java-concurrent/java-concurrent.gradle +++ b/dd-java-agent/instrumentation/java-concurrent/java-concurrent.gradle @@ -7,7 +7,6 @@ apply from: "${rootDir}/gradle/java.gradle" apply from: "${rootDir}/gradle/test-with-scala.gradle" -apply from: "${rootDir}/gradle/test-with-kotlin.gradle" apply plugin: 'org.unbroken-dome.test-sets' @@ -16,8 +15,7 @@ testSets { } compileSlickTestGroovy { - classpath = classpath.plus(files(compileSlickTestScala.destinationDir)) - dependsOn compileSlickTestScala + classpath += files(sourceSets.slickTest.scala.classesDirectory) } dependencies { diff --git a/gradle/test-with-kotlin.gradle b/gradle/test-with-kotlin.gradle index bd2f8ad295..237b244b29 100644 --- a/gradle/test-with-kotlin.gradle +++ b/gradle/test-with-kotlin.gradle @@ -2,6 +2,7 @@ apply plugin: 'kotlin' compileTestGroovy { - classpath = classpath.plus(files(compileTestKotlin.destinationDir)) - dependsOn compileTestKotlin + //Note: look like it should be `classpath += files(sourceSets.test.kotlin.classesDirectory)` + //instead, but kotlin plugin doesn't support it (yet?) + classpath += files(compileTestKotlin.destinationDir) } diff --git a/gradle/test-with-scala.gradle b/gradle/test-with-scala.gradle index 420a3bc64e..7c6ae2be48 100644 --- a/gradle/test-with-scala.gradle +++ b/gradle/test-with-scala.gradle @@ -13,6 +13,5 @@ configurations { } compileTestGroovy { - classpath = classpath.plus(files(compileTestScala.destinationDir)) - dependsOn compileTestScala + classpath += files(sourceSets.test.scala.classesDirectory) } From 17af9b752cec09fbc200e498883ed52c2efb7c54 Mon Sep 17 00:00:00 2001 From: dougqh Date: Thu, 23 Jan 2020 10:40:48 -0500 Subject: [PATCH 18/37] Fix typo in test name --- .../agent/integration/classloading/ClassLoadingTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-java-agent/src/test/groovy/datadog/trace/agent/integration/classloading/ClassLoadingTest.groovy b/dd-java-agent/src/test/groovy/datadog/trace/agent/integration/classloading/ClassLoadingTest.groovy index 0a24d3b322..c4ba7012fa 100644 --- a/dd-java-agent/src/test/groovy/datadog/trace/agent/integration/classloading/ClassLoadingTest.groovy +++ b/dd-java-agent/src/test/groovy/datadog/trace/agent/integration/classloading/ClassLoadingTest.groovy @@ -78,7 +78,7 @@ class ClassLoadingTest extends Specification { loader.count == countAfterFirstLoad } - def "make sure that ByteBuddy doesn't resue cached type descriptions between different classloaders"() { + def "make sure that ByteBuddy doesn't reuse cached type descriptions between different classloaders"() { setup: CountingClassLoader loader1 = new CountingClassLoader(classpath) CountingClassLoader loader2 = new CountingClassLoader(classpath) From 726236bd64d76da9770df52022b89bf623d880a2 Mon Sep 17 00:00:00 2001 From: dougqh Date: Thu, 23 Jan 2020 10:55:16 -0500 Subject: [PATCH 19/37] Type cache overhaul This change overhauls the core type cache The new approach aims to achieve several things... 1 - cache is strictly bounded -- no variance for number of classes of ClassLoaders 2 - cache is significantly smaller 3 - cache doesn't compromise start-up time 4 - primary eviction policy isn't driven by time 5 - primary eviction policy isn't driven by GC There are some slight compromises here. In practice, start-up does increase slightly in a memory rich environment; however, start-up improves considerably in a memory poor environment. The basic approcach is to have a single unified Guava cache for all ClassLoaders -- nominally keyed a composite of ClassLoader & class name The ByteBuddy CacheProvider are simply thin wrappers around the Guava cache associated to a particular ClassLoader However rather than having a large number of WeakReferences floating around. The cache assigns an ID to each ClassLoader. To further avoid, consuming memory the cache only preserves a small map of Loader / ID assignments. This means a ClassLoader may have more than one active ID. This introduce the possibility for ID exhaustion. That unlikely case is handle by retiring the internal CacheInstance and starting anew. --- .../trace/agent/tooling/AgentTooling.java | 2 +- .../agent/tooling/DDCachingPoolStrategy.java | 329 +++++++++++++----- .../agent/tooling/CacheProviderTest.groovy | 223 ++++++++++++ .../tooling/EvictingCacheProviderTest.groovy | 102 ------ 4 files changed, 457 insertions(+), 199 deletions(-) create mode 100644 dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy delete mode 100644 dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/EvictingCacheProviderTest.groovy diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentTooling.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentTooling.java index ad744a15fd..c20192b383 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentTooling.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentTooling.java @@ -16,7 +16,7 @@ public class AgentTooling { } private static final DDLocationStrategy LOCATION_STRATEGY = new DDLocationStrategy(); - private static final DDCachingPoolStrategy POOL_STRATEGY = new DDCachingPoolStrategy(CLEANER); + private static final DDCachingPoolStrategy POOL_STRATEGY = new DDCachingPoolStrategy(); public static void init() { // Only need to trigger static initializers for now. diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java index 886d742c78..a1ad033970 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java @@ -1,146 +1,283 @@ package datadog.trace.agent.tooling; -import static datadog.trace.agent.tooling.ClassLoaderMatcher.BOOTSTRAP_CLASSLOADER; -import static datadog.trace.agent.tooling.ClassLoaderMatcher.skipClassLoader; import static net.bytebuddy.agent.builder.AgentBuilder.PoolStrategy; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import datadog.trace.bootstrap.WeakMap; -import java.security.SecureClassLoader; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import lombok.extern.slf4j.Slf4j; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.ClassFileLocator; import net.bytebuddy.pool.TypePool; /** - * Custom Pool strategy. + * NEW (Jan 2020) Custom Pool strategy. * - *

Here we are using WeakMap.Provider as the backing ClassLoader -> CacheProvider lookup. + *

    + * Uses a Guava Cache directly... + *
  • better control over locking than WeakMap.Provider + *
  • provides direct control over concurrency level + *
  • initial and maximum capacity + *
* - *

We also use our bootstrap proxy when matching against the bootstrap loader. + *

    + * There two core parts to the cache... + *
  • a cache of ID assignments for ClassLoaders + *
  • a single cache of TypeResolutions for all ClassLoaders - keyed by a custom composite key + * that combines loader ID & name + *
* - *

The CacheProvider is a custom implementation that uses guava's cache to expire and limit size. + *

This design was chosen to create a single limited size cache that can be adjusted + * for the entire application -- without having to create a large number of WeakReference objects. * - *

By evicting from the cache we are able to reduce the memory overhead of the agent for apps - * that have many classes. + *

The ID assignment mostly assigns a single ID to each ClassLoader, but the maximumSize + * restriction means that an evicted ClassLoader could be assigned another ID later on. * - *

See eviction policy below. + *

For the validity of the cache, the important part is that ID assignment guarantees that + * no two ClassLoaders share the same ID. + * + *

NOTE: As an additional safe-guard, a new CacheInstance can be created if the original loader ID + * sequence is exhausted. */ -public class DDCachingPoolStrategy - implements PoolStrategy, WeakMap.ValueSupplier { - - // Need this because we can't put null into the typePoolCache map. - private static final ClassLoader BOOTSTRAP_CLASSLOADER_PLACEHOLDER = - new SecureClassLoader(null) {}; - - private final WeakMap typePoolCache = - WeakMap.Provider.newWeakMap(); - private final Cleaner cleaner; - - public DDCachingPoolStrategy(final Cleaner cleaner) { - this.cleaner = cleaner; - } +@Slf4j +public class DDCachingPoolStrategy implements PoolStrategy { + /** + * Most of the logic exists in CacheInstance This volatile + exhaustion checking is defense + * against loader ID exhaustion + */ + volatile CacheInstance cacheInstance = new CacheInstance(); @Override public TypePool typePool(final ClassFileLocator classFileLocator, final ClassLoader classLoader) { - final ClassLoader key = - BOOTSTRAP_CLASSLOADER == classLoader ? BOOTSTRAP_CLASSLOADER_PLACEHOLDER : classLoader; - final TypePool.CacheProvider cache = typePoolCache.computeIfAbsent(key, this); + CacheInstance cacheInstance = this.cacheInstance; - return new TypePool.Default.WithLazyResolution( - cache, classFileLocator, TypePool.Default.ReaderMode.FAST); + TypePool typePool = cacheInstance.typePool(classFileLocator, classLoader); + if (cacheInstance.exhaustedLoaderIdSeq()) { + // If the loader ID sequence is exhausted, drop the prior cache & start over + // The ID space is so large that this shouldn't occur + log.error("cacheInstance exhausted - rebuilding cache"); + + this.cacheInstance = new CacheInstance(); + } + return typePool; } - @Override - public TypePool.CacheProvider get(final ClassLoader key) { - if (BOOTSTRAP_CLASSLOADER_PLACEHOLDER != key && skipClassLoader().matches(key)) { - // Don't bother creating a cache for a classloader that won't match. - // (avoiding a lot of DelegatingClassLoader instances) - // This is primarily an optimization. - return TypePool.CacheProvider.NoOp.INSTANCE; - } else { - return EvictingCacheProvider.withObjectType(cleaner, 1, TimeUnit.MINUTES); + /* + * CacheInstance embodies the core of the cache. In general, we only + * expect a single CacheInstance object to ever be created. + * + * However, CacheInstance does provide an extra layer of protection + * against loaderIdSeq exhaustion. If ever the loaderIdSeq of + * CacheInstance is exhausted, then DDCachingPoolStrategy.typePool + * will detect that and discard the CacheInstance. + * + * At that time, a new CacheInstance with a fresh sequence will + * be created in its place. + */ + private static final class CacheInstance { + static final int CONCURRENCY_LEVEL = 8; + static final int LOADER_CAPACITY = 64; + static final int TYPE_CAPACITY = 64; + + static final long BOOTSTRAP_ID = Long.MIN_VALUE; + static final long START_ID = BOOTSTRAP_ID + 1; + static final long LIMIT_ID = Long.MAX_VALUE - 10; + + static final long EXHAUSTED_ID = LIMIT_ID; + + // Many things are package visible for testing purposes -- + // others to avoid creation of synthetic accessors + + /** + * Cache of recent loaderIds: guarantee is that no two loaders are given the same ID; however, a + * loader may be given more than one ID if it falls out the cache. + */ + final Cache loaderIdCache = + CacheBuilder.newBuilder() + .weakKeys() + .concurrencyLevel(CONCURRENCY_LEVEL) + .initialCapacity(LOADER_CAPACITY / 2) + .maximumSize(LOADER_CAPACITY) + .build(); + + /** + * Single shared Type.Resolution cache -- uses a composite key of loader ID & class name The + * initial capacity is set to the maximum capacity to avoid expansion overhead. + */ + final Cache sharedResolutionCache = + CacheBuilder.newBuilder() + .softValues() + .concurrencyLevel(CONCURRENCY_LEVEL) + .initialCapacity(TYPE_CAPACITY) + .maximumSize(TYPE_CAPACITY) + .build(); + + /** + * ID sequence for loaders -- BOOTSTRAP_ID is reserved -- starts higher at START_ID Sequence + * proceeds up until LIMIT_ID at which the sequence and this cacheInstance are considered to be + * exhausted + */ + final AtomicLong loaderIdSeq = new AtomicLong(START_ID); + + /** Fast path for bootstrap */ + final SharedResolutionCacheAdapter bootstrapCacheProvider = + new SharedResolutionCacheAdapter(BOOTSTRAP_ID, sharedResolutionCache); + + private final Callable provisionIdCallable = + new Callable() { + @Override + public final Long call() throws Exception { + return provisionId(); + } + }; + + final TypePool typePool( + final ClassFileLocator classFileLocator, final ClassLoader classLoader) { + if (classLoader == null) { + return createCachingTypePool(bootstrapCacheProvider, classFileLocator); + } + + Long existingId = loaderIdCache.getIfPresent(classLoader); + if (existingId != null) { + return createCachingTypePool(existingId, classFileLocator); + } + + if (exhaustedLoaderIdSeq()) { + return createNonCachingTypePool(classFileLocator); + } + + long provisionedId = 0; + try { + provisionedId = loaderIdCache.get(classLoader, this.provisionIdCallable); + } catch (ExecutionException e) { + log.error("unexpected exception", e); + + return createNonCachingTypePool(classFileLocator); + } + if (provisionedId == EXHAUSTED_ID) { + return createNonCachingTypePool(classFileLocator); + } else { + return createCachingTypePool(provisionedId, classFileLocator); + } + } + + final boolean exhaustedLoaderIdSeq() { + return (loaderIdSeq.get() >= LIMIT_ID); + } + + final long provisionId() { + do { + long curId = loaderIdSeq.get(); + if (curId >= LIMIT_ID) return EXHAUSTED_ID; + + long newId = curId + 1; + boolean acquired = loaderIdSeq.compareAndSet(curId, newId); + if (acquired) return newId; + } while (!Thread.currentThread().isInterrupted()); + + return EXHAUSTED_ID; + } + + private final TypePool createNonCachingTypePool(final ClassFileLocator classFileLocator) { + return new TypePool.Default.WithLazyResolution( + TypePool.CacheProvider.NoOp.INSTANCE, classFileLocator, TypePool.Default.ReaderMode.FAST); + } + + private final TypePool.CacheProvider createCacheProvider(final long loaderId) { + return new SharedResolutionCacheAdapter(loaderId, sharedResolutionCache); + } + + private final TypePool createCachingTypePool( + final long loaderId, final ClassFileLocator classFileLocator) { + return new TypePool.Default.WithLazyResolution( + createCacheProvider(loaderId), + classFileLocator, + TypePool.Default.ReaderMode.FAST); + } + + private final TypePool createCachingTypePool( + final TypePool.CacheProvider cacheProvider, final ClassFileLocator classFileLocator) { + return new TypePool.Default.WithLazyResolution( + cacheProvider, classFileLocator, TypePool.Default.ReaderMode.FAST); + } + + final long approximateSize() { + return sharedResolutionCache.size(); } } - private static class EvictingCacheProvider implements TypePool.CacheProvider { + /** + * TypeCacheKey is key for the sharedResolutionCache. It is a mix of a cacheId/loaderId & a type + * name. + */ + static final class TypeCacheKey { + private final long cacheId; + private final String name; - /** A map containing all cached resolutions by their names. */ - private final Cache cache; + private final int hashCode; - /** Creates a new simple cache. */ - private EvictingCacheProvider( - final Cleaner cleaner, final long expireDuration, final TimeUnit unit) { - cache = - CacheBuilder.newBuilder() - .initialCapacity(100) // Per classloader, so we want a small default. - .maximumSize(5000) - .softValues() - .expireAfterAccess(expireDuration, unit) - .build(); + TypeCacheKey(final long cacheId, final String name) { + this.cacheId = cacheId; + this.name = name; - /* - * The cache only does cleanup on occasional reads and writes. - * We want to ensure this happens more regularly, so we schedule a thread to do run cleanup manually. - */ - cleaner.scheduleCleaning(cache, CacheCleaner.CLEANER, expireDuration, unit); + hashCode = (int) (31 * cacheId) ^ name.hashCode(); } - private static EvictingCacheProvider withObjectType( - final Cleaner cleaner, final long expireDuration, final TimeUnit unit) { - final EvictingCacheProvider cacheProvider = - new EvictingCacheProvider(cleaner, expireDuration, unit); - cacheProvider.register( - Object.class.getName(), new TypePool.Resolution.Simple(TypeDescription.OBJECT)); - return cacheProvider; + @Override + public final int hashCode() { + return hashCode; + } + + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof TypeCacheKey)) return false; + + TypeCacheKey that = (TypeCacheKey) obj; + return (cacheId == that.cacheId) && name.equals(that.name); + } + } + + static final class SharedResolutionCacheAdapter implements TypePool.CacheProvider { + private static final String OBJECT_NAME = "java.lang.Object"; + private static final TypePool.Resolution OBJECT_RESOLUTION = + new TypePool.Resolution.Simple(TypeDescription.OBJECT); + + private final long cacheId; + private final Cache sharedResolutionCache; + + SharedResolutionCacheAdapter( + final long cacheId, final Cache sharedResolutionCache) { + this.cacheId = cacheId; + this.sharedResolutionCache = sharedResolutionCache; } @Override public TypePool.Resolution find(final String name) { - return cache.getIfPresent(name); + TypePool.Resolution existingResolution = sharedResolutionCache.getIfPresent(new TypeCacheKey(cacheId, name)); + if ( existingResolution != null ) return existingResolution; + + if ( OBJECT_NAME.equals(name) ) { + return OBJECT_RESOLUTION; + } + + return null; } @Override public TypePool.Resolution register(final String name, final TypePool.Resolution resolution) { - try { - return cache.get(name, new ResolutionProvider(resolution)); - } catch (final ExecutionException e) { + if ( OBJECT_NAME.equals(name) ) { return resolution; } + + sharedResolutionCache.put(new TypeCacheKey(cacheId, name), resolution); + return resolution; } @Override public void clear() { - cache.invalidateAll(); - } - - public long size() { - return cache.size(); - } - - private static class CacheCleaner implements Cleaner.Adapter { - private static final CacheCleaner CLEANER = new CacheCleaner(); - - @Override - public void clean(final Cache target) { - target.cleanUp(); - } - } - - private static class ResolutionProvider implements Callable { - private final TypePool.Resolution value; - - private ResolutionProvider(final TypePool.Resolution value) { - this.value = value; - } - - @Override - public TypePool.Resolution call() { - return value; - } + // Allowing the high-level eviction policy make the clearing decisions } } } diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy new file mode 100644 index 0000000000..dcc26f8b32 --- /dev/null +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy @@ -0,0 +1,223 @@ +package datadog.trace.agent.tooling + +import datadog.trace.util.gc.GCUtils +import datadog.trace.util.test.DDSpecification +import net.bytebuddy.description.type.TypeDescription +import net.bytebuddy.dynamic.ClassFileLocator +import net.bytebuddy.pool.TypePool +import spock.lang.Timeout + +import java.lang.ref.WeakReference +import java.security.SecureClassLoader +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicReference + +import static datadog.trace.agent.tooling.AgentTooling.CLEANER + +@Timeout(5) +class CacheProviderTest extends DDSpecification { + def "key equivalence"() { + setup: + def key1 = new DDCachingPoolStrategy.TypeCacheKey(1, "foo") + def key2 = new DDCachingPoolStrategy.TypeCacheKey(1, "foo") + + expect: + key1.hashCode() == key2.hashCode() + key1.equals(key2) + } + + def "different loader - same name"() { + setup: + def key1 = new DDCachingPoolStrategy.TypeCacheKey(1, "foo") + def key2 = new DDCachingPoolStrategy.TypeCacheKey(2, "foo") + + expect: + // not strictly guaranteed, but important for performance + key1.hashCode() != key2.hashCode() + + !key1.equals(key2) + } + + def "same loader - different name"() { + setup: + def key1 = new DDCachingPoolStrategy.TypeCacheKey(1, "foo") + def key2 = new DDCachingPoolStrategy.TypeCacheKey(1, "foobar") + + expect: + // not strictly guaranteed, but important for performance + key1.hashCode() != key2.hashCode() + + !key1.equals(key2) + } + + def "test basic caching"() { + setup: + def cacheInstance = new DDCachingPoolStrategy.CacheInstance(); + + def cacheProvider = cacheInstance.createCacheProvider(1); + + when: + cacheProvider.register("foo", new TypePool.Resolution.Simple(TypeDescription.VOID)) + + then: + // not strictly guaranteed, but fine for this test + cacheProvider.find("foo") != null + cacheInstance.approximateSize() == 1 + } + + def "test ID equivalence"() { + setup: + def cacheInstance = new DDCachingPoolStrategy.CacheInstance(); + + def cacheProvider1A = cacheInstance.createCacheProvider(1); + def cacheProvider1B = cacheInstance.createCacheProvider(1); + + when: + cacheProvider1A.register("foo", newVoid()) + + then: + // not strictly guaranteed, but fine for this test + cacheProvider1A.find("foo") != null + cacheProvider1B.find("foo") != null + + cacheProvider1A.find("foo").is(cacheProvider1B.find("foo")) + cacheInstance.approximateSize() == 1 + } + + def "test ID separation"() { + setup: + def cacheInstance = new DDCachingPoolStrategy.CacheInstance(); + + def cacheProvider1 = cacheInstance.createCacheProvider(1); + def cacheProvider2 = cacheInstance.createCacheProvider(2); + + when: + cacheProvider1.register("foo", newVoid()) + cacheProvider2.register("foo", newVoid()) + + then: + // not strictly guaranteed, but fine for this test + cacheProvider1.find("foo") != null + cacheProvider2.find("foo") != null + + !cacheProvider1.find("foo").is(cacheProvider2.find("foo")) + cacheInstance.approximateSize() == 2 + } + + def "test loader ID assignment"() { + setup: + def cacheInstance = new DDCachingPoolStrategy.CacheInstance() + + def locator1 = newLocator() + def loader1 = newClassLoader() + + def locator2 = newLocator() + def loader2 = newClassLoader() + + when: + cacheInstance.typePool(locator1, loader1) + cacheInstance.typePool(locator2, loader2) + + then: + def loaderId1 = cacheInstance.loaderIdCache.getIfPresent(loader1) + def loaderId2 = cacheInstance.loaderIdCache.getIfPresent(loader2) + + // both were assigned an ID -- technically these can fall out of the ID cache + loaderId1 != null + loaderId2 != null + + // both IDs are not the BOOTSTRAP_ID + loaderId1 != DDCachingPoolStrategy.CacheInstance.BOOTSTRAP_ID + loaderId2 != DDCachingPoolStrategy.CacheInstance.BOOTSTRAP_ID + + // class loaders don't share an ID + cacheInstance.loaderIdCache.getIfPresent(loader1) != cacheInstance.loaderIdCache.getIfPresent(loader2) + } + + def "test loader ID exhaustion"() { + setup: + def cacheInstance = new DDCachingPoolStrategy.CacheInstance() + + when: + cacheInstance.loaderIdSeq.set(DDCachingPoolStrategy.CacheInstance.LIMIT_ID - 2) + + then: + cacheInstance.provisionId() != DDCachingPoolStrategy.CacheInstance.EXHAUSTED_ID + + then: + // once exhausted provisioning -- stays exhausted + cacheInstance.provisionId() == DDCachingPoolStrategy.CacheInstance.EXHAUSTED_ID + cacheInstance.exhaustedLoaderIdSeq() + cacheInstance.provisionId() == DDCachingPoolStrategy.CacheInstance.EXHAUSTED_ID + cacheInstance.exhaustedLoaderIdSeq() + cacheInstance.provisionId() == DDCachingPoolStrategy.CacheInstance.EXHAUSTED_ID + cacheInstance.exhaustedLoaderIdSeq() + } + + def "test exhaustion cacheInstance switch"() { + setup: + def cachingStrat = new DDCachingPoolStrategy() + def origCacheInstance = cachingStrat.cacheInstance + + cachingStrat.cacheInstance.loaderIdSeq.set(DDCachingPoolStrategy.CacheInstance.LIMIT_ID) + + when: + cachingStrat.typePool(newLocator(), newClassLoader()) + + then: + cachingStrat.cacheInstance != origCacheInstance + } + + def "test cacheInstance capacity"() { + setup: + def cacheInstance = new DDCachingPoolStrategy.CacheInstance() + def capacity = DDCachingPoolStrategy.CacheInstance.TYPE_CAPACITY + + def cacheProvider1 = cacheInstance.createCacheProvider(1); + def cacheProvider2 = cacheInstance.createCacheProvider(2); + + def id = 0 + + when: + (capacity / 2).times { + id += 1 + cacheProvider1.register("foo${id}", newVoid()) + cacheProvider2.register("foo${id}", newVoid()) + } + + then: + // cache will start to proactively free slots & size calc is approximate + cacheInstance.approximateSize() > capacity - 4 + + when: + 10.times { + id += 1 + cacheProvider1.register("foo${id}", newVoid()) + cacheProvider2.register("foo${id}", newVoid()) + } + + then: + // cache will start to proactively free slots & size calc is approximate + cacheInstance.approximateSize() > capacity - 4 + } + + static def newVoid() { + return new TypePool.Resolution.Simple(TypeDescription.VOID) + } + + static def newClassLoader() { + return new SecureClassLoader(null) {}; + } + + static def newLocator() { + return new ClassFileLocator() { + @Override + ClassFileLocator.Resolution locate(String name) throws IOException { + return null + } + + @Override + void close() throws IOException {} + } + } +} diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/EvictingCacheProviderTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/EvictingCacheProviderTest.groovy deleted file mode 100644 index 3de7cc3140..0000000000 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/EvictingCacheProviderTest.groovy +++ /dev/null @@ -1,102 +0,0 @@ -package datadog.trace.agent.tooling - -import datadog.trace.util.gc.GCUtils -import datadog.trace.util.test.DDSpecification -import net.bytebuddy.description.type.TypeDescription -import net.bytebuddy.pool.TypePool -import spock.lang.Timeout - -import java.lang.ref.WeakReference -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicReference - -import static datadog.trace.agent.tooling.AgentTooling.CLEANER - -@Timeout(5) -class EvictingCacheProviderTest extends DDSpecification { - - def "test provider"() { - setup: - def provider = new DDCachingPoolStrategy.EvictingCacheProvider(CLEANER, 2, TimeUnit.MINUTES) - - expect: - provider.size() == 0 - provider.find(className) == null - - when: - provider.register(className, new TypePool.Resolution.Simple(TypeDescription.VOID)) - - then: - provider.size() == 1 - provider.find(className) == new TypePool.Resolution.Simple(TypeDescription.VOID) - - when: - provider.clear() - - then: - provider.size() == 0 - provider.find(className) == null - - where: - className = "SomeClass" - } - - def "test timeout eviction"() { - setup: - def provider = new DDCachingPoolStrategy.EvictingCacheProvider(CLEANER, timeout, TimeUnit.MILLISECONDS) - def resolutionRef = new AtomicReference(new TypePool.Resolution.Simple(TypeDescription.VOID)) - def weakRef = new WeakReference(resolutionRef.get()) - - when: - def lastAccess = System.nanoTime() - provider.register(className, resolutionRef.get()) - - then: - // Ensure continued access prevents expiration. - for (int i = 0; i < timeout + 10; i++) { - assert TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - lastAccess) < timeout: "test took too long on " + i - assert provider.find(className) != null - assert provider.size() == 1 - lastAccess = System.nanoTime() - Thread.sleep(1) - } - - when: - Thread.sleep(timeout) - - then: - provider.find(className) == null - - when: - provider.register(className, resolutionRef.get()) - resolutionRef.set(null) - GCUtils.awaitGC(weakRef) - - then: - // Verify properly GC'd - provider.find(className) == null - weakRef.get() == null - - where: - className = "SomeClass" - timeout = 500 // Takes about 50 ms locally, adding an order of magnitude for CI. - } - - def "test size limit"() { - setup: - def provider = new DDCachingPoolStrategy.EvictingCacheProvider(CLEANER, 2, TimeUnit.MINUTES) - def typeDef = new TypePool.Resolution.Simple(TypeDescription.VOID) - for (int i = 0; i < 10000; i++) { - provider.register("ClassName$i", typeDef) - } - - expect: - provider.size() == 5000 - - when: - provider.clear() - - then: - provider.size() == 0 - } -} From 984d77e44ce0de96df6b7fe00cc7210deb360c94 Mon Sep 17 00:00:00 2001 From: dougqh Date: Thu, 23 Jan 2020 11:15:39 -0500 Subject: [PATCH 20/37] googleJavaFormat & codeNarc --- .../agent/tooling/DDCachingPoolStrategy.java | 25 +++++++------- .../agent/tooling/CacheProviderTest.groovy | 34 ++++++++----------- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java index a1ad033970..657141e97c 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java @@ -29,17 +29,17 @@ import net.bytebuddy.pool.TypePool; * that combines loader ID & name * * - *

This design was chosen to create a single limited size cache that can be adjusted - * for the entire application -- without having to create a large number of WeakReference objects. + *

This design was chosen to create a single limited size cache that can be adjusted for the + * entire application -- without having to create a large number of WeakReference objects. * *

The ID assignment mostly assigns a single ID to each ClassLoader, but the maximumSize * restriction means that an evicted ClassLoader could be assigned another ID later on. * - *

For the validity of the cache, the important part is that ID assignment guarantees that - * no two ClassLoaders share the same ID. + *

For the validity of the cache, the important part is that ID assignment guarantees that no two + * ClassLoaders share the same ID. * - *

NOTE: As an additional safe-guard, a new CacheInstance can be created if the original loader ID - * sequence is exhausted. + *

NOTE: As an additional safe-guard, a new CacheInstance can be created if the original loader + * ID sequence is exhausted. */ @Slf4j public class DDCachingPoolStrategy implements PoolStrategy { @@ -192,9 +192,7 @@ public class DDCachingPoolStrategy implements PoolStrategy { private final TypePool createCachingTypePool( final long loaderId, final ClassFileLocator classFileLocator) { return new TypePool.Default.WithLazyResolution( - createCacheProvider(loaderId), - classFileLocator, - TypePool.Default.ReaderMode.FAST); + createCacheProvider(loaderId), classFileLocator, TypePool.Default.ReaderMode.FAST); } private final TypePool createCachingTypePool( @@ -255,10 +253,11 @@ public class DDCachingPoolStrategy implements PoolStrategy { @Override public TypePool.Resolution find(final String name) { - TypePool.Resolution existingResolution = sharedResolutionCache.getIfPresent(new TypeCacheKey(cacheId, name)); - if ( existingResolution != null ) return existingResolution; + TypePool.Resolution existingResolution = + sharedResolutionCache.getIfPresent(new TypeCacheKey(cacheId, name)); + if (existingResolution != null) return existingResolution; - if ( OBJECT_NAME.equals(name) ) { + if (OBJECT_NAME.equals(name)) { return OBJECT_RESOLUTION; } @@ -267,7 +266,7 @@ public class DDCachingPoolStrategy implements PoolStrategy { @Override public TypePool.Resolution register(final String name, final TypePool.Resolution resolution) { - if ( OBJECT_NAME.equals(name) ) { + if (OBJECT_NAME.equals(name)) { return resolution; } diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy index dcc26f8b32..959313c545 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy @@ -1,18 +1,12 @@ package datadog.trace.agent.tooling -import datadog.trace.util.gc.GCUtils import datadog.trace.util.test.DDSpecification import net.bytebuddy.description.type.TypeDescription import net.bytebuddy.dynamic.ClassFileLocator import net.bytebuddy.pool.TypePool import spock.lang.Timeout -import java.lang.ref.WeakReference import java.security.SecureClassLoader -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicReference - -import static datadog.trace.agent.tooling.AgentTooling.CLEANER @Timeout(5) class CacheProviderTest extends DDSpecification { @@ -52,9 +46,9 @@ class CacheProviderTest extends DDSpecification { def "test basic caching"() { setup: - def cacheInstance = new DDCachingPoolStrategy.CacheInstance(); + def cacheInstance = new DDCachingPoolStrategy.CacheInstance() - def cacheProvider = cacheInstance.createCacheProvider(1); + def cacheProvider = cacheInstance.createCacheProvider(1) when: cacheProvider.register("foo", new TypePool.Resolution.Simple(TypeDescription.VOID)) @@ -67,10 +61,10 @@ class CacheProviderTest extends DDSpecification { def "test ID equivalence"() { setup: - def cacheInstance = new DDCachingPoolStrategy.CacheInstance(); + def cacheInstance = new DDCachingPoolStrategy.CacheInstance() - def cacheProvider1A = cacheInstance.createCacheProvider(1); - def cacheProvider1B = cacheInstance.createCacheProvider(1); + def cacheProvider1A = cacheInstance.createCacheProvider(1) + def cacheProvider1B = cacheInstance.createCacheProvider(1) when: cacheProvider1A.register("foo", newVoid()) @@ -86,10 +80,10 @@ class CacheProviderTest extends DDSpecification { def "test ID separation"() { setup: - def cacheInstance = new DDCachingPoolStrategy.CacheInstance(); + def cacheInstance = new DDCachingPoolStrategy.CacheInstance() - def cacheProvider1 = cacheInstance.createCacheProvider(1); - def cacheProvider2 = cacheInstance.createCacheProvider(2); + def cacheProvider1 = cacheInstance.createCacheProvider(1) + def cacheProvider2 = cacheInstance.createCacheProvider(2) when: cacheProvider1.register("foo", newVoid()) @@ -173,8 +167,8 @@ class CacheProviderTest extends DDSpecification { def cacheInstance = new DDCachingPoolStrategy.CacheInstance() def capacity = DDCachingPoolStrategy.CacheInstance.TYPE_CAPACITY - def cacheProvider1 = cacheInstance.createCacheProvider(1); - def cacheProvider2 = cacheInstance.createCacheProvider(2); + def cacheProvider1 = cacheInstance.createCacheProvider(1) + def cacheProvider2 = cacheInstance.createCacheProvider(2) def id = 0 @@ -201,15 +195,15 @@ class CacheProviderTest extends DDSpecification { cacheInstance.approximateSize() > capacity - 4 } - static def newVoid() { + static newVoid() { return new TypePool.Resolution.Simple(TypeDescription.VOID) } - static def newClassLoader() { - return new SecureClassLoader(null) {}; + static newClassLoader() { + return new SecureClassLoader(null) {} } - static def newLocator() { + static newLocator() { return new ClassFileLocator() { @Override ClassFileLocator.Resolution locate(String name) throws IOException { From 3daad0009d5d37607ffdc8c45f6cd72f2adb27d7 Mon Sep 17 00:00:00 2001 From: Brian Devins-Suresh Date: Fri, 24 Jan 2020 10:58:52 -0500 Subject: [PATCH 21/37] Add null check to hibernate decorator --- .../trace/instrumentation/hibernate/HibernateDecorator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dd-java-agent/instrumentation/hibernate/src/main/java/datadog/trace/instrumentation/hibernate/HibernateDecorator.java b/dd-java-agent/instrumentation/hibernate/src/main/java/datadog/trace/instrumentation/hibernate/HibernateDecorator.java index b9cb30a859..eadd8999f8 100644 --- a/dd-java-agent/instrumentation/hibernate/src/main/java/datadog/trace/instrumentation/hibernate/HibernateDecorator.java +++ b/dd-java-agent/instrumentation/hibernate/src/main/java/datadog/trace/instrumentation/hibernate/HibernateDecorator.java @@ -47,6 +47,9 @@ public class HibernateDecorator extends OrmClientDecorator { @Override public String entityName(final Object entity) { + if (entity == null) { + return null; + } String name = null; final Set annotations = new HashSet<>(); for (final Annotation annotation : entity.getClass().getDeclaredAnnotations()) { From cf877f67e5fa67656857c59395c3c1fbde0ef0a6 Mon Sep 17 00:00:00 2001 From: dougqh Date: Mon, 27 Jan 2020 09:47:36 -0500 Subject: [PATCH 22/37] Working around muzzle quirk Muzzle doesn't like creation of SecureClassLoader-s, so switching to a URLClassLoader for my placeholder loader in tests --- .../groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy index 959313c545..0d7e687850 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy @@ -200,7 +200,7 @@ class CacheProviderTest extends DDSpecification { } static newClassLoader() { - return new SecureClassLoader(null) {} + return new URLClassLoader([] as URL[], (ClassLoader)null); } static newLocator() { From fb871611b5b827d88a8400c96b6f31a071c2abbb Mon Sep 17 00:00:00 2001 From: dougqh Date: Mon, 27 Jan 2020 12:03:44 -0500 Subject: [PATCH 23/37] Replacing ID generation with WeakReference reuse First pass at replacing ID generation with WeakReference reuse In this first version, the Cache was replaced with Cache>. The core cache is still of Cache and TypeCacheKey logically remains a composite key of ClassLoader, class name. The removal of ID assignment means ID exhaustion is no longer na issue, so there's never a need to rebuild the cache. For that reason, CacheInstance has removed and the core caching logic has been moved into DDCachingPoolStrategy. While TypeCacheKey remains conceptually the same, the internals have changed somewhat. The TypeCacheKey now has 3 core fields... - loaderHash - loadeRef - class name Since loader refs are recycled, the fast path for key equivalence can use reference equivalence of the reference objects. This change ripples through the CacheProvider-s which also have to store loaderHash and loaderRef. It may be worth going a step further and switching to a Cache as well. That still avoid the creation of many WeakReference-s, since the underlying CacheProvider will hold a canonical WeakReference per ClassLoader. --- .../agent/tooling/DDCachingPoolStrategy.java | 291 ++++++++---------- .../agent/tooling/CacheProviderTest.groovy | 199 ++++++------ 2 files changed, 228 insertions(+), 262 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java index 657141e97c..1e47032a7a 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java @@ -4,9 +4,9 @@ import static net.bytebuddy.agent.builder.AgentBuilder.PoolStrategy; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicLong; + +import java.lang.ref.WeakReference; + import lombok.extern.slf4j.Slf4j; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.ClassFileLocator; @@ -43,167 +43,94 @@ import net.bytebuddy.pool.TypePool; */ @Slf4j public class DDCachingPoolStrategy implements PoolStrategy { + // Many things are package visible for testing purposes -- + // others to avoid creation of synthetic accessors + + static final int CONCURRENCY_LEVEL = 8; + static final int LOADER_CAPACITY = 64; + static final int TYPE_CAPACITY = 64; + + static final int BOOTSTRAP_HASH = 0; + /** - * Most of the logic exists in CacheInstance This volatile + exhaustion checking is defense - * against loader ID exhaustion + * Cache of recent ClassLoader WeakReferences; used to... + *

    + *
  • Reduced number of WeakReferences created
  • + *
  • Allow for quick fast path equivalence check of composite keys
  • + *
*/ - volatile CacheInstance cacheInstance = new CacheInstance(); + final Cache> loaderRefCache = + CacheBuilder.newBuilder() + .weakKeys() + .concurrencyLevel(CONCURRENCY_LEVEL) + .initialCapacity(LOADER_CAPACITY / 2) + .maximumSize(LOADER_CAPACITY) + .build(); - @Override - public TypePool typePool(final ClassFileLocator classFileLocator, final ClassLoader classLoader) { - CacheInstance cacheInstance = this.cacheInstance; - - TypePool typePool = cacheInstance.typePool(classFileLocator, classLoader); - if (cacheInstance.exhaustedLoaderIdSeq()) { - // If the loader ID sequence is exhausted, drop the prior cache & start over - // The ID space is so large that this shouldn't occur - log.error("cacheInstance exhausted - rebuilding cache"); - - this.cacheInstance = new CacheInstance(); - } - return typePool; - } - - /* - * CacheInstance embodies the core of the cache. In general, we only - * expect a single CacheInstance object to ever be created. - * - * However, CacheInstance does provide an extra layer of protection - * against loaderIdSeq exhaustion. If ever the loaderIdSeq of - * CacheInstance is exhausted, then DDCachingPoolStrategy.typePool - * will detect that and discard the CacheInstance. - * - * At that time, a new CacheInstance with a fresh sequence will - * be created in its place. + /** + * Single shared Type.Resolution cache -- uses a composite key -- + * conceptually of loader & name */ - private static final class CacheInstance { - static final int CONCURRENCY_LEVEL = 8; - static final int LOADER_CAPACITY = 64; - static final int TYPE_CAPACITY = 64; - - static final long BOOTSTRAP_ID = Long.MIN_VALUE; - static final long START_ID = BOOTSTRAP_ID + 1; - static final long LIMIT_ID = Long.MAX_VALUE - 10; - - static final long EXHAUSTED_ID = LIMIT_ID; - - // Many things are package visible for testing purposes -- - // others to avoid creation of synthetic accessors - - /** - * Cache of recent loaderIds: guarantee is that no two loaders are given the same ID; however, a - * loader may be given more than one ID if it falls out the cache. - */ - final Cache loaderIdCache = - CacheBuilder.newBuilder() - .weakKeys() - .concurrencyLevel(CONCURRENCY_LEVEL) - .initialCapacity(LOADER_CAPACITY / 2) - .maximumSize(LOADER_CAPACITY) - .build(); - - /** - * Single shared Type.Resolution cache -- uses a composite key of loader ID & class name The - * initial capacity is set to the maximum capacity to avoid expansion overhead. - */ - final Cache sharedResolutionCache = - CacheBuilder.newBuilder() - .softValues() - .concurrencyLevel(CONCURRENCY_LEVEL) - .initialCapacity(TYPE_CAPACITY) - .maximumSize(TYPE_CAPACITY) - .build(); - - /** - * ID sequence for loaders -- BOOTSTRAP_ID is reserved -- starts higher at START_ID Sequence - * proceeds up until LIMIT_ID at which the sequence and this cacheInstance are considered to be - * exhausted - */ - final AtomicLong loaderIdSeq = new AtomicLong(START_ID); + final Cache sharedResolutionCache = + CacheBuilder.newBuilder() + .softValues() + .concurrencyLevel(CONCURRENCY_LEVEL) + .initialCapacity(TYPE_CAPACITY) + .maximumSize(TYPE_CAPACITY) + .build(); /** Fast path for bootstrap */ final SharedResolutionCacheAdapter bootstrapCacheProvider = - new SharedResolutionCacheAdapter(BOOTSTRAP_ID, sharedResolutionCache); + new SharedResolutionCacheAdapter(BOOTSTRAP_HASH, null, sharedResolutionCache); - private final Callable provisionIdCallable = - new Callable() { - @Override - public final Long call() throws Exception { - return provisionId(); - } - }; - - final TypePool typePool( - final ClassFileLocator classFileLocator, final ClassLoader classLoader) { - if (classLoader == null) { - return createCachingTypePool(bootstrapCacheProvider, classFileLocator); - } - - Long existingId = loaderIdCache.getIfPresent(classLoader); - if (existingId != null) { - return createCachingTypePool(existingId, classFileLocator); - } - - if (exhaustedLoaderIdSeq()) { - return createNonCachingTypePool(classFileLocator); - } - - long provisionedId = 0; - try { - provisionedId = loaderIdCache.get(classLoader, this.provisionIdCallable); - } catch (ExecutionException e) { - log.error("unexpected exception", e); - - return createNonCachingTypePool(classFileLocator); - } - if (provisionedId == EXHAUSTED_ID) { - return createNonCachingTypePool(classFileLocator); - } else { - return createCachingTypePool(provisionedId, classFileLocator); - } + @Override + public final TypePool typePool( + final ClassFileLocator classFileLocator, final ClassLoader classLoader) { + if (classLoader == null) { + return createCachingTypePool(bootstrapCacheProvider, classFileLocator); } - final boolean exhaustedLoaderIdSeq() { - return (loaderIdSeq.get() >= LIMIT_ID); + WeakReference loaderRef = loaderRefCache.getIfPresent(classLoader); + + if ( loaderRef == null ) { + loaderRef = new WeakReference<>(classLoader); + loaderRefCache.put(classLoader, loaderRef); } - final long provisionId() { - do { - long curId = loaderIdSeq.get(); - if (curId >= LIMIT_ID) return EXHAUSTED_ID; + int loaderHash = classLoader.hashCode(); + return createCachingTypePool(loaderHash, loaderRef, classFileLocator); + } - long newId = curId + 1; - boolean acquired = loaderIdSeq.compareAndSet(curId, newId); - if (acquired) return newId; - } while (!Thread.currentThread().isInterrupted()); + private final TypePool createNonCachingTypePool(final ClassFileLocator classFileLocator) { + return new TypePool.Default.WithLazyResolution( + TypePool.CacheProvider.NoOp.INSTANCE, classFileLocator, TypePool.Default.ReaderMode.FAST); + } - return EXHAUSTED_ID; - } + private final TypePool.CacheProvider createCacheProvider( + final int loaderHash, + final WeakReference loaderRef) + { + return new SharedResolutionCacheAdapter(loaderHash, loaderRef, sharedResolutionCache); + } - private final TypePool createNonCachingTypePool(final ClassFileLocator classFileLocator) { - return new TypePool.Default.WithLazyResolution( - TypePool.CacheProvider.NoOp.INSTANCE, classFileLocator, TypePool.Default.ReaderMode.FAST); - } + private final TypePool createCachingTypePool( + final int loaderHash, + final WeakReference loaderRef, + final ClassFileLocator classFileLocator) { + return new TypePool.Default.WithLazyResolution( + createCacheProvider(loaderHash, loaderRef), + classFileLocator, + TypePool.Default.ReaderMode.FAST); + } - private final TypePool.CacheProvider createCacheProvider(final long loaderId) { - return new SharedResolutionCacheAdapter(loaderId, sharedResolutionCache); - } + private final TypePool createCachingTypePool( + final TypePool.CacheProvider cacheProvider, final ClassFileLocator classFileLocator) { + return new TypePool.Default.WithLazyResolution( + cacheProvider, classFileLocator, TypePool.Default.ReaderMode.FAST); + } - private final TypePool createCachingTypePool( - final long loaderId, final ClassFileLocator classFileLocator) { - return new TypePool.Default.WithLazyResolution( - createCacheProvider(loaderId), classFileLocator, TypePool.Default.ReaderMode.FAST); - } - - private final TypePool createCachingTypePool( - final TypePool.CacheProvider cacheProvider, final ClassFileLocator classFileLocator) { - return new TypePool.Default.WithLazyResolution( - cacheProvider, classFileLocator, TypePool.Default.ReaderMode.FAST); - } - - final long approximateSize() { - return sharedResolutionCache.size(); - } + final long approximateSize() { + return sharedResolutionCache.size(); } /** @@ -211,16 +138,22 @@ public class DDCachingPoolStrategy implements PoolStrategy { * name. */ static final class TypeCacheKey { - private final long cacheId; - private final String name; + private final int loaderHash; + private final WeakReference loaderRef; + private final String className; private final int hashCode; - TypeCacheKey(final long cacheId, final String name) { - this.cacheId = cacheId; - this.name = name; + TypeCacheKey( + final int loaderHash, + final WeakReference loaderRef, + final String className) + { + this.loaderHash = loaderHash; + this.loaderRef = loaderRef; + this.className = className; - hashCode = (int) (31 * cacheId) ^ name.hashCode(); + hashCode = (int) (31 * this.loaderHash) ^ className.hashCode(); } @Override @@ -230,10 +163,34 @@ public class DDCachingPoolStrategy implements PoolStrategy { @Override public boolean equals(final Object obj) { - if (!(obj instanceof TypeCacheKey)) return false; + if ( !(obj instanceof TypeCacheKey) ) return false; - TypeCacheKey that = (TypeCacheKey) obj; - return (cacheId == that.cacheId) && name.equals(that.name); + TypeCacheKey that = (TypeCacheKey)obj; + + if ( loaderHash != that.loaderHash ) return false; + + // Fastpath loaderRef equivalence -- works because of WeakReference cache used + // Also covers the bootstrap null loaderRef case + if ( loaderRef == that.loaderRef ) { + // still need to check name + return className.equals(that.className); + } else if ( className.equals(that.className) ) { + // need to perform a deeper loader check -- requires calling Reference.get + // which can strengthened the Reference, so deliberately done last + + // If either reference has gone null, they aren't considered equivalent + // Technically, this is a bit of violation of equals semantics, since + // two equivalent references can be not equivalent. + ClassLoader thisLoader = loaderRef.get(); + if ( thisLoader == null ) return false; + + ClassLoader thatLoader = that.loaderRef.get(); + if ( thatLoader == null ) return false; + + return (thisLoader == thatLoader); + } else { + return false; + } } } @@ -242,22 +199,26 @@ public class DDCachingPoolStrategy implements PoolStrategy { private static final TypePool.Resolution OBJECT_RESOLUTION = new TypePool.Resolution.Simple(TypeDescription.OBJECT); - private final long cacheId; + private final int loaderHash; + private final WeakReference loaderRef; private final Cache sharedResolutionCache; SharedResolutionCacheAdapter( - final long cacheId, final Cache sharedResolutionCache) { - this.cacheId = cacheId; + final int loaderHash, + final WeakReference loaderRef, + final Cache sharedResolutionCache) { + this.loaderHash = loaderHash; + this.loaderRef = loaderRef; this.sharedResolutionCache = sharedResolutionCache; } @Override - public TypePool.Resolution find(final String name) { + public TypePool.Resolution find(final String className) { TypePool.Resolution existingResolution = - sharedResolutionCache.getIfPresent(new TypeCacheKey(cacheId, name)); + sharedResolutionCache.getIfPresent(new TypeCacheKey(loaderHash, loaderRef, className)); if (existingResolution != null) return existingResolution; - if (OBJECT_NAME.equals(name)) { + if (OBJECT_NAME.equals(className)) { return OBJECT_RESOLUTION; } @@ -265,12 +226,12 @@ public class DDCachingPoolStrategy implements PoolStrategy { } @Override - public TypePool.Resolution register(final String name, final TypePool.Resolution resolution) { - if (OBJECT_NAME.equals(name)) { + public TypePool.Resolution register(final String className, final TypePool.Resolution resolution) { + if (OBJECT_NAME.equals(className)) { return resolution; } - sharedResolutionCache.put(new TypeCacheKey(cacheId, name), resolution); + sharedResolutionCache.put(new TypeCacheKey(loaderHash, loaderRef, className), resolution); return resolution; } diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy index 0d7e687850..4ce1bc5ba5 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy @@ -6,49 +6,97 @@ import net.bytebuddy.dynamic.ClassFileLocator import net.bytebuddy.pool.TypePool import spock.lang.Timeout +import java.lang.ref.WeakReference import java.security.SecureClassLoader @Timeout(5) class CacheProviderTest extends DDSpecification { - def "key equivalence"() { - setup: - def key1 = new DDCachingPoolStrategy.TypeCacheKey(1, "foo") - def key2 = new DDCachingPoolStrategy.TypeCacheKey(1, "foo") + def "key bootstrap equivalence"() { + def loader = null + def loaderHash = DDCachingPoolStrategy.BOOTSTRAP_HASH + def loaderRef = null + + def key1 = new DDCachingPoolStrategy.TypeCacheKey(loaderHash, loaderRef, "foo") + def key2 = new DDCachingPoolStrategy.TypeCacheKey(loaderHash, loaderRef, "foo") expect: key1.hashCode() == key2.hashCode() key1.equals(key2) } - def "different loader - same name"() { + def "key same ref equivalence"() { setup: - def key1 = new DDCachingPoolStrategy.TypeCacheKey(1, "foo") - def key2 = new DDCachingPoolStrategy.TypeCacheKey(2, "foo") + def loader = newClassLoader() + def loaderHash = loader.hashCode() + def loaderRef = new WeakReference(loader) + + def key1 = new DDCachingPoolStrategy.TypeCacheKey(loaderHash, loaderRef, "foo") + def key2 = new DDCachingPoolStrategy.TypeCacheKey(loaderHash, loaderRef, "foo") expect: - // not strictly guaranteed, but important for performance - key1.hashCode() != key2.hashCode() - - !key1.equals(key2) + key1.hashCode() == key2.hashCode() + key1.equals(key2) } - def "same loader - different name"() { + def "key different ref equivalence"() { setup: - def key1 = new DDCachingPoolStrategy.TypeCacheKey(1, "foo") - def key2 = new DDCachingPoolStrategy.TypeCacheKey(1, "foobar") + def loader = newClassLoader() + def loaderHash = loader.hashCode() + def loaderRef1 = new WeakReference(loader) + def loaderRef2 = new WeakReference(loader) + + def key1 = new DDCachingPoolStrategy.TypeCacheKey(loaderHash, loaderRef1, "foo") + def key2 = new DDCachingPoolStrategy.TypeCacheKey(loaderHash, loaderRef2, "foo") expect: - // not strictly guaranteed, but important for performance - key1.hashCode() != key2.hashCode() + loaderRef1 != loaderRef2 - !key1.equals(key2) + key1.hashCode() == key2.hashCode() + key1.equals(key2) + } + + def "key mismatch -- same loader - diff name"() { + setup: + def loader = newClassLoader() + def loaderHash = loader.hashCode() + def loaderRef = new WeakReference(loader) + def fooKey = new DDCachingPoolStrategy.TypeCacheKey(loaderHash, loaderRef, "foo") + def barKey = new DDCachingPoolStrategy.TypeCacheKey(loaderHash, loaderRef, "bar") + + expect: + // not strictly guaranteed -- but important for performance + fooKey.hashCode() != barKey.hashCode() + !fooKey.equals(barKey) + } + + def "key mismatch -- same name - diff loader"() { + setup: + def loader1 = newClassLoader() + def loader1Hash = loader1.hashCode() + def loaderRef1 = new WeakReference(loader1) + + def loader2 = newClassLoader() + def loader2Hash = loader2.hashCode() + def loaderRef2 = new WeakReference(loader2) + + def fooKey1 = new DDCachingPoolStrategy.TypeCacheKey(loader1Hash, loaderRef1, "foo") + def fooKey2 = new DDCachingPoolStrategy.TypeCacheKey(loader2Hash, loaderRef2, "foo") + + expect: + // not strictly guaranteed -- but important for performance + fooKey1.hashCode() != fooKey2.hashCode() + !fooKey1.equals(fooKey2) } def "test basic caching"() { setup: - def cacheInstance = new DDCachingPoolStrategy.CacheInstance() + def poolStrat = new DDCachingPoolStrategy() - def cacheProvider = cacheInstance.createCacheProvider(1) + def loader = newClassLoader() + def loaderHash = loader.hashCode() + def loaderRef = new WeakReference(loader) + + def cacheProvider = poolStrat.createCacheProvider(loaderHash, loaderRef) when: cacheProvider.register("foo", new TypePool.Resolution.Simple(TypeDescription.VOID)) @@ -56,15 +104,20 @@ class CacheProviderTest extends DDSpecification { then: // not strictly guaranteed, but fine for this test cacheProvider.find("foo") != null - cacheInstance.approximateSize() == 1 + poolStrat.approximateSize() == 1 } - def "test ID equivalence"() { + def "test loader equivalence"() { setup: - def cacheInstance = new DDCachingPoolStrategy.CacheInstance() + def poolStrat = new DDCachingPoolStrategy() - def cacheProvider1A = cacheInstance.createCacheProvider(1) - def cacheProvider1B = cacheInstance.createCacheProvider(1) + def loader1 = newClassLoader() + def loaderHash1 = loader1.hashCode() + def loaderRef1A = new WeakReference(loader1) + def loaderRef1B = new WeakReference(loader1) + + def cacheProvider1A = poolStrat.createCacheProvider(loaderHash1, loaderRef1A) + def cacheProvider1B = poolStrat.createCacheProvider(loaderHash1, loaderRef1B) when: cacheProvider1A.register("foo", newVoid()) @@ -75,15 +128,23 @@ class CacheProviderTest extends DDSpecification { cacheProvider1B.find("foo") != null cacheProvider1A.find("foo").is(cacheProvider1B.find("foo")) - cacheInstance.approximateSize() == 1 + poolStrat.approximateSize() == 1 } - def "test ID separation"() { + def "test loader separation"() { setup: - def cacheInstance = new DDCachingPoolStrategy.CacheInstance() + def poolStrat = new DDCachingPoolStrategy() - def cacheProvider1 = cacheInstance.createCacheProvider(1) - def cacheProvider2 = cacheInstance.createCacheProvider(2) + def loader1 = newClassLoader() + def loaderHash1 = loader1.hashCode() + def loaderRef1 = new WeakReference(loader1) + + def loader2 = newClassLoader() + def loaderHash2 = loader2.hashCode() + def loaderRef2 = new WeakReference(loader2) + + def cacheProvider1 = poolStrat.createCacheProvider(loaderHash1, loaderRef1) + def cacheProvider2 = poolStrat.createCacheProvider(loaderHash2, loaderRef2) when: cacheProvider1.register("foo", newVoid()) @@ -95,80 +156,24 @@ class CacheProviderTest extends DDSpecification { cacheProvider2.find("foo") != null !cacheProvider1.find("foo").is(cacheProvider2.find("foo")) - cacheInstance.approximateSize() == 2 + poolStrat.approximateSize() == 2 } - def "test loader ID assignment"() { + def "test capacity"() { setup: - def cacheInstance = new DDCachingPoolStrategy.CacheInstance() + def poolStrat = new DDCachingPoolStrategy() + def capacity = DDCachingPoolStrategy.TYPE_CAPACITY - def locator1 = newLocator() def loader1 = newClassLoader() + def loaderHash1 = loader1.hashCode() + def loaderRef1 = new WeakReference(loader1) - def locator2 = newLocator() def loader2 = newClassLoader() + def loaderHash2 = loader2.hashCode() + def loaderRef2 = new WeakReference(loader2) - when: - cacheInstance.typePool(locator1, loader1) - cacheInstance.typePool(locator2, loader2) - - then: - def loaderId1 = cacheInstance.loaderIdCache.getIfPresent(loader1) - def loaderId2 = cacheInstance.loaderIdCache.getIfPresent(loader2) - - // both were assigned an ID -- technically these can fall out of the ID cache - loaderId1 != null - loaderId2 != null - - // both IDs are not the BOOTSTRAP_ID - loaderId1 != DDCachingPoolStrategy.CacheInstance.BOOTSTRAP_ID - loaderId2 != DDCachingPoolStrategy.CacheInstance.BOOTSTRAP_ID - - // class loaders don't share an ID - cacheInstance.loaderIdCache.getIfPresent(loader1) != cacheInstance.loaderIdCache.getIfPresent(loader2) - } - - def "test loader ID exhaustion"() { - setup: - def cacheInstance = new DDCachingPoolStrategy.CacheInstance() - - when: - cacheInstance.loaderIdSeq.set(DDCachingPoolStrategy.CacheInstance.LIMIT_ID - 2) - - then: - cacheInstance.provisionId() != DDCachingPoolStrategy.CacheInstance.EXHAUSTED_ID - - then: - // once exhausted provisioning -- stays exhausted - cacheInstance.provisionId() == DDCachingPoolStrategy.CacheInstance.EXHAUSTED_ID - cacheInstance.exhaustedLoaderIdSeq() - cacheInstance.provisionId() == DDCachingPoolStrategy.CacheInstance.EXHAUSTED_ID - cacheInstance.exhaustedLoaderIdSeq() - cacheInstance.provisionId() == DDCachingPoolStrategy.CacheInstance.EXHAUSTED_ID - cacheInstance.exhaustedLoaderIdSeq() - } - - def "test exhaustion cacheInstance switch"() { - setup: - def cachingStrat = new DDCachingPoolStrategy() - def origCacheInstance = cachingStrat.cacheInstance - - cachingStrat.cacheInstance.loaderIdSeq.set(DDCachingPoolStrategy.CacheInstance.LIMIT_ID) - - when: - cachingStrat.typePool(newLocator(), newClassLoader()) - - then: - cachingStrat.cacheInstance != origCacheInstance - } - - def "test cacheInstance capacity"() { - setup: - def cacheInstance = new DDCachingPoolStrategy.CacheInstance() - def capacity = DDCachingPoolStrategy.CacheInstance.TYPE_CAPACITY - - def cacheProvider1 = cacheInstance.createCacheProvider(1) - def cacheProvider2 = cacheInstance.createCacheProvider(2) + def cacheProvider1 = poolStrat.createCacheProvider(loaderHash1, loaderRef1) + def cacheProvider2 = poolStrat.createCacheProvider(loaderHash2, loaderRef2) def id = 0 @@ -181,7 +186,7 @@ class CacheProviderTest extends DDSpecification { then: // cache will start to proactively free slots & size calc is approximate - cacheInstance.approximateSize() > capacity - 4 + poolStrat.approximateSize() > capacity - 4 when: 10.times { @@ -192,7 +197,7 @@ class CacheProviderTest extends DDSpecification { then: // cache will start to proactively free slots & size calc is approximate - cacheInstance.approximateSize() > capacity - 4 + poolStrat.approximateSize() > capacity - 4 } static newVoid() { From d50f901f3993cbfddb4e8b1abf8cf01880ae6adc Mon Sep 17 00:00:00 2001 From: dougqh Date: Mon, 27 Jan 2020 12:34:39 -0500 Subject: [PATCH 24/37] googleJavaFormat, codeNarcTest, and test reliability --- .../agent/tooling/DDCachingPoolStrategy.java | 56 +++++++++---------- .../agent/tooling/CacheProviderTest.groovy | 7 +-- 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java index 1e47032a7a..7f3d3f7e83 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java @@ -4,9 +4,7 @@ import static net.bytebuddy.agent.builder.AgentBuilder.PoolStrategy; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; - import java.lang.ref.WeakReference; - import lombok.extern.slf4j.Slf4j; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.ClassFileLocator; @@ -54,9 +52,10 @@ public class DDCachingPoolStrategy implements PoolStrategy { /** * Cache of recent ClassLoader WeakReferences; used to... + * *
    - *
  • Reduced number of WeakReferences created
  • - *
  • Allow for quick fast path equivalence check of composite keys
  • + *
  • Reduced number of WeakReferences created + *
  • Allow for quick fast path equivalence check of composite keys *
*/ final Cache> loaderRefCache = @@ -68,8 +67,7 @@ public class DDCachingPoolStrategy implements PoolStrategy { .build(); /** - * Single shared Type.Resolution cache -- uses a composite key -- - * conceptually of loader & name + * Single shared Type.Resolution cache -- uses a composite key -- conceptually of loader & name */ final Cache sharedResolutionCache = CacheBuilder.newBuilder() @@ -79,9 +77,9 @@ public class DDCachingPoolStrategy implements PoolStrategy { .maximumSize(TYPE_CAPACITY) .build(); - /** Fast path for bootstrap */ - final SharedResolutionCacheAdapter bootstrapCacheProvider = - new SharedResolutionCacheAdapter(BOOTSTRAP_HASH, null, sharedResolutionCache); + /** Fast path for bootstrap */ + final SharedResolutionCacheAdapter bootstrapCacheProvider = + new SharedResolutionCacheAdapter(BOOTSTRAP_HASH, null, sharedResolutionCache); @Override public final TypePool typePool( @@ -92,7 +90,7 @@ public class DDCachingPoolStrategy implements PoolStrategy { WeakReference loaderRef = loaderRefCache.getIfPresent(classLoader); - if ( loaderRef == null ) { + if (loaderRef == null) { loaderRef = new WeakReference<>(classLoader); loaderRefCache.put(classLoader, loaderRef); } @@ -107,20 +105,18 @@ public class DDCachingPoolStrategy implements PoolStrategy { } private final TypePool.CacheProvider createCacheProvider( - final int loaderHash, - final WeakReference loaderRef) - { + final int loaderHash, final WeakReference loaderRef) { return new SharedResolutionCacheAdapter(loaderHash, loaderRef, sharedResolutionCache); } private final TypePool createCachingTypePool( - final int loaderHash, - final WeakReference loaderRef, - final ClassFileLocator classFileLocator) { + final int loaderHash, + final WeakReference loaderRef, + final ClassFileLocator classFileLocator) { return new TypePool.Default.WithLazyResolution( - createCacheProvider(loaderHash, loaderRef), - classFileLocator, - TypePool.Default.ReaderMode.FAST); + createCacheProvider(loaderHash, loaderRef), + classFileLocator, + TypePool.Default.ReaderMode.FAST); } private final TypePool createCachingTypePool( @@ -145,10 +141,7 @@ public class DDCachingPoolStrategy implements PoolStrategy { private final int hashCode; TypeCacheKey( - final int loaderHash, - final WeakReference loaderRef, - final String className) - { + final int loaderHash, final WeakReference loaderRef, final String className) { this.loaderHash = loaderHash; this.loaderRef = loaderRef; this.className = className; @@ -163,18 +156,18 @@ public class DDCachingPoolStrategy implements PoolStrategy { @Override public boolean equals(final Object obj) { - if ( !(obj instanceof TypeCacheKey) ) return false; + if (!(obj instanceof TypeCacheKey)) return false; - TypeCacheKey that = (TypeCacheKey)obj; + TypeCacheKey that = (TypeCacheKey) obj; - if ( loaderHash != that.loaderHash ) return false; + if (loaderHash != that.loaderHash) return false; // Fastpath loaderRef equivalence -- works because of WeakReference cache used // Also covers the bootstrap null loaderRef case - if ( loaderRef == that.loaderRef ) { + if (loaderRef == that.loaderRef) { // still need to check name return className.equals(that.className); - } else if ( className.equals(that.className) ) { + } else if (className.equals(that.className)) { // need to perform a deeper loader check -- requires calling Reference.get // which can strengthened the Reference, so deliberately done last @@ -182,10 +175,10 @@ public class DDCachingPoolStrategy implements PoolStrategy { // Technically, this is a bit of violation of equals semantics, since // two equivalent references can be not equivalent. ClassLoader thisLoader = loaderRef.get(); - if ( thisLoader == null ) return false; + if (thisLoader == null) return false; ClassLoader thatLoader = that.loaderRef.get(); - if ( thatLoader == null ) return false; + if (thatLoader == null) return false; return (thisLoader == thatLoader); } else { @@ -226,7 +219,8 @@ public class DDCachingPoolStrategy implements PoolStrategy { } @Override - public TypePool.Resolution register(final String className, final TypePool.Resolution resolution) { + public TypePool.Resolution register( + final String className, final TypePool.Resolution resolution) { if (OBJECT_NAME.equals(className)) { return resolution; } diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy index 4ce1bc5ba5..354069acea 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy @@ -7,12 +7,11 @@ import net.bytebuddy.pool.TypePool import spock.lang.Timeout import java.lang.ref.WeakReference -import java.security.SecureClassLoader @Timeout(5) class CacheProviderTest extends DDSpecification { def "key bootstrap equivalence"() { - def loader = null + // def loader = null def loaderHash = DDCachingPoolStrategy.BOOTSTRAP_HASH def loaderRef = null @@ -197,7 +196,7 @@ class CacheProviderTest extends DDSpecification { then: // cache will start to proactively free slots & size calc is approximate - poolStrat.approximateSize() > capacity - 4 + poolStrat.approximateSize() > 0.9 * capacity } static newVoid() { @@ -205,7 +204,7 @@ class CacheProviderTest extends DDSpecification { } static newClassLoader() { - return new URLClassLoader([] as URL[], (ClassLoader)null); + return new URLClassLoader([] as URL[], (ClassLoader)null) } static newLocator() { From 4c7a0ba7a7ca60918b927ca59a315ec1044eb7f4 Mon Sep 17 00:00:00 2001 From: dougqh Date: Mon, 27 Jan 2020 17:14:17 -0500 Subject: [PATCH 25/37] Fixing muzzle? MuzzlePlugin groovy checks that no threads are spawned because this holds the ClassLoader live. This was breaking with the caching change because the cache no longer uses the Cleaner service. This caused a problem because the Thread behind the cleaner is created lazily when the first task is created, but without the cache the creation was delayed. To solve this, I addressed the original cause of the leak. The newly created Thread automatically inherits the contextClassLoader of its parent, but that's unnecessary for a cleaner thread. So I changed the ThreadFactory for cleaner to explicitly null out the contextClassLoader. We should probably null out contextClassLoader in other thread factories and also reduce our use of contextClassLoaders in general, but that will left to another PR. --- buildSrc/src/main/groovy/MuzzlePlugin.groovy | 5 ++++- .../src/main/java/datadog/trace/agent/tooling/Cleaner.java | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/main/groovy/MuzzlePlugin.groovy b/buildSrc/src/main/groovy/MuzzlePlugin.groovy index 99ad0b90dd..2f852d9fd3 100644 --- a/buildSrc/src/main/groovy/MuzzlePlugin.groovy +++ b/buildSrc/src/main/groovy/MuzzlePlugin.groovy @@ -291,7 +291,10 @@ class MuzzlePlugin implements Plugin { doLast { final ClassLoader instrumentationCL = createInstrumentationClassloader(instrumentationProject, toolingProject) def ccl = Thread.currentThread().contextClassLoader - def bogusLoader = new SecureClassLoader() + def bogusLoader = new SecureClassLoader() { + @Override + String toString() { return "bogus" } + } Thread.currentThread().contextClassLoader = bogusLoader final ClassLoader userCL = createClassLoaderForTask(instrumentationProject, bootstrapProject, taskName) try { diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/Cleaner.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/Cleaner.java index 8115fb0f48..61529aff63 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/Cleaner.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/Cleaner.java @@ -20,6 +20,7 @@ class Cleaner { final Thread thread = new Thread(r, "dd-cleaner"); thread.setDaemon(true); thread.setPriority(Thread.MIN_PRIORITY); + thread.setContextClassLoader(null); return thread; } }; From 176f826a440c9557ec933d7d62c90c1aa416de09 Mon Sep 17 00:00:00 2001 From: dougqh Date: Mon, 27 Jan 2020 17:44:39 -0500 Subject: [PATCH 26/37] Adjusting approximateSize check to be more reliable --- .../groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy index 354069acea..111763d098 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy @@ -185,7 +185,7 @@ class CacheProviderTest extends DDSpecification { then: // cache will start to proactively free slots & size calc is approximate - poolStrat.approximateSize() > capacity - 4 + poolStrat.approximateSize() > 0.9 * capacity when: 10.times { From 1e390984c154b541de4f5bc820a37276d67879ed Mon Sep 17 00:00:00 2001 From: Blinkingor Date: Tue, 28 Jan 2020 10:28:37 +0100 Subject: [PATCH 27/37] Fix potential StackOverFlowError on regexp --- .../TraceConfigInstrumentation.java | 29 +++-- .../TraceConfigInstrumentationTest.groovy | 102 ++++++++++++++++++ 2 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy diff --git a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java index 9ecd3312d7..f3f924dd5d 100644 --- a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java +++ b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java @@ -2,22 +2,22 @@ package datadog.trace.instrumentation.trace_annotation; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static net.bytebuddy.matcher.ElementMatchers.named; - import com.google.auto.service.AutoService; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.Config; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + /** * TraceConfig Instrumentation does not extend Default. * @@ -42,16 +42,29 @@ public class TraceConfigInstrumentation implements Instrumenter { + PACKAGE_CLASS_NAME_REGEX + "\\[" + METHOD_LIST_REGEX - + "\\]\\s*;?\\s*"; + + "\\]"; private final Map> classMethodsToTrace; + private boolean validateConfigString(String configString) { + for (String clazz : configString.split(";")) { + if (!clazz.matches(CONFIG_FORMAT)) { + return false; + } + } + return true; + } + public TraceConfigInstrumentation() { - final String configString = Config.get().getTraceMethods(); + this(Config.get().getTraceMethods()); + } + + public TraceConfigInstrumentation(final String configString) { + if (configString == null || configString.trim().isEmpty()) { classMethodsToTrace = Collections.emptyMap(); - } else if (!configString.matches(CONFIG_FORMAT)) { + } else if (!validateConfigString(configString)) { log.warn( "Invalid trace method config '{}'. Must match 'package.Class$Name[method1,method2];*'.", configString); diff --git a/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy b/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy new file mode 100644 index 0000000000..a983cf954c --- /dev/null +++ b/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy @@ -0,0 +1,102 @@ +import datadog.trace.agent.test.AgentTestRunner +import datadog.trace.agent.test.utils.ConfigUtils +import datadog.trace.instrumentation.trace_annotation.TraceConfigInstrumentation + +class TraceConfigInstrumentationTest extends AgentTestRunner { + + def "test no arg constructor simple"() { + final interestingClass = "java.lang.String[toString]"; + setup: + ConfigUtils.updateConfig { + System.setProperty("dd.trace.methods", interestingClass) + } + def traceConfigInstrumentation; + + when: + traceConfigInstrumentation = new TraceConfigInstrumentation(); + + then: + traceConfigInstrumentation.classMethodsToTrace.size() == 1 + traceConfigInstrumentation.classMethodsToTrace.containsKey("java.lang.String") + traceConfigInstrumentation.classMethodsToTrace.get("java.lang.String").contains("toString") + } + + def "test no arg constructor multi"() { + final interestingClass = "java.lang.String[toString];java.math.BigDecimal[negate, floatValue];"; + setup: + ConfigUtils.updateConfig { + System.setProperty("dd.trace.methods", interestingClass) + } + def traceConfigInstrumentation; + + when: + traceConfigInstrumentation = new TraceConfigInstrumentation(); + + then: + traceConfigInstrumentation.classMethodsToTrace.size() == 2 + traceConfigInstrumentation.classMethodsToTrace.containsKey("java.lang.String") + traceConfigInstrumentation.classMethodsToTrace.containsKey("java.math.BigDecimal") + traceConfigInstrumentation.classMethodsToTrace.get("java.math.BigDecimal").contains("negate") + traceConfigInstrumentation.classMethodsToTrace.get("java.math.BigDecimal").contains("floatValue") + } + + def "test large list valid"() { + final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Server[init,init,generateServerCredentials,calculateSecret,verifyClientEvidenceMessage,calculateServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];org.bouncycastle.crypto.agreement.srp.SRP6VerifierGenerator[init,init,generateVerifier];org.bouncycastle.crypto.commitments.GeneralHashCommitter[commit,isRevealed];org.bouncycastle.crypto.commitments.HashCommitter[commit,isRevealed];org.bouncycastle.crypto.digests.Blake2bDigest[update,update,doFinal,reset,getAlgorithmName,getDigestSize,getByteLength,clearKey,clearSalt];org.bouncycastle.crypto.digests.Blake2sDigest[update,update,doFinal,reset,getAlgorithmName,getDigestSize,getByteLength,clearKey,clearSalt];org.bouncycastle.crypto.digests.DSTU7564Digest[getAlgorithmName,getDigestSize,getByteLength,update,update,doFinal,reset,copy,reset];org.bouncycastle.crypto.digests.GOST3411Digest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength,copy,reset];org.bouncycastle.crypto.digests.GOST3411_2012Digest[getByteLength,update,update,doFinal,reset,reset];org.bouncycastle.crypto.digests.GOST3411_2012_256Digest[getAlgorithmName,getDigestSize,doFinal,copy];org.bouncycastle.crypto.digests.GOST3411_2012_512Digest[getAlgorithmName,getDigestSize,copy];org.bouncycastle.crypto.digests.GeneralDigest[update,update,finish,reset,getByteLength];org.bouncycastle.crypto.digests.KeccakDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.LongDigest[update,update,finish,reset,getByteLength];org.bouncycastle.crypto.digests.MD2Digest[getAlgorithmName,getDigestSize,doFinal,reset,update,update,getByteLength,copy,reset];org.bouncycastle.crypto.digests.MD4Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.MD5Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.NonMemoableDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.NullDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset];org.bouncycastle.crypto.digests.RIPEMD128Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD160Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD256Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD320Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.SHA1Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA224Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA256Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA384Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA3Digest[getAlgorithmName,doFinal];org.bouncycastle.crypto.digests.SHA512Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA512tDigest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHAKEDigest[getAlgorithmName,doFinal,doFinal,doOutput];org.bouncycastle.crypto.digests.SM3Digest[getAlgorithmName,getDigestSize,copy,reset,reset,doFinal,finish];org.bouncycastle.crypto.digests.ShortenedDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.SkeinDigest[reset,copy,getAlgorithmName,getDigestSize,getByteLength,init,reset,update,update,doFinal];org.bouncycastle.crypto.digests.SkeinEngine[copy,reset,getOutputSize,getBlockSize,init,reset,update,update,doFinal];org.bouncycastle.crypto.digests.TigerDigest[getAlgorithmName,getDigestSize,update,update,unpackWord,doFinal,reset,getByteLength,copy,reset];org.bouncycastle.crypto.digests.WhirlpoolDigest[getAlgorithmName,getDigestSize,doFinal,reset,update,update,getByteLength,copy,reset];org.bouncycastle.crypto.ec.CustomNamedCurves[getByName,getByOID,getOID,getName,getNames];org.bouncycastle.crypto.ec.ECElGamalDecryptor[init,decrypt];org.bouncycastle.crypto.ec.ECElGamalEncryptor[init,encrypt];org.bouncycastle.crypto.ec.ECFixedTransform[init,transform,getTransformValue];org.bouncycastle.crypto.ec.ECNewPublicKeyTransform[init,transform];org.bouncycastle.crypto.ec.ECNewRandomnessTransform[init,transform,getTransformValue];org.bouncycastle.crypto.ec.ECPair[getX,getY,equals,equals,hashCode];org.bouncycastle.crypto.encodings.ISO9796d1Encoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,setPadBits,getPadBits,processBlock];org.bouncycastle.crypto.encodings.OAEPEncoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,processBlock,encodeBlock,decodeBlock];org.bouncycastle.crypto.encodings.PKCS1Encoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.AESEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.AESFastEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.AESLightEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.ARIAEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.BlowfishEngine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.CAST5Engine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.CAST6Engine[getAlgorithmName,reset,getBlockSize];org.bouncycastle.crypto.engines.CamelliaEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.CamelliaLightEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.ChaCha7539Engine[getAlgorithmName,salsaCore];org.bouncycastle.crypto.engines.ChaChaEngine[getAlgorithmName,chachaCore,salsaCore];org.bouncycastle.crypto.engines.CramerShoupCiphertext[getU1,setU1,getU2,setU2,getE,setE,getV,setV,toString,toByteArray];org.bouncycastle.crypto.engines.CramerShoupCoreEngine[init,init,getInputBlockSize,getOutputBlockSize,convertInput,convertOutput,encryptBlock,decryptBlock];org.bouncycastle.crypto.engines.CryptoProWrapEngine[init];org.bouncycastle.crypto.engines.DESEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DESedeEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DESedeWrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.DSTU7624Engine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DSTU7624WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.ElGamalEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.GOST28147Engine[init,getAlgorithmName,getBlockSize,processBlock,reset,getSBox,getSBoxName];org.bouncycastle.crypto.engines.GOST28147WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.GOST3412_2015Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.Grain128Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.Grainv1Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.HC128Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.HC256Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.IDEAEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.IESEngine[init,init,init,getCipher,getMac,processBlock];org.bouncycastle.crypto.engines.ISAACEngine[init,returnByte,processBytes,getAlgorithmName,reset];org.bouncycastle.crypto.engines.NaccacheSternEngine[init,setDebug,getInputBlockSize,getOutputBlockSize,processBlock,encrypt,addCryptedBlocks,processData];org.bouncycastle.crypto.engines.NoekeonEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.NullEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.OldIESEngine[init,init,init,getCipher,getMac,processBlock];org.bouncycastle.crypto.engines.RC2Engine[init,reset,getAlgorithmName,getBlockSize,processBlock];org.bouncycastle.crypto.engines.RC2WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RC4Engine[init,getAlgorithmName,returnByte,processBytes,reset];org.bouncycastle.crypto.engines.RC532Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RC564Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RC6Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RFC3211WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RFC3394WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RFC5649WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RSABlindedEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RSABlindingEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RSAEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RijndaelEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.SEEDEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.SM2Engine[init,processBlock];org.bouncycastle.crypto.engines.SM4Engine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.Salsa20Engine[init,getAlgorithmName,returnByte,processBytes,skip,seekTo,getPosition,reset,salsaCore];org.bouncycastle.crypto.engines.SerpentEngineBase[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.Shacal2Engine[reset,getAlgorithmName,getBlockSize,init,setKey,processBlock];org.bouncycastle.crypto.engines.SkipjackEngine[init,getAlgorithmName,getBlockSize,processBlock,reset,encryptBlock,decryptBlock];org.bouncycastle.crypto.engines.TEAEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.ThreefishEngine[init,init,getAlgorithmName,getBlockSize,reset,processBlock,processBlock,bytesToWord,wordToBytes];org.bouncycastle.crypto.engines.TnepresEngine[getAlgorithmName];org.bouncycastle.crypto.engines.TwofishEngine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.VMPCEngine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.VMPCKSA3Engine[getAlgorithmName];org.bouncycastle.crypto.engines.XSalsa20Engine[getAlgorithmName,salsaCore];org.bouncycastle.crypto.engines.XTEAEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.examples.DESExample[main];org.bouncycastle.crypto.examples.JPAKEExample[main];org.bouncycastle.crypto.generators.BCrypt[passwordToByteArray,generate];org.bouncycastle.crypto.generators.BaseKDFBytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.CramerShoupKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.CramerShoupParametersGenerator[init,generateParameters,generateParameters];org.bouncycastle.crypto.generators.DESKeyGenerator[init,generateKey];org.bouncycastle.crypto.generators.DESedeKeyGenerator[init,generateKey];org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DHKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DHParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.DSAKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DSAParametersGenerator[init,init,generateParameters];org.bouncycastle.crypto.generators.DSTU4145KeyPairGenerator[generateKeyPair];org.bouncycastle.crypto.generators.ECKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.ElGamalKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.ElGamalParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator[generate];org.bouncycastle.crypto.generators.GOST3410KeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.GOST3410ParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.HKDFBytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.KDFCounterBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.KDFDoublePipelineIterationBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.KDFFeedbackBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.MGF1BytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.NaccacheSternKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.OpenBSDBCrypt[generate,generate,checkPassword];org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator[init,generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS12ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.Poly1305KeyGenerator[init,generateKey,clamp,checkKey];org.bouncycastle.crypto.generators.RSABlindingFactorGenerator[init,generateBlindingFactor];org.bouncycastle.crypto.generators.RSAKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.SCrypt[generate];org.bouncycastle.crypto.io.CipherInputStream[read,read,read,skip,available,close,mark,reset,markSupported];org.bouncycastle.crypto.io.CipherOutputStream[write,write,write,flush,close];org.bouncycastle.crypto.io.DigestInputStream[read,read,getDigest];org.bouncycastle.crypto.io.DigestOutputStream[write,write,getDigest];org.bouncycastle.crypto.io.MacInputStream[read,read,getMac];org.bouncycastle.crypto.io.MacOutputStream[write,write,getMac];org.bouncycastle.crypto.io.SignerInputStream[read,read,getSigner];org.bouncycastle.crypto.io.SignerOutputStream[write,write,getSigner];org.bouncycastle.crypto.kems.ECIESKeyEncapsulation[init,encrypt,encrypt,decrypt,decrypt];org.bouncycastle.crypto.kems.RSAKeyEncapsulation[init,encrypt,encrypt,decrypt,decrypt];org.bouncycastle.crypto.macs.BlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CBCBlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CFBBlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.DSTU7564Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.DSTU7624Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.GMac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.GOST28147Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.HMac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.ISO9797Alg3Mac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.KGMac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.OldHMac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.Poly1305[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.SipHash[getAlgorithmName,getMacSize,init,update,update,doFinal,doFinal,reset];org.bouncycastle.crypto.macs.SkeinMac[getAlgorithmName,init,getMacSize,reset,update,update,doFinal];org.bouncycastle.crypto.macs.VMPCMac[doFinal,getAlgorithmName,getMacSize,init,reset,update,update];org.bouncycastle.crypto.modes.CBCBlockCipher[getUnderlyingCipher,init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.modes.CCMBlockCipher[getUnderlyingCipher,init,getAlgorithmName,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset,getMac,getUpdateOutputSize,getOutputSize,processPacket,processPacket];org.bouncycastle.crypto.modes.CFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,encryptBlock,decryptBlock,getCurrentIV,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.CTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.EAXBlockCipher[getAlgorithmName,getUnderlyingCipher,getBlockSize,init,reset,processAADByte,processAADBytes,processByte,processBytes,doFinal,getMac,getUpdateOutputSize,getOutputSize];org.bouncycastle.crypto.modes.G3413CBCBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.modes.G3413CFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.G3413CTRBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.G3413OFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.GCFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.GCMBlockCipher[getUnderlyingCipher,getAlgorithmName,init,getMac,getOutputSize,getUpdateOutputSize,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.modes.GOFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.KCCMBlockCipher[init,getAlgorithmName,getUnderlyingCipher,processAADByte,processAADBytes,processByte,processBytes,processPacket,doFinal,getMac,getUpdateOutputSize,getOutputSize,reset];org.bouncycastle.crypto.modes.KCTRBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.KGCMBlockCipher[init,getAlgorithmName,getUnderlyingCipher,processAADByte,processAADBytes,processByte,processBytes,doFinal,getMac,getUpdateOutputSize,getOutputSize,reset];org.bouncycastle.crypto.modes.KXTSBlockCipher[getOutputSize,getUpdateOutputSize,init,processByte,processBytes,doFinal,reset,getUnderlyingCipher,getBlockSize];org.bouncycastle.crypto.modes.NISTCTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.OCBBlockCipher[getUnderlyingCipher,getAlgorithmName,init,getMac,getOutputSize,getUpdateOutputSize,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.modes.OFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.OldCTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher[getUnderlyingCipher,getAlgorithmName,getBlockSize,processBlock,reset,init];org.bouncycastle.crypto.modes.PGPCFBBlockCipher[getUnderlyingCipher,getAlgorithmName,getBlockSize,processBlock,reset,init];org.bouncycastle.crypto.modes.PaddedBlockCipher[getOutputSize,getUpdateOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.SICBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,skip,seekTo,getPosition,getUnderlyingCipher];org.bouncycastle.crypto.modes.gcm.BasicGCMExponentiator[init,exponentiateX];org.bouncycastle.crypto.modes.gcm.BasicGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.GCMUtil[oneAsBytes,oneAsInts,oneAsLongs,asBytes,asBytes,asBytes,asBytes,asInts,asInts,asLongs,asLongs,copy,copy,divideP,multiply,multiply,multiply,multiplyP,multiplyP,multiplyP,multiplyP,multiplyP3,multiplyP4,multiplyP7,multiplyP8,multiplyP8,multiplyP8,multiplyP8,pAsLongs,square,xor,xor,xor,xor,xor,xor,xor,xor,xor,xor];org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator[init,exponentiateX];org.bouncycastle.crypto.modes.gcm.Tables4kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.Tables64kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_128[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_256[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_512[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_128[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_256[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_512[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.Tables16kKGCMMultiplier_512[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.Tables4kKGCMMultiplier_128[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.Tables8kKGCMMultiplier_256[init,multiplyH];org.bouncycastle.crypto.paddings.ISO10126d2Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.ISO7816d4Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.PKCS7Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher[init,getOutputSize,getUpdateOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,getBlockSize,reset];org.bouncycastle.crypto.paddings.TBCPadding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.X923Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.ZeroBytePadding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.params.AEADParameters[getKey,getMacSize,getAssociatedText,getNonce];org.bouncycastle.crypto.params.AsymmetricKeyParameter[isPrivate];org.bouncycastle.crypto.params.CCMParameters[getKey,getMacSize,getAssociatedText,getNonce];org.bouncycastle.crypto.params.CramerShoupKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.CramerShoupKeyParameters[getParameters,equals,hashCode,isPrivate];org.bouncycastle.crypto.params.CramerShoupParameters[equals,hashCode,getG1,getG2,getP,getH];org.bouncycastle.crypto.params.CramerShoupPrivateKeyParameters[getX1,getX2,getY1,getY2,getZ,setPk,getPk,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.CramerShoupPublicKeyParameters[getC,getD,getH,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DESParameters[isWeakKey,setOddParity,getKey];org.bouncycastle.crypto.params.DESedeParameters[isWeakKey,isWeakKey,isRealEDEKey,isReal2Key,isReal3Key,setOddParity,getKey];org.bouncycastle.crypto.params.DHKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.DHKeyParameters[getParameters,equals,hashCode,isPrivate];org.bouncycastle.crypto.params.DHMQVPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHMQVPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHParameters[getP,getG,getQ,getJ,getM,getL,getValidationParameters,equals,hashCode];org.bouncycastle.crypto.params.DHPrivateKeyParameters[getX,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DHPublicKeyParameters[getY,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DHUPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHUPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHValidationParameters[getCounter,getSeed,equals,hashCode];org.bouncycastle.crypto.params.DSAKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.DSAKeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.DSAParameterGenerationParameters[getL,getN,getCertainty,getRandom,getUsageIndex];org.bouncycastle.crypto.params.DSAParameters[getP,getQ,getG,getValidationParameters,equals,hashCode];org.bouncycastle.crypto.params.DSAPrivateKeyParameters[getX,getParameters,isPrivate];org.bouncycastle.crypto.params.DSAPublicKeyParameters[getY,getParameters,isPrivate];org.bouncycastle.crypto.params.DSAValidationParameters[getCounter,getSeed,getUsageIndex,hashCode,equals];org.bouncycastle.crypto.params.ECDHUPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.ECDHUPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.ECDomainParameters[getCurve,getG,getN,getH,getHInv,getSeed,equals,hashCode];org.bouncycastle.crypto.params.ECKeyGenerationParameters[getDomainParameters,getRandom,getStrength];org.bouncycastle.crypto.params.ECKeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.ECNamedDomainParameters[getName,getCurve,getG,getN,getH,getHInv,getSeed,equals,hashCode];org.bouncycastle.crypto.params.ECPrivateKeyParameters[getD,getParameters,isPrivate];org.bouncycastle.crypto.params.ECPublicKeyParameters[getQ,getParameters,isPrivate];org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.ElGamalKeyParameters[getParameters,hashCode,equals,isPrivate];org.bouncycastle.crypto.params.ElGamalParameters[getP,getG,getL,equals,hashCode];org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters[getX,equals,hashCode,getParameters,isPrivate];org.bouncycastle.crypto.params.ElGamalPublicKeyParameters[getY,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410KeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.GOST3410KeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410Parameters[getP,getQ,getA,getValidationParameters,hashCode,equals];org.bouncycastle.crypto.params.GOST3410PrivateKeyParameters[getX,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410PublicKeyParameters[getY,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410ValidationParameters[getC,getX0,getCL,getX0L,equals,hashCode];org.bouncycastle.crypto.params.HKDFParameters[skipExtractParameters,defaultParameters,getIKM,skipExtract,getSalt,getInfo];org.bouncycastle.crypto.params.IESParameters[getDerivationV,getEncodingV,getMacKeySize];org.bouncycastle.crypto.params.IESWithCipherParameters[getCipherKeySize,getDerivationV,getEncodingV,getMacKeySize];org.bouncycastle.crypto.params.ISO18033KDFParameters[getSeed];org.bouncycastle.crypto.params.KDFCounterParameters[getKI,getFixedInputData,getFixedInputDataCounterPrefix,getFixedInputDataCounterSuffix,getR];org.bouncycastle.crypto.params.KDFDoublePipelineIterationParameters[createWithCounter,createWithoutCounter,getKI,useCounter,getR,getFixedInputData];org.bouncycastle.crypto.params.KDFFeedbackParameters[createWithCounter,createWithoutCounter,getKI,getIV,useCounter,getR,getFixedInputData];org.bouncycastle.crypto.params.KDFParameters[getSharedSecret,getIV];org.bouncycastle.crypto.params.KeyParameter[getKey];org.bouncycastle.crypto.params.MGFParameters[getSeed];org.bouncycastle.crypto.params.MQVPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.MQVPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.NaccacheSternKeyGenerationParameters[getCertainty,getCntSmallPrimes,isDebug,getRandom,getStrength];org.bouncycastle.crypto.params.NaccacheSternKeyParameters[getG,getLowerSigmaBound,getModulus,isPrivate];org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters[getPhi_n,getSmallPrimes,getG,getLowerSigmaBound,getModulus,isPrivate];org.bouncycastle.crypto.params.ParametersWithID[getID,getParameters];org.bouncycastle.crypto.params.ParametersWithIV[getIV,getParameters];org.bouncycastle.crypto.params.ParametersWithRandom[getRandom,getParameters];org.bouncycastle.crypto.params.ParametersWithSBox[getSBox,getParameters];org.bouncycastle.crypto.params.ParametersWithSalt[getSalt,getParameters];org.bouncycastle.crypto.params.ParametersWithUKM[getUKM,getParameters];org.bouncycastle.crypto.params.RC2Parameters[getEffectiveKeyBits,getKey];org.bouncycastle.crypto.params.RC5Parameters[getKey,getRounds];org.bouncycastle.crypto.params.RSABlindingParameters[getPublicKey,getBlindingFactor];org.bouncycastle.crypto.params.RSAKeyGenerationParameters[getPublicExponent,getCertainty,getRandom,getStrength];org.bouncycastle.crypto.params.RSAKeyParameters[getModulus,getExponent,isPrivate];org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters[getPublicExponent,getP,getQ,getDP,getDQ,getQInv,getModulus,getExponent,isPrivate];org.bouncycastle.crypto.params.SM2KeyExchangePrivateParameters[isInitiator,getStaticPrivateKey,getStaticPublicPoint,getEphemeralPrivateKey,getEphemeralPublicPoint];org.bouncycastle.crypto.params.SM2KeyExchangePublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.SRP6GroupParameters[getG,getN];org.bouncycastle.crypto.params.SkeinParameters[getParameters,getKey,getPersonalisation,getPublicKey,getKeyIdentifier,getNonce];org.bouncycastle.crypto.params.TweakableBlockCipherParameters[getKey,getTweak];org.bouncycastle.crypto.parsers.DHIESPublicKeyParser[readKey];org.bouncycastle.crypto.parsers.ECIESPublicKeyParser[readKey];org.bouncycastle.crypto.prng.BasicEntropySourceProvider[get];org.bouncycastle.crypto.prng.DigestRandomGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.EntropyUtil[generateSeed];org.bouncycastle.crypto.prng.FixedSecureRandom[nextBytes,generateSeed,nextInt,nextLong,isExhausted];org.bouncycastle.crypto.prng.ReversedWindowGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.SP800SecureRandom[setSeed,setSeed,nextBytes,generateSeed,reseed];org.bouncycastle.crypto.prng.SP800SecureRandomBuilder[setPersonalizationString,setSecurityStrength,setEntropyBitsRequired,buildHash,buildCTR,buildHMAC];org.bouncycastle.crypto.prng.ThreadedSeedGenerator[generateSeed];org.bouncycastle.crypto.prng.VMPCRandomGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.X931SecureRandom[setSeed,setSeed,nextBytes,generateSeed];org.bouncycastle.crypto.prng.X931SecureRandomBuilder[setDateTimeVector,build];org.bouncycastle.crypto.prng.drbg.CTRSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.DualECPoints[getSeedLen,getMaxOutlen,getP,getQ,getSecurityStrength,getCofactor];org.bouncycastle.crypto.prng.drbg.DualECSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.HMacSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.HashSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.signers.DSADigestSigner[init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.DSASigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.DSTU4145Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECDSASigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECGOST3410Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECGOST3410_2012Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECNRSigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.GOST3410Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.GenericSigner[init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.HMacDSAKCalculator[isDeterministic,init,init,nextK];org.bouncycastle.crypto.signers.ISO9796d2PSSSigner[init,updateWithRecoveredMessage,update,update,reset,generateSignature,verifySignature,hasFullMessage,getRecoveredMessage];org.bouncycastle.crypto.signers.ISO9796d2Signer[init,updateWithRecoveredMessage,update,update,reset,generateSignature,verifySignature,hasFullMessage,getRecoveredMessage];org.bouncycastle.crypto.signers.ISOTrailers[getTrailer,noTrailerAvailable];org.bouncycastle.crypto.signers.PSSSigner[init,update,update,reset,generateSignature,verifySignature];org.bouncycastle.crypto.signers.RSADigestSigner[getAlgorithmName,init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.RandomDSAKCalculator[isDeterministic,init,init,nextK];org.bouncycastle.crypto.signers.SM2Signer[init,update,update,verifySignature,reset,generateSignature];org.bouncycastle.crypto.signers.X931Signer[init,update,update,reset,generateSignature,verifySignature];org.bouncycastle.crypto.tls.AbstractTlsCipherFactory[createCipher];org.bouncycastle.crypto.tls.AbstractTlsClient[init,getSessionToResume,getClientHelloRecordLayerVersion,getClientVersion,isFallback,getClientExtensions,getMinimumVersion,notifyServerVersion,getCompressionMethods,notifySessionID,notifySelectedCipherSuite,notifySelectedCompressionMethod,processServerExtensions,processServerSupplementalData,getClientSupplementalData,getCompression,getCipher,notifyNewSessionTicket];org.bouncycastle.crypto.tls.AbstractTlsKeyExchange[init,processServerCertificate,processServerCredentials,requiresServerKeyExchange,generateServerKeyExchange,skipServerKeyExchange,processServerKeyExchange,skipClientCredentials,processClientCertificate,processClientKeyExchange];org.bouncycastle.crypto.tls.AbstractTlsPeer[shouldUseGMTUnixTime,notifySecureRenegotiation,notifyAlertRaised,notifyAlertReceived,notifyHandshakeComplete];org.bouncycastle.crypto.tls.AbstractTlsServer[init,notifyClientVersion,notifyFallback,notifyOfferedCipherSuites,notifyOfferedCompressionMethods,processClientExtensions,getServerVersion,getSelectedCipherSuite,getSelectedCompressionMethod,getServerExtensions,getServerSupplementalData,getCertificateStatus,getCertificateRequest,processClientSupplementalData,notifyClientCertificate,getCompression,getCipher,getNewSessionTicket];org.bouncycastle.crypto.tls.AbstractTlsSigner[init,generateRawSignature,verifyRawSignature,createSigner,createVerifyer];org.bouncycastle.crypto.tls.AbstractTlsSignerCredentials[getSignatureAndHashAlgorithm];org.bouncycastle.crypto.tls.AlertDescription[getName,getText];org.bouncycastle.crypto.tls.AlertLevel[getName,getText];org.bouncycastle.crypto.tls.BasicTlsPSKIdentity[skipIdentityHint,notifyIdentityHint,getPSKIdentity,getPSK];org.bouncycastle.crypto.tls.ByteQueue[nextTwoPow,addData,available,copyTo,read,readFrom,removeData,removeData,removeData,shrink];org.bouncycastle.crypto.tls.ByteQueueInputStream[addBytes,peek,read,read,read,skip,available,close];org.bouncycastle.crypto.tls.ByteQueueOutputStream[getBuffer,write,write];org.bouncycastle.crypto.tls.CertChainType[isValid];org.bouncycastle.crypto.tls.Certificate[getCertificateList,getCertificateAt,getLength,isEmpty,encode,parse];org.bouncycastle.crypto.tls.CertificateRequest[getCertificateTypes,getSupportedSignatureAlgorithms,getCertificateAuthorities,encode,parse];org.bouncycastle.crypto.tls.CertificateStatus[getStatusType,getResponse,getOCSPResponse,encode,parse];org.bouncycastle.crypto.tls.CertificateStatusRequest[getStatusType,getRequest,getOCSPStatusRequest,encode,parse];org.bouncycastle.crypto.tls.CertificateURL[getType,getURLAndHashList,encode,parse];org.bouncycastle.crypto.tls.Chacha20Poly1305[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.CipherSuite[isSCSV];org.bouncycastle.crypto.tls.DTLSClientProtocol[connect];org.bouncycastle.crypto.tls.DTLSServerProtocol[getVerifyRequests,setVerifyRequests,accept];org.bouncycastle.crypto.tls.DTLSTransport[getReceiveLimit,getSendLimit,receive,send,close];org.bouncycastle.crypto.tls.DefaultTlsAgreementCredentials[getCertificate,generateAgreement];org.bouncycastle.crypto.tls.DefaultTlsCipherFactory[createCipher];org.bouncycastle.crypto.tls.DefaultTlsClient[getCipherSuites,getKeyExchange,getMinimumVersion];org.bouncycastle.crypto.tls.DefaultTlsEncryptionCredentials[getCertificate,decryptPreMasterSecret];org.bouncycastle.crypto.tls.DefaultTlsSRPGroupVerifier[accept];org.bouncycastle.crypto.tls.DefaultTlsServer[getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.DefaultTlsSignerCredentials[getCertificate,generateCertificateSignature,getSignatureAndHashAlgorithm];org.bouncycastle.crypto.tls.DigitallySigned[getAlgorithm,getSignature,encode,parse];org.bouncycastle.crypto.tls.ECBasisType[isValid];org.bouncycastle.crypto.tls.FiniteFieldDHEGroup[isValid];org.bouncycastle.crypto.tls.HashAlgorithm[getName,getText,isPrivate];org.bouncycastle.crypto.tls.HeartbeatExtension[getMode,encode,parse];org.bouncycastle.crypto.tls.HeartbeatMessage[encode,parse];org.bouncycastle.crypto.tls.HeartbeatMessageType[isValid];org.bouncycastle.crypto.tls.HeartbeatMode[isValid];org.bouncycastle.crypto.tls.MaxFragmentLength[isValid];org.bouncycastle.crypto.tls.NameType[isValid];org.bouncycastle.crypto.tls.NamedCurve[isValid,refersToASpecificNamedCurve];org.bouncycastle.crypto.tls.NewSessionTicket[getTicketLifetimeHint,getTicket,encode,parse];org.bouncycastle.crypto.tls.OCSPStatusRequest[getResponderIDList,getRequestExtensions,encode,parse];org.bouncycastle.crypto.tls.PSKTlsClient[getCipherSuites,getKeyExchange,getAuthentication,getMinimumVersion];org.bouncycastle.crypto.tls.PSKTlsServer[getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.ProtocolVersion[getFullVersion,getMajorVersion,getMinorVersion,isDTLS,isSSL,isTLS,getEquivalentTLSVersion,isEqualOrEarlierVersionOf,isLaterVersionOf,equals,equals,hashCode,get,toString];org.bouncycastle.crypto.tls.SRPTlsClient[getCipherSuites,getClientExtensions,processServerExtensions,getKeyExchange,getAuthentication,getMinimumVersion];org.bouncycastle.crypto.tls.SRPTlsServer[processClientExtensions,getSelectedCipherSuite,getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.SSL3Mac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.tls.SecurityParameters[getEntity,getCipherSuite,getCompressionAlgorithm,getPrfAlgorithm,getVerifyDataLength,getMasterSecret,getClientRandom,getServerRandom,getSessionHash,getPskIdentity,getPSKIdentity,getSRPIdentity];org.bouncycastle.crypto.tls.ServerDHParams[getPublicKey,encode,parse];org.bouncycastle.crypto.tls.ServerName[getNameType,getName,getHostName,encode,parse];org.bouncycastle.crypto.tls.ServerNameList[getServerNameList,encode,parse];org.bouncycastle.crypto.tls.ServerOnlyTlsAuthentication[getClientCredentials];org.bouncycastle.crypto.tls.ServerSRPParams[getB,getG,getN,getS,encode,parse];org.bouncycastle.crypto.tls.SessionParameters[clear,copy,getCipherSuite,getCompressionAlgorithm,getMasterSecret,getPeerCertificate,getPskIdentity,getPSKIdentity,getSRPIdentity,readServerExtensions];org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm[getHash,getSignature,equals,hashCode,encode,parse];org.bouncycastle.crypto.tls.SimulatedTlsSRPIdentityManager[getRFC5054Default,getLoginParameters];org.bouncycastle.crypto.tls.SupplementalDataEntry[getDataType,getData];org.bouncycastle.crypto.tls.TlsAEADCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsBlockCipher[getWriteMac,getReadMac,getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsClientProtocol[connect,getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsDHEKeyExchange[processServerCredentials,generateServerKeyExchange,processServerKeyExchange];org.bouncycastle.crypto.tls.TlsDHKeyExchange[init,skipServerCredentials,processServerCertificate,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientCertificate,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsDHUtils[addNegotiatedDHEGroupsClientExtension,addNegotiatedDHEGroupsServerExtension,getNegotiatedDHEGroupsClientExtension,getNegotiatedDHEGroupsServerExtension,createNegotiatedDHEGroupsClientExtension,createNegotiatedDHEGroupsServerExtension,readNegotiatedDHEGroupsClientExtension,readNegotiatedDHEGroupsServerExtension,getParametersForDHEGroup,containsDHECipherSuites,isDHECipherSuite,areCompatibleParameters,calculateDHBasicAgreement,generateDHKeyPair,generateEphemeralClientKeyExchange,generateEphemeralServerKeyExchange,validateDHParameters,validateDHPublicKey,readDHParameter,writeDHParameter];org.bouncycastle.crypto.tls.TlsDSASigner[generateRawSignature,verifyRawSignature,createSigner,createVerifyer];org.bouncycastle.crypto.tls.TlsDSSSigner[isValidPublicKey];org.bouncycastle.crypto.tls.TlsECCUtils[addSupportedEllipticCurvesExtension,addSupportedPointFormatsExtension,getSupportedEllipticCurvesExtension,getSupportedPointFormatsExtension,createSupportedEllipticCurvesExtension,createSupportedPointFormatsExtension,readSupportedEllipticCurvesExtension,readSupportedPointFormatsExtension,getNameOfNamedCurve,getParametersForNamedCurve,hasAnySupportedNamedCurves,containsECCCipherSuites,isECCCipherSuite,areOnSameCurve,isSupportedNamedCurve,isCompressionPreferred,serializeECFieldElement,serializeECPoint,serializeECPublicKey,deserializeECFieldElement,deserializeECPoint,deserializeECPublicKey,calculateECDHBasicAgreement,generateECKeyPair,generateEphemeralClientKeyExchange,validateECPublicKey,readECExponent,readECFieldElement,readECParameter,readECParameters,writeECExponent,writeECFieldElement,writeECFieldElement,writeECParameter,writeExplicitECParameters,writeECPoint,writeNamedECParameters];org.bouncycastle.crypto.tls.TlsECDHEKeyExchange[processServerCredentials,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials];org.bouncycastle.crypto.tls.TlsECDHKeyExchange[init,skipServerCredentials,processServerCertificate,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientCertificate,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsECDSASigner[isValidPublicKey];org.bouncycastle.crypto.tls.TlsExtensionsUtils[ensureExtensionsInitialised,addEncryptThenMACExtension,addExtendedMasterSecretExtension,addHeartbeatExtension,addMaxFragmentLengthExtension,addPaddingExtension,addServerNameExtension,addStatusRequestExtension,addTruncatedHMacExtension,getHeartbeatExtension,getMaxFragmentLengthExtension,getPaddingExtension,getServerNameExtension,getStatusRequestExtension,hasEncryptThenMACExtension,hasExtendedMasterSecretExtension,hasTruncatedHMacExtension,createEmptyExtensionData,createEncryptThenMACExtension,createExtendedMasterSecretExtension,createHeartbeatExtension,createMaxFragmentLengthExtension,createPaddingExtension,createServerNameExtension,createStatusRequestExtension,createTruncatedHMacExtension,readEncryptThenMACExtension,readExtendedMasterSecretExtension,readHeartbeatExtension,readMaxFragmentLengthExtension,readPaddingExtension,readServerNameExtension,readStatusRequestExtension,readTruncatedHMacExtension];org.bouncycastle.crypto.tls.TlsFatalAlert[getAlertDescription,getCause];org.bouncycastle.crypto.tls.TlsFatalAlertReceived[getAlertDescription,getCause];org.bouncycastle.crypto.tls.TlsMac[getMACSecret,getSize,calculateMac,calculateMacConstantTime];org.bouncycastle.crypto.tls.TlsNullCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsNullCompression[compress,decompress];org.bouncycastle.crypto.tls.TlsPSKKeyExchange[skipServerCredentials,processServerCredentials,generateServerKeyExchange,processServerCertificate,requiresServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsProtocol[getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsRSAKeyExchange[skipServerCredentials,processServerCredentials,processServerCertificate,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsRSASigner[generateRawSignature,verifyRawSignature,createSigner,createVerifyer,isValidPublicKey];org.bouncycastle.crypto.tls.TlsRSAUtils[generateEncryptedPreMasterSecret,safeDecryptPreMasterSecret];org.bouncycastle.crypto.tls.TlsSRPKeyExchange[init,skipServerCredentials,processServerCertificate,processServerCredentials,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsSRPLoginParameters[getGroup,getSalt,getVerifier];org.bouncycastle.crypto.tls.TlsSRPUtils[addSRPExtension,getSRPExtension,createSRPExtension,readSRPExtension,readSRPParameter,writeSRPParameter,isSRPCipherSuite];org.bouncycastle.crypto.tls.TlsSRTPUtils[addUseSRTPExtension,getUseSRTPExtension,createUseSRTPExtension,readUseSRTPExtension];org.bouncycastle.crypto.tls.TlsServerProtocol[accept,getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsStreamCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsUtils[checkUint8,checkUint8,checkUint8,checkUint16,checkUint16,checkUint24,checkUint24,checkUint32,checkUint48,checkUint64,isValidUint8,isValidUint8,isValidUint8,isValidUint16,isValidUint16,isValidUint24,isValidUint24,isValidUint32,isValidUint48,isValidUint64,isSSL,isTLSv11,isTLSv11,isTLSv12,isTLSv12,writeUint8,writeUint8,writeUint8,writeUint8,writeUint16,writeUint16,writeUint24,writeUint24,writeUint32,writeUint32,writeUint48,writeUint48,writeUint64,writeUint64,writeOpaque8,writeOpaque16,writeOpaque24,writeUint8Array,writeUint8Array,writeUint8ArrayWithUint8Length,writeUint8ArrayWithUint8Length,writeUint16Array,writeUint16Array,writeUint16ArrayWithUint16Length,writeUint16ArrayWithUint16Length,encodeOpaque8,encodeUint8ArrayWithUint8Length,encodeUint16ArrayWithUint16Length,readUint8,readUint8,readUint16,readUint16,readUint24,readUint24,readUint32,readUint32,readUint48,readUint48,readAllOrNothing,readFully,readFully,readOpaque8,readOpaque16,readOpaque24,readUint8Array,readUint16Array,readVersion,readVersion,readVersionRaw,readVersionRaw,readASN1Object,readDERObject,writeGMTUnixTime,writeVersion,writeVersion,getAllSignatureAlgorithms,getDefaultDSSSignatureAlgorithms,getDefaultECDSASignatureAlgorithms,getDefaultRSASignatureAlgorithms,getDefaultSupportedSignatureAlgorithms,getSignatureAndHashAlgorithm,getExtensionData,hasExpectedEmptyExtensionData,importSession,isSignatureAlgorithmsExtensionAllowed,addSignatureAlgorithmsExtension,getSignatureAlgorithmsExtension,createSignatureAlgorithmsExtension,readSignatureAlgorithmsExtension,encodeSupportedSignatureAlgorithms,parseSupportedSignatureAlgorithms,verifySupportedSignatureAlgorithm,PRF,PRF_legacy,createHash,createHash,cloneHash,createPRFHash,clonePRFHash,getHashAlgorithmForPRFAlgorithm,getOIDForHashAlgorithm,hasSigningCapability,createTlsSigner,getCipherType,getEncryptionAlgorithm,getKeyExchangeAlgorithm,getMACAlgorithm,getMinimumVersion,isAEADCipherSuite,isBlockCipherSuite,isStreamCipherSuite,isValidCipherSuiteForSignatureAlgorithms,isValidCipherSuiteForVersion,getUsableSignatureAlgorithms];org.bouncycastle.crypto.tls.UDPTransport[getReceiveLimit,getSendLimit,receive,send,close];org.bouncycastle.crypto.tls.URLAndHash[getURL,getSHA1Hash,encode,parse];org.bouncycastle.crypto.tls.UseSRTPData[getProtectionProfiles,getMki];org.bouncycastle.crypto.util.DERMacData[getMacData];org.bouncycastle.crypto.util.DEROtherInfo[getEncoded];org.bouncycastle.crypto.util.DigestFactory[createMD5,createSHA1,createSHA224,createSHA256,createSHA384,createSHA512,createSHA512_224,createSHA512_256,createSHA3_224,createSHA3_256,createSHA3_384,createSHA3_512];org.bouncycastle.crypto.util.PBKDF2Config[getIterationCount,getPRF,getSaltLength,getAlgorithm];org.bouncycastle.crypto.util.PBKDFConfig[getAlgorithm];org.bouncycastle.crypto.util.Pack[bigEndianToInt,bigEndianToInt,intToBigEndian,intToBigEndian,intToBigEndian,intToBigEndian,bigEndianToLong,bigEndianToLong,longToBigEndian,longToBigEndian,longToBigEndian,longToBigEndian,littleEndianToInt,littleEndianToInt,littleEndianToInt,intToLittleEndian,intToLittleEndian,intToLittleEndian,intToLittleEndian,littleEndianToLong,littleEndianToLong,longToLittleEndian,longToLittleEndian,longToLittleEndian,longToLittleEndian];org.bouncycastle.crypto.util.PrivateKeyFactory[createKey,createKey,createKey];org.bouncycastle.crypto.util.PrivateKeyInfoFactory[createPrivateKeyInfo];org.bouncycastle.crypto.util.PublicKeyFactory[createKey,createKey,createKey,createKey];org.bouncycastle.crypto.util.ScryptConfig[getCostParameter,getBlockSize,getParallelizationParameter,getSaltLength,getAlgorithm];org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory[createSubjectPublicKeyInfo]"; + setup: + def traceConfigInstrumentation; + + when: + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + + then: + traceConfigInstrumentation.classMethodsToTrace.size() == 471 + } + + def "test list invalid method list"() { + final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Server[];org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];"; + setup: + def traceConfigInstrumentation; + + when: + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + + then: + traceConfigInstrumentation.classMethodsToTrace.size() == 0 + } + + def "test list invalid separation"() { + final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey]org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];"; + setup: + def traceConfigInstrumentation; + + when: + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + + then: + traceConfigInstrumentation.classMethodsToTrace.size() == 0 + } + + def "test list invalid class"() { + final interestingClasses = "orgbouncycastlecrypto@3AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];"; + setup: + def traceConfigInstrumentation; + + when: + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + + then: + traceConfigInstrumentation.classMethodsToTrace.size() == 0 + } + + def "test list without trailing semi-colon"() { + final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset]"; + setup: + def traceConfigInstrumentation; + + when: + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + + then: + traceConfigInstrumentation.classMethodsToTrace.size() == 2 + } +} From cf876b5e679ae54c10c3e70eaa3a378033eb904c Mon Sep 17 00:00:00 2001 From: Blinkingor Date: Tue, 28 Jan 2020 15:21:50 +0100 Subject: [PATCH 28/37] Fix import order --- .../trace_annotation/TraceConfigInstrumentation.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java index f3f924dd5d..549466cf9d 100644 --- a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java +++ b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java @@ -2,22 +2,22 @@ package datadog.trace.instrumentation.trace_annotation; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static net.bytebuddy.matcher.ElementMatchers.named; + import com.google.auto.service.AutoService; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.Config; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - /** * TraceConfig Instrumentation does not extend Default. * From 10b963d27707b862e6dad79f599aefed05e90d5c Mon Sep 17 00:00:00 2001 From: Blinkingor Date: Tue, 28 Jan 2020 15:35:39 +0100 Subject: [PATCH 29/37] Codenarc fixes --- .../TraceConfigInstrumentationTest.groovy | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy b/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy index a983cf954c..96f0326a24 100644 --- a/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy @@ -5,15 +5,15 @@ import datadog.trace.instrumentation.trace_annotation.TraceConfigInstrumentation class TraceConfigInstrumentationTest extends AgentTestRunner { def "test no arg constructor simple"() { - final interestingClass = "java.lang.String[toString]"; + final interestingClass = "java.lang.String[toString]" setup: ConfigUtils.updateConfig { System.setProperty("dd.trace.methods", interestingClass) } - def traceConfigInstrumentation; + def traceConfigInstrumentation when: - traceConfigInstrumentation = new TraceConfigInstrumentation(); + traceConfigInstrumentation = new TraceConfigInstrumentation() then: traceConfigInstrumentation.classMethodsToTrace.size() == 1 @@ -22,15 +22,15 @@ class TraceConfigInstrumentationTest extends AgentTestRunner { } def "test no arg constructor multi"() { - final interestingClass = "java.lang.String[toString];java.math.BigDecimal[negate, floatValue];"; + final interestingClass = "java.lang.String[toString];java.math.BigDecimal[negate, floatValue];" setup: ConfigUtils.updateConfig { System.setProperty("dd.trace.methods", interestingClass) } - def traceConfigInstrumentation; + def traceConfigInstrumentation when: - traceConfigInstrumentation = new TraceConfigInstrumentation(); + traceConfigInstrumentation = new TraceConfigInstrumentation() then: traceConfigInstrumentation.classMethodsToTrace.size() == 2 @@ -41,60 +41,60 @@ class TraceConfigInstrumentationTest extends AgentTestRunner { } def "test large list valid"() { - final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Server[init,init,generateServerCredentials,calculateSecret,verifyClientEvidenceMessage,calculateServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];org.bouncycastle.crypto.agreement.srp.SRP6VerifierGenerator[init,init,generateVerifier];org.bouncycastle.crypto.commitments.GeneralHashCommitter[commit,isRevealed];org.bouncycastle.crypto.commitments.HashCommitter[commit,isRevealed];org.bouncycastle.crypto.digests.Blake2bDigest[update,update,doFinal,reset,getAlgorithmName,getDigestSize,getByteLength,clearKey,clearSalt];org.bouncycastle.crypto.digests.Blake2sDigest[update,update,doFinal,reset,getAlgorithmName,getDigestSize,getByteLength,clearKey,clearSalt];org.bouncycastle.crypto.digests.DSTU7564Digest[getAlgorithmName,getDigestSize,getByteLength,update,update,doFinal,reset,copy,reset];org.bouncycastle.crypto.digests.GOST3411Digest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength,copy,reset];org.bouncycastle.crypto.digests.GOST3411_2012Digest[getByteLength,update,update,doFinal,reset,reset];org.bouncycastle.crypto.digests.GOST3411_2012_256Digest[getAlgorithmName,getDigestSize,doFinal,copy];org.bouncycastle.crypto.digests.GOST3411_2012_512Digest[getAlgorithmName,getDigestSize,copy];org.bouncycastle.crypto.digests.GeneralDigest[update,update,finish,reset,getByteLength];org.bouncycastle.crypto.digests.KeccakDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.LongDigest[update,update,finish,reset,getByteLength];org.bouncycastle.crypto.digests.MD2Digest[getAlgorithmName,getDigestSize,doFinal,reset,update,update,getByteLength,copy,reset];org.bouncycastle.crypto.digests.MD4Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.MD5Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.NonMemoableDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.NullDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset];org.bouncycastle.crypto.digests.RIPEMD128Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD160Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD256Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD320Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.SHA1Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA224Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA256Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA384Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA3Digest[getAlgorithmName,doFinal];org.bouncycastle.crypto.digests.SHA512Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA512tDigest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHAKEDigest[getAlgorithmName,doFinal,doFinal,doOutput];org.bouncycastle.crypto.digests.SM3Digest[getAlgorithmName,getDigestSize,copy,reset,reset,doFinal,finish];org.bouncycastle.crypto.digests.ShortenedDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.SkeinDigest[reset,copy,getAlgorithmName,getDigestSize,getByteLength,init,reset,update,update,doFinal];org.bouncycastle.crypto.digests.SkeinEngine[copy,reset,getOutputSize,getBlockSize,init,reset,update,update,doFinal];org.bouncycastle.crypto.digests.TigerDigest[getAlgorithmName,getDigestSize,update,update,unpackWord,doFinal,reset,getByteLength,copy,reset];org.bouncycastle.crypto.digests.WhirlpoolDigest[getAlgorithmName,getDigestSize,doFinal,reset,update,update,getByteLength,copy,reset];org.bouncycastle.crypto.ec.CustomNamedCurves[getByName,getByOID,getOID,getName,getNames];org.bouncycastle.crypto.ec.ECElGamalDecryptor[init,decrypt];org.bouncycastle.crypto.ec.ECElGamalEncryptor[init,encrypt];org.bouncycastle.crypto.ec.ECFixedTransform[init,transform,getTransformValue];org.bouncycastle.crypto.ec.ECNewPublicKeyTransform[init,transform];org.bouncycastle.crypto.ec.ECNewRandomnessTransform[init,transform,getTransformValue];org.bouncycastle.crypto.ec.ECPair[getX,getY,equals,equals,hashCode];org.bouncycastle.crypto.encodings.ISO9796d1Encoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,setPadBits,getPadBits,processBlock];org.bouncycastle.crypto.encodings.OAEPEncoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,processBlock,encodeBlock,decodeBlock];org.bouncycastle.crypto.encodings.PKCS1Encoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.AESEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.AESFastEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.AESLightEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.ARIAEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.BlowfishEngine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.CAST5Engine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.CAST6Engine[getAlgorithmName,reset,getBlockSize];org.bouncycastle.crypto.engines.CamelliaEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.CamelliaLightEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.ChaCha7539Engine[getAlgorithmName,salsaCore];org.bouncycastle.crypto.engines.ChaChaEngine[getAlgorithmName,chachaCore,salsaCore];org.bouncycastle.crypto.engines.CramerShoupCiphertext[getU1,setU1,getU2,setU2,getE,setE,getV,setV,toString,toByteArray];org.bouncycastle.crypto.engines.CramerShoupCoreEngine[init,init,getInputBlockSize,getOutputBlockSize,convertInput,convertOutput,encryptBlock,decryptBlock];org.bouncycastle.crypto.engines.CryptoProWrapEngine[init];org.bouncycastle.crypto.engines.DESEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DESedeEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DESedeWrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.DSTU7624Engine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DSTU7624WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.ElGamalEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.GOST28147Engine[init,getAlgorithmName,getBlockSize,processBlock,reset,getSBox,getSBoxName];org.bouncycastle.crypto.engines.GOST28147WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.GOST3412_2015Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.Grain128Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.Grainv1Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.HC128Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.HC256Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.IDEAEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.IESEngine[init,init,init,getCipher,getMac,processBlock];org.bouncycastle.crypto.engines.ISAACEngine[init,returnByte,processBytes,getAlgorithmName,reset];org.bouncycastle.crypto.engines.NaccacheSternEngine[init,setDebug,getInputBlockSize,getOutputBlockSize,processBlock,encrypt,addCryptedBlocks,processData];org.bouncycastle.crypto.engines.NoekeonEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.NullEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.OldIESEngine[init,init,init,getCipher,getMac,processBlock];org.bouncycastle.crypto.engines.RC2Engine[init,reset,getAlgorithmName,getBlockSize,processBlock];org.bouncycastle.crypto.engines.RC2WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RC4Engine[init,getAlgorithmName,returnByte,processBytes,reset];org.bouncycastle.crypto.engines.RC532Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RC564Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RC6Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RFC3211WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RFC3394WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RFC5649WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RSABlindedEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RSABlindingEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RSAEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RijndaelEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.SEEDEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.SM2Engine[init,processBlock];org.bouncycastle.crypto.engines.SM4Engine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.Salsa20Engine[init,getAlgorithmName,returnByte,processBytes,skip,seekTo,getPosition,reset,salsaCore];org.bouncycastle.crypto.engines.SerpentEngineBase[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.Shacal2Engine[reset,getAlgorithmName,getBlockSize,init,setKey,processBlock];org.bouncycastle.crypto.engines.SkipjackEngine[init,getAlgorithmName,getBlockSize,processBlock,reset,encryptBlock,decryptBlock];org.bouncycastle.crypto.engines.TEAEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.ThreefishEngine[init,init,getAlgorithmName,getBlockSize,reset,processBlock,processBlock,bytesToWord,wordToBytes];org.bouncycastle.crypto.engines.TnepresEngine[getAlgorithmName];org.bouncycastle.crypto.engines.TwofishEngine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.VMPCEngine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.VMPCKSA3Engine[getAlgorithmName];org.bouncycastle.crypto.engines.XSalsa20Engine[getAlgorithmName,salsaCore];org.bouncycastle.crypto.engines.XTEAEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.examples.DESExample[main];org.bouncycastle.crypto.examples.JPAKEExample[main];org.bouncycastle.crypto.generators.BCrypt[passwordToByteArray,generate];org.bouncycastle.crypto.generators.BaseKDFBytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.CramerShoupKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.CramerShoupParametersGenerator[init,generateParameters,generateParameters];org.bouncycastle.crypto.generators.DESKeyGenerator[init,generateKey];org.bouncycastle.crypto.generators.DESedeKeyGenerator[init,generateKey];org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DHKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DHParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.DSAKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DSAParametersGenerator[init,init,generateParameters];org.bouncycastle.crypto.generators.DSTU4145KeyPairGenerator[generateKeyPair];org.bouncycastle.crypto.generators.ECKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.ElGamalKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.ElGamalParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator[generate];org.bouncycastle.crypto.generators.GOST3410KeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.GOST3410ParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.HKDFBytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.KDFCounterBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.KDFDoublePipelineIterationBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.KDFFeedbackBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.MGF1BytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.NaccacheSternKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.OpenBSDBCrypt[generate,generate,checkPassword];org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator[init,generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS12ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.Poly1305KeyGenerator[init,generateKey,clamp,checkKey];org.bouncycastle.crypto.generators.RSABlindingFactorGenerator[init,generateBlindingFactor];org.bouncycastle.crypto.generators.RSAKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.SCrypt[generate];org.bouncycastle.crypto.io.CipherInputStream[read,read,read,skip,available,close,mark,reset,markSupported];org.bouncycastle.crypto.io.CipherOutputStream[write,write,write,flush,close];org.bouncycastle.crypto.io.DigestInputStream[read,read,getDigest];org.bouncycastle.crypto.io.DigestOutputStream[write,write,getDigest];org.bouncycastle.crypto.io.MacInputStream[read,read,getMac];org.bouncycastle.crypto.io.MacOutputStream[write,write,getMac];org.bouncycastle.crypto.io.SignerInputStream[read,read,getSigner];org.bouncycastle.crypto.io.SignerOutputStream[write,write,getSigner];org.bouncycastle.crypto.kems.ECIESKeyEncapsulation[init,encrypt,encrypt,decrypt,decrypt];org.bouncycastle.crypto.kems.RSAKeyEncapsulation[init,encrypt,encrypt,decrypt,decrypt];org.bouncycastle.crypto.macs.BlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CBCBlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CFBBlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.DSTU7564Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.DSTU7624Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.GMac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.GOST28147Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.HMac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.ISO9797Alg3Mac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.KGMac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.OldHMac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.Poly1305[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.SipHash[getAlgorithmName,getMacSize,init,update,update,doFinal,doFinal,reset];org.bouncycastle.crypto.macs.SkeinMac[getAlgorithmName,init,getMacSize,reset,update,update,doFinal];org.bouncycastle.crypto.macs.VMPCMac[doFinal,getAlgorithmName,getMacSize,init,reset,update,update];org.bouncycastle.crypto.modes.CBCBlockCipher[getUnderlyingCipher,init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.modes.CCMBlockCipher[getUnderlyingCipher,init,getAlgorithmName,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset,getMac,getUpdateOutputSize,getOutputSize,processPacket,processPacket];org.bouncycastle.crypto.modes.CFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,encryptBlock,decryptBlock,getCurrentIV,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.CTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.EAXBlockCipher[getAlgorithmName,getUnderlyingCipher,getBlockSize,init,reset,processAADByte,processAADBytes,processByte,processBytes,doFinal,getMac,getUpdateOutputSize,getOutputSize];org.bouncycastle.crypto.modes.G3413CBCBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.modes.G3413CFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.G3413CTRBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.G3413OFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.GCFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.GCMBlockCipher[getUnderlyingCipher,getAlgorithmName,init,getMac,getOutputSize,getUpdateOutputSize,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.modes.GOFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.KCCMBlockCipher[init,getAlgorithmName,getUnderlyingCipher,processAADByte,processAADBytes,processByte,processBytes,processPacket,doFinal,getMac,getUpdateOutputSize,getOutputSize,reset];org.bouncycastle.crypto.modes.KCTRBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.KGCMBlockCipher[init,getAlgorithmName,getUnderlyingCipher,processAADByte,processAADBytes,processByte,processBytes,doFinal,getMac,getUpdateOutputSize,getOutputSize,reset];org.bouncycastle.crypto.modes.KXTSBlockCipher[getOutputSize,getUpdateOutputSize,init,processByte,processBytes,doFinal,reset,getUnderlyingCipher,getBlockSize];org.bouncycastle.crypto.modes.NISTCTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.OCBBlockCipher[getUnderlyingCipher,getAlgorithmName,init,getMac,getOutputSize,getUpdateOutputSize,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.modes.OFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.OldCTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher[getUnderlyingCipher,getAlgorithmName,getBlockSize,processBlock,reset,init];org.bouncycastle.crypto.modes.PGPCFBBlockCipher[getUnderlyingCipher,getAlgorithmName,getBlockSize,processBlock,reset,init];org.bouncycastle.crypto.modes.PaddedBlockCipher[getOutputSize,getUpdateOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.SICBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,skip,seekTo,getPosition,getUnderlyingCipher];org.bouncycastle.crypto.modes.gcm.BasicGCMExponentiator[init,exponentiateX];org.bouncycastle.crypto.modes.gcm.BasicGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.GCMUtil[oneAsBytes,oneAsInts,oneAsLongs,asBytes,asBytes,asBytes,asBytes,asInts,asInts,asLongs,asLongs,copy,copy,divideP,multiply,multiply,multiply,multiplyP,multiplyP,multiplyP,multiplyP,multiplyP3,multiplyP4,multiplyP7,multiplyP8,multiplyP8,multiplyP8,multiplyP8,pAsLongs,square,xor,xor,xor,xor,xor,xor,xor,xor,xor,xor];org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator[init,exponentiateX];org.bouncycastle.crypto.modes.gcm.Tables4kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.Tables64kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_128[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_256[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_512[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_128[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_256[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_512[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.Tables16kKGCMMultiplier_512[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.Tables4kKGCMMultiplier_128[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.Tables8kKGCMMultiplier_256[init,multiplyH];org.bouncycastle.crypto.paddings.ISO10126d2Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.ISO7816d4Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.PKCS7Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher[init,getOutputSize,getUpdateOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,getBlockSize,reset];org.bouncycastle.crypto.paddings.TBCPadding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.X923Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.ZeroBytePadding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.params.AEADParameters[getKey,getMacSize,getAssociatedText,getNonce];org.bouncycastle.crypto.params.AsymmetricKeyParameter[isPrivate];org.bouncycastle.crypto.params.CCMParameters[getKey,getMacSize,getAssociatedText,getNonce];org.bouncycastle.crypto.params.CramerShoupKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.CramerShoupKeyParameters[getParameters,equals,hashCode,isPrivate];org.bouncycastle.crypto.params.CramerShoupParameters[equals,hashCode,getG1,getG2,getP,getH];org.bouncycastle.crypto.params.CramerShoupPrivateKeyParameters[getX1,getX2,getY1,getY2,getZ,setPk,getPk,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.CramerShoupPublicKeyParameters[getC,getD,getH,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DESParameters[isWeakKey,setOddParity,getKey];org.bouncycastle.crypto.params.DESedeParameters[isWeakKey,isWeakKey,isRealEDEKey,isReal2Key,isReal3Key,setOddParity,getKey];org.bouncycastle.crypto.params.DHKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.DHKeyParameters[getParameters,equals,hashCode,isPrivate];org.bouncycastle.crypto.params.DHMQVPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHMQVPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHParameters[getP,getG,getQ,getJ,getM,getL,getValidationParameters,equals,hashCode];org.bouncycastle.crypto.params.DHPrivateKeyParameters[getX,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DHPublicKeyParameters[getY,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DHUPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHUPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHValidationParameters[getCounter,getSeed,equals,hashCode];org.bouncycastle.crypto.params.DSAKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.DSAKeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.DSAParameterGenerationParameters[getL,getN,getCertainty,getRandom,getUsageIndex];org.bouncycastle.crypto.params.DSAParameters[getP,getQ,getG,getValidationParameters,equals,hashCode];org.bouncycastle.crypto.params.DSAPrivateKeyParameters[getX,getParameters,isPrivate];org.bouncycastle.crypto.params.DSAPublicKeyParameters[getY,getParameters,isPrivate];org.bouncycastle.crypto.params.DSAValidationParameters[getCounter,getSeed,getUsageIndex,hashCode,equals];org.bouncycastle.crypto.params.ECDHUPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.ECDHUPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.ECDomainParameters[getCurve,getG,getN,getH,getHInv,getSeed,equals,hashCode];org.bouncycastle.crypto.params.ECKeyGenerationParameters[getDomainParameters,getRandom,getStrength];org.bouncycastle.crypto.params.ECKeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.ECNamedDomainParameters[getName,getCurve,getG,getN,getH,getHInv,getSeed,equals,hashCode];org.bouncycastle.crypto.params.ECPrivateKeyParameters[getD,getParameters,isPrivate];org.bouncycastle.crypto.params.ECPublicKeyParameters[getQ,getParameters,isPrivate];org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.ElGamalKeyParameters[getParameters,hashCode,equals,isPrivate];org.bouncycastle.crypto.params.ElGamalParameters[getP,getG,getL,equals,hashCode];org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters[getX,equals,hashCode,getParameters,isPrivate];org.bouncycastle.crypto.params.ElGamalPublicKeyParameters[getY,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410KeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.GOST3410KeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410Parameters[getP,getQ,getA,getValidationParameters,hashCode,equals];org.bouncycastle.crypto.params.GOST3410PrivateKeyParameters[getX,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410PublicKeyParameters[getY,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410ValidationParameters[getC,getX0,getCL,getX0L,equals,hashCode];org.bouncycastle.crypto.params.HKDFParameters[skipExtractParameters,defaultParameters,getIKM,skipExtract,getSalt,getInfo];org.bouncycastle.crypto.params.IESParameters[getDerivationV,getEncodingV,getMacKeySize];org.bouncycastle.crypto.params.IESWithCipherParameters[getCipherKeySize,getDerivationV,getEncodingV,getMacKeySize];org.bouncycastle.crypto.params.ISO18033KDFParameters[getSeed];org.bouncycastle.crypto.params.KDFCounterParameters[getKI,getFixedInputData,getFixedInputDataCounterPrefix,getFixedInputDataCounterSuffix,getR];org.bouncycastle.crypto.params.KDFDoublePipelineIterationParameters[createWithCounter,createWithoutCounter,getKI,useCounter,getR,getFixedInputData];org.bouncycastle.crypto.params.KDFFeedbackParameters[createWithCounter,createWithoutCounter,getKI,getIV,useCounter,getR,getFixedInputData];org.bouncycastle.crypto.params.KDFParameters[getSharedSecret,getIV];org.bouncycastle.crypto.params.KeyParameter[getKey];org.bouncycastle.crypto.params.MGFParameters[getSeed];org.bouncycastle.crypto.params.MQVPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.MQVPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.NaccacheSternKeyGenerationParameters[getCertainty,getCntSmallPrimes,isDebug,getRandom,getStrength];org.bouncycastle.crypto.params.NaccacheSternKeyParameters[getG,getLowerSigmaBound,getModulus,isPrivate];org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters[getPhi_n,getSmallPrimes,getG,getLowerSigmaBound,getModulus,isPrivate];org.bouncycastle.crypto.params.ParametersWithID[getID,getParameters];org.bouncycastle.crypto.params.ParametersWithIV[getIV,getParameters];org.bouncycastle.crypto.params.ParametersWithRandom[getRandom,getParameters];org.bouncycastle.crypto.params.ParametersWithSBox[getSBox,getParameters];org.bouncycastle.crypto.params.ParametersWithSalt[getSalt,getParameters];org.bouncycastle.crypto.params.ParametersWithUKM[getUKM,getParameters];org.bouncycastle.crypto.params.RC2Parameters[getEffectiveKeyBits,getKey];org.bouncycastle.crypto.params.RC5Parameters[getKey,getRounds];org.bouncycastle.crypto.params.RSABlindingParameters[getPublicKey,getBlindingFactor];org.bouncycastle.crypto.params.RSAKeyGenerationParameters[getPublicExponent,getCertainty,getRandom,getStrength];org.bouncycastle.crypto.params.RSAKeyParameters[getModulus,getExponent,isPrivate];org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters[getPublicExponent,getP,getQ,getDP,getDQ,getQInv,getModulus,getExponent,isPrivate];org.bouncycastle.crypto.params.SM2KeyExchangePrivateParameters[isInitiator,getStaticPrivateKey,getStaticPublicPoint,getEphemeralPrivateKey,getEphemeralPublicPoint];org.bouncycastle.crypto.params.SM2KeyExchangePublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.SRP6GroupParameters[getG,getN];org.bouncycastle.crypto.params.SkeinParameters[getParameters,getKey,getPersonalisation,getPublicKey,getKeyIdentifier,getNonce];org.bouncycastle.crypto.params.TweakableBlockCipherParameters[getKey,getTweak];org.bouncycastle.crypto.parsers.DHIESPublicKeyParser[readKey];org.bouncycastle.crypto.parsers.ECIESPublicKeyParser[readKey];org.bouncycastle.crypto.prng.BasicEntropySourceProvider[get];org.bouncycastle.crypto.prng.DigestRandomGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.EntropyUtil[generateSeed];org.bouncycastle.crypto.prng.FixedSecureRandom[nextBytes,generateSeed,nextInt,nextLong,isExhausted];org.bouncycastle.crypto.prng.ReversedWindowGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.SP800SecureRandom[setSeed,setSeed,nextBytes,generateSeed,reseed];org.bouncycastle.crypto.prng.SP800SecureRandomBuilder[setPersonalizationString,setSecurityStrength,setEntropyBitsRequired,buildHash,buildCTR,buildHMAC];org.bouncycastle.crypto.prng.ThreadedSeedGenerator[generateSeed];org.bouncycastle.crypto.prng.VMPCRandomGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.X931SecureRandom[setSeed,setSeed,nextBytes,generateSeed];org.bouncycastle.crypto.prng.X931SecureRandomBuilder[setDateTimeVector,build];org.bouncycastle.crypto.prng.drbg.CTRSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.DualECPoints[getSeedLen,getMaxOutlen,getP,getQ,getSecurityStrength,getCofactor];org.bouncycastle.crypto.prng.drbg.DualECSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.HMacSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.HashSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.signers.DSADigestSigner[init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.DSASigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.DSTU4145Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECDSASigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECGOST3410Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECGOST3410_2012Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECNRSigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.GOST3410Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.GenericSigner[init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.HMacDSAKCalculator[isDeterministic,init,init,nextK];org.bouncycastle.crypto.signers.ISO9796d2PSSSigner[init,updateWithRecoveredMessage,update,update,reset,generateSignature,verifySignature,hasFullMessage,getRecoveredMessage];org.bouncycastle.crypto.signers.ISO9796d2Signer[init,updateWithRecoveredMessage,update,update,reset,generateSignature,verifySignature,hasFullMessage,getRecoveredMessage];org.bouncycastle.crypto.signers.ISOTrailers[getTrailer,noTrailerAvailable];org.bouncycastle.crypto.signers.PSSSigner[init,update,update,reset,generateSignature,verifySignature];org.bouncycastle.crypto.signers.RSADigestSigner[getAlgorithmName,init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.RandomDSAKCalculator[isDeterministic,init,init,nextK];org.bouncycastle.crypto.signers.SM2Signer[init,update,update,verifySignature,reset,generateSignature];org.bouncycastle.crypto.signers.X931Signer[init,update,update,reset,generateSignature,verifySignature];org.bouncycastle.crypto.tls.AbstractTlsCipherFactory[createCipher];org.bouncycastle.crypto.tls.AbstractTlsClient[init,getSessionToResume,getClientHelloRecordLayerVersion,getClientVersion,isFallback,getClientExtensions,getMinimumVersion,notifyServerVersion,getCompressionMethods,notifySessionID,notifySelectedCipherSuite,notifySelectedCompressionMethod,processServerExtensions,processServerSupplementalData,getClientSupplementalData,getCompression,getCipher,notifyNewSessionTicket];org.bouncycastle.crypto.tls.AbstractTlsKeyExchange[init,processServerCertificate,processServerCredentials,requiresServerKeyExchange,generateServerKeyExchange,skipServerKeyExchange,processServerKeyExchange,skipClientCredentials,processClientCertificate,processClientKeyExchange];org.bouncycastle.crypto.tls.AbstractTlsPeer[shouldUseGMTUnixTime,notifySecureRenegotiation,notifyAlertRaised,notifyAlertReceived,notifyHandshakeComplete];org.bouncycastle.crypto.tls.AbstractTlsServer[init,notifyClientVersion,notifyFallback,notifyOfferedCipherSuites,notifyOfferedCompressionMethods,processClientExtensions,getServerVersion,getSelectedCipherSuite,getSelectedCompressionMethod,getServerExtensions,getServerSupplementalData,getCertificateStatus,getCertificateRequest,processClientSupplementalData,notifyClientCertificate,getCompression,getCipher,getNewSessionTicket];org.bouncycastle.crypto.tls.AbstractTlsSigner[init,generateRawSignature,verifyRawSignature,createSigner,createVerifyer];org.bouncycastle.crypto.tls.AbstractTlsSignerCredentials[getSignatureAndHashAlgorithm];org.bouncycastle.crypto.tls.AlertDescription[getName,getText];org.bouncycastle.crypto.tls.AlertLevel[getName,getText];org.bouncycastle.crypto.tls.BasicTlsPSKIdentity[skipIdentityHint,notifyIdentityHint,getPSKIdentity,getPSK];org.bouncycastle.crypto.tls.ByteQueue[nextTwoPow,addData,available,copyTo,read,readFrom,removeData,removeData,removeData,shrink];org.bouncycastle.crypto.tls.ByteQueueInputStream[addBytes,peek,read,read,read,skip,available,close];org.bouncycastle.crypto.tls.ByteQueueOutputStream[getBuffer,write,write];org.bouncycastle.crypto.tls.CertChainType[isValid];org.bouncycastle.crypto.tls.Certificate[getCertificateList,getCertificateAt,getLength,isEmpty,encode,parse];org.bouncycastle.crypto.tls.CertificateRequest[getCertificateTypes,getSupportedSignatureAlgorithms,getCertificateAuthorities,encode,parse];org.bouncycastle.crypto.tls.CertificateStatus[getStatusType,getResponse,getOCSPResponse,encode,parse];org.bouncycastle.crypto.tls.CertificateStatusRequest[getStatusType,getRequest,getOCSPStatusRequest,encode,parse];org.bouncycastle.crypto.tls.CertificateURL[getType,getURLAndHashList,encode,parse];org.bouncycastle.crypto.tls.Chacha20Poly1305[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.CipherSuite[isSCSV];org.bouncycastle.crypto.tls.DTLSClientProtocol[connect];org.bouncycastle.crypto.tls.DTLSServerProtocol[getVerifyRequests,setVerifyRequests,accept];org.bouncycastle.crypto.tls.DTLSTransport[getReceiveLimit,getSendLimit,receive,send,close];org.bouncycastle.crypto.tls.DefaultTlsAgreementCredentials[getCertificate,generateAgreement];org.bouncycastle.crypto.tls.DefaultTlsCipherFactory[createCipher];org.bouncycastle.crypto.tls.DefaultTlsClient[getCipherSuites,getKeyExchange,getMinimumVersion];org.bouncycastle.crypto.tls.DefaultTlsEncryptionCredentials[getCertificate,decryptPreMasterSecret];org.bouncycastle.crypto.tls.DefaultTlsSRPGroupVerifier[accept];org.bouncycastle.crypto.tls.DefaultTlsServer[getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.DefaultTlsSignerCredentials[getCertificate,generateCertificateSignature,getSignatureAndHashAlgorithm];org.bouncycastle.crypto.tls.DigitallySigned[getAlgorithm,getSignature,encode,parse];org.bouncycastle.crypto.tls.ECBasisType[isValid];org.bouncycastle.crypto.tls.FiniteFieldDHEGroup[isValid];org.bouncycastle.crypto.tls.HashAlgorithm[getName,getText,isPrivate];org.bouncycastle.crypto.tls.HeartbeatExtension[getMode,encode,parse];org.bouncycastle.crypto.tls.HeartbeatMessage[encode,parse];org.bouncycastle.crypto.tls.HeartbeatMessageType[isValid];org.bouncycastle.crypto.tls.HeartbeatMode[isValid];org.bouncycastle.crypto.tls.MaxFragmentLength[isValid];org.bouncycastle.crypto.tls.NameType[isValid];org.bouncycastle.crypto.tls.NamedCurve[isValid,refersToASpecificNamedCurve];org.bouncycastle.crypto.tls.NewSessionTicket[getTicketLifetimeHint,getTicket,encode,parse];org.bouncycastle.crypto.tls.OCSPStatusRequest[getResponderIDList,getRequestExtensions,encode,parse];org.bouncycastle.crypto.tls.PSKTlsClient[getCipherSuites,getKeyExchange,getAuthentication,getMinimumVersion];org.bouncycastle.crypto.tls.PSKTlsServer[getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.ProtocolVersion[getFullVersion,getMajorVersion,getMinorVersion,isDTLS,isSSL,isTLS,getEquivalentTLSVersion,isEqualOrEarlierVersionOf,isLaterVersionOf,equals,equals,hashCode,get,toString];org.bouncycastle.crypto.tls.SRPTlsClient[getCipherSuites,getClientExtensions,processServerExtensions,getKeyExchange,getAuthentication,getMinimumVersion];org.bouncycastle.crypto.tls.SRPTlsServer[processClientExtensions,getSelectedCipherSuite,getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.SSL3Mac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.tls.SecurityParameters[getEntity,getCipherSuite,getCompressionAlgorithm,getPrfAlgorithm,getVerifyDataLength,getMasterSecret,getClientRandom,getServerRandom,getSessionHash,getPskIdentity,getPSKIdentity,getSRPIdentity];org.bouncycastle.crypto.tls.ServerDHParams[getPublicKey,encode,parse];org.bouncycastle.crypto.tls.ServerName[getNameType,getName,getHostName,encode,parse];org.bouncycastle.crypto.tls.ServerNameList[getServerNameList,encode,parse];org.bouncycastle.crypto.tls.ServerOnlyTlsAuthentication[getClientCredentials];org.bouncycastle.crypto.tls.ServerSRPParams[getB,getG,getN,getS,encode,parse];org.bouncycastle.crypto.tls.SessionParameters[clear,copy,getCipherSuite,getCompressionAlgorithm,getMasterSecret,getPeerCertificate,getPskIdentity,getPSKIdentity,getSRPIdentity,readServerExtensions];org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm[getHash,getSignature,equals,hashCode,encode,parse];org.bouncycastle.crypto.tls.SimulatedTlsSRPIdentityManager[getRFC5054Default,getLoginParameters];org.bouncycastle.crypto.tls.SupplementalDataEntry[getDataType,getData];org.bouncycastle.crypto.tls.TlsAEADCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsBlockCipher[getWriteMac,getReadMac,getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsClientProtocol[connect,getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsDHEKeyExchange[processServerCredentials,generateServerKeyExchange,processServerKeyExchange];org.bouncycastle.crypto.tls.TlsDHKeyExchange[init,skipServerCredentials,processServerCertificate,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientCertificate,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsDHUtils[addNegotiatedDHEGroupsClientExtension,addNegotiatedDHEGroupsServerExtension,getNegotiatedDHEGroupsClientExtension,getNegotiatedDHEGroupsServerExtension,createNegotiatedDHEGroupsClientExtension,createNegotiatedDHEGroupsServerExtension,readNegotiatedDHEGroupsClientExtension,readNegotiatedDHEGroupsServerExtension,getParametersForDHEGroup,containsDHECipherSuites,isDHECipherSuite,areCompatibleParameters,calculateDHBasicAgreement,generateDHKeyPair,generateEphemeralClientKeyExchange,generateEphemeralServerKeyExchange,validateDHParameters,validateDHPublicKey,readDHParameter,writeDHParameter];org.bouncycastle.crypto.tls.TlsDSASigner[generateRawSignature,verifyRawSignature,createSigner,createVerifyer];org.bouncycastle.crypto.tls.TlsDSSSigner[isValidPublicKey];org.bouncycastle.crypto.tls.TlsECCUtils[addSupportedEllipticCurvesExtension,addSupportedPointFormatsExtension,getSupportedEllipticCurvesExtension,getSupportedPointFormatsExtension,createSupportedEllipticCurvesExtension,createSupportedPointFormatsExtension,readSupportedEllipticCurvesExtension,readSupportedPointFormatsExtension,getNameOfNamedCurve,getParametersForNamedCurve,hasAnySupportedNamedCurves,containsECCCipherSuites,isECCCipherSuite,areOnSameCurve,isSupportedNamedCurve,isCompressionPreferred,serializeECFieldElement,serializeECPoint,serializeECPublicKey,deserializeECFieldElement,deserializeECPoint,deserializeECPublicKey,calculateECDHBasicAgreement,generateECKeyPair,generateEphemeralClientKeyExchange,validateECPublicKey,readECExponent,readECFieldElement,readECParameter,readECParameters,writeECExponent,writeECFieldElement,writeECFieldElement,writeECParameter,writeExplicitECParameters,writeECPoint,writeNamedECParameters];org.bouncycastle.crypto.tls.TlsECDHEKeyExchange[processServerCredentials,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials];org.bouncycastle.crypto.tls.TlsECDHKeyExchange[init,skipServerCredentials,processServerCertificate,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientCertificate,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsECDSASigner[isValidPublicKey];org.bouncycastle.crypto.tls.TlsExtensionsUtils[ensureExtensionsInitialised,addEncryptThenMACExtension,addExtendedMasterSecretExtension,addHeartbeatExtension,addMaxFragmentLengthExtension,addPaddingExtension,addServerNameExtension,addStatusRequestExtension,addTruncatedHMacExtension,getHeartbeatExtension,getMaxFragmentLengthExtension,getPaddingExtension,getServerNameExtension,getStatusRequestExtension,hasEncryptThenMACExtension,hasExtendedMasterSecretExtension,hasTruncatedHMacExtension,createEmptyExtensionData,createEncryptThenMACExtension,createExtendedMasterSecretExtension,createHeartbeatExtension,createMaxFragmentLengthExtension,createPaddingExtension,createServerNameExtension,createStatusRequestExtension,createTruncatedHMacExtension,readEncryptThenMACExtension,readExtendedMasterSecretExtension,readHeartbeatExtension,readMaxFragmentLengthExtension,readPaddingExtension,readServerNameExtension,readStatusRequestExtension,readTruncatedHMacExtension];org.bouncycastle.crypto.tls.TlsFatalAlert[getAlertDescription,getCause];org.bouncycastle.crypto.tls.TlsFatalAlertReceived[getAlertDescription,getCause];org.bouncycastle.crypto.tls.TlsMac[getMACSecret,getSize,calculateMac,calculateMacConstantTime];org.bouncycastle.crypto.tls.TlsNullCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsNullCompression[compress,decompress];org.bouncycastle.crypto.tls.TlsPSKKeyExchange[skipServerCredentials,processServerCredentials,generateServerKeyExchange,processServerCertificate,requiresServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsProtocol[getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsRSAKeyExchange[skipServerCredentials,processServerCredentials,processServerCertificate,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsRSASigner[generateRawSignature,verifyRawSignature,createSigner,createVerifyer,isValidPublicKey];org.bouncycastle.crypto.tls.TlsRSAUtils[generateEncryptedPreMasterSecret,safeDecryptPreMasterSecret];org.bouncycastle.crypto.tls.TlsSRPKeyExchange[init,skipServerCredentials,processServerCertificate,processServerCredentials,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsSRPLoginParameters[getGroup,getSalt,getVerifier];org.bouncycastle.crypto.tls.TlsSRPUtils[addSRPExtension,getSRPExtension,createSRPExtension,readSRPExtension,readSRPParameter,writeSRPParameter,isSRPCipherSuite];org.bouncycastle.crypto.tls.TlsSRTPUtils[addUseSRTPExtension,getUseSRTPExtension,createUseSRTPExtension,readUseSRTPExtension];org.bouncycastle.crypto.tls.TlsServerProtocol[accept,getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsStreamCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsUtils[checkUint8,checkUint8,checkUint8,checkUint16,checkUint16,checkUint24,checkUint24,checkUint32,checkUint48,checkUint64,isValidUint8,isValidUint8,isValidUint8,isValidUint16,isValidUint16,isValidUint24,isValidUint24,isValidUint32,isValidUint48,isValidUint64,isSSL,isTLSv11,isTLSv11,isTLSv12,isTLSv12,writeUint8,writeUint8,writeUint8,writeUint8,writeUint16,writeUint16,writeUint24,writeUint24,writeUint32,writeUint32,writeUint48,writeUint48,writeUint64,writeUint64,writeOpaque8,writeOpaque16,writeOpaque24,writeUint8Array,writeUint8Array,writeUint8ArrayWithUint8Length,writeUint8ArrayWithUint8Length,writeUint16Array,writeUint16Array,writeUint16ArrayWithUint16Length,writeUint16ArrayWithUint16Length,encodeOpaque8,encodeUint8ArrayWithUint8Length,encodeUint16ArrayWithUint16Length,readUint8,readUint8,readUint16,readUint16,readUint24,readUint24,readUint32,readUint32,readUint48,readUint48,readAllOrNothing,readFully,readFully,readOpaque8,readOpaque16,readOpaque24,readUint8Array,readUint16Array,readVersion,readVersion,readVersionRaw,readVersionRaw,readASN1Object,readDERObject,writeGMTUnixTime,writeVersion,writeVersion,getAllSignatureAlgorithms,getDefaultDSSSignatureAlgorithms,getDefaultECDSASignatureAlgorithms,getDefaultRSASignatureAlgorithms,getDefaultSupportedSignatureAlgorithms,getSignatureAndHashAlgorithm,getExtensionData,hasExpectedEmptyExtensionData,importSession,isSignatureAlgorithmsExtensionAllowed,addSignatureAlgorithmsExtension,getSignatureAlgorithmsExtension,createSignatureAlgorithmsExtension,readSignatureAlgorithmsExtension,encodeSupportedSignatureAlgorithms,parseSupportedSignatureAlgorithms,verifySupportedSignatureAlgorithm,PRF,PRF_legacy,createHash,createHash,cloneHash,createPRFHash,clonePRFHash,getHashAlgorithmForPRFAlgorithm,getOIDForHashAlgorithm,hasSigningCapability,createTlsSigner,getCipherType,getEncryptionAlgorithm,getKeyExchangeAlgorithm,getMACAlgorithm,getMinimumVersion,isAEADCipherSuite,isBlockCipherSuite,isStreamCipherSuite,isValidCipherSuiteForSignatureAlgorithms,isValidCipherSuiteForVersion,getUsableSignatureAlgorithms];org.bouncycastle.crypto.tls.UDPTransport[getReceiveLimit,getSendLimit,receive,send,close];org.bouncycastle.crypto.tls.URLAndHash[getURL,getSHA1Hash,encode,parse];org.bouncycastle.crypto.tls.UseSRTPData[getProtectionProfiles,getMki];org.bouncycastle.crypto.util.DERMacData[getMacData];org.bouncycastle.crypto.util.DEROtherInfo[getEncoded];org.bouncycastle.crypto.util.DigestFactory[createMD5,createSHA1,createSHA224,createSHA256,createSHA384,createSHA512,createSHA512_224,createSHA512_256,createSHA3_224,createSHA3_256,createSHA3_384,createSHA3_512];org.bouncycastle.crypto.util.PBKDF2Config[getIterationCount,getPRF,getSaltLength,getAlgorithm];org.bouncycastle.crypto.util.PBKDFConfig[getAlgorithm];org.bouncycastle.crypto.util.Pack[bigEndianToInt,bigEndianToInt,intToBigEndian,intToBigEndian,intToBigEndian,intToBigEndian,bigEndianToLong,bigEndianToLong,longToBigEndian,longToBigEndian,longToBigEndian,longToBigEndian,littleEndianToInt,littleEndianToInt,littleEndianToInt,intToLittleEndian,intToLittleEndian,intToLittleEndian,intToLittleEndian,littleEndianToLong,littleEndianToLong,longToLittleEndian,longToLittleEndian,longToLittleEndian,longToLittleEndian];org.bouncycastle.crypto.util.PrivateKeyFactory[createKey,createKey,createKey];org.bouncycastle.crypto.util.PrivateKeyInfoFactory[createPrivateKeyInfo];org.bouncycastle.crypto.util.PublicKeyFactory[createKey,createKey,createKey,createKey];org.bouncycastle.crypto.util.ScryptConfig[getCostParameter,getBlockSize,getParallelizationParameter,getSaltLength,getAlgorithm];org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory[createSubjectPublicKeyInfo]"; + final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Server[init,init,generateServerCredentials,calculateSecret,verifyClientEvidenceMessage,calculateServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];org.bouncycastle.crypto.agreement.srp.SRP6VerifierGenerator[init,init,generateVerifier];org.bouncycastle.crypto.commitments.GeneralHashCommitter[commit,isRevealed];org.bouncycastle.crypto.commitments.HashCommitter[commit,isRevealed];org.bouncycastle.crypto.digests.Blake2bDigest[update,update,doFinal,reset,getAlgorithmName,getDigestSize,getByteLength,clearKey,clearSalt];org.bouncycastle.crypto.digests.Blake2sDigest[update,update,doFinal,reset,getAlgorithmName,getDigestSize,getByteLength,clearKey,clearSalt];org.bouncycastle.crypto.digests.DSTU7564Digest[getAlgorithmName,getDigestSize,getByteLength,update,update,doFinal,reset,copy,reset];org.bouncycastle.crypto.digests.GOST3411Digest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength,copy,reset];org.bouncycastle.crypto.digests.GOST3411_2012Digest[getByteLength,update,update,doFinal,reset,reset];org.bouncycastle.crypto.digests.GOST3411_2012_256Digest[getAlgorithmName,getDigestSize,doFinal,copy];org.bouncycastle.crypto.digests.GOST3411_2012_512Digest[getAlgorithmName,getDigestSize,copy];org.bouncycastle.crypto.digests.GeneralDigest[update,update,finish,reset,getByteLength];org.bouncycastle.crypto.digests.KeccakDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.LongDigest[update,update,finish,reset,getByteLength];org.bouncycastle.crypto.digests.MD2Digest[getAlgorithmName,getDigestSize,doFinal,reset,update,update,getByteLength,copy,reset];org.bouncycastle.crypto.digests.MD4Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.MD5Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.NonMemoableDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.NullDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset];org.bouncycastle.crypto.digests.RIPEMD128Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD160Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD256Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD320Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.SHA1Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA224Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA256Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA384Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA3Digest[getAlgorithmName,doFinal];org.bouncycastle.crypto.digests.SHA512Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA512tDigest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHAKEDigest[getAlgorithmName,doFinal,doFinal,doOutput];org.bouncycastle.crypto.digests.SM3Digest[getAlgorithmName,getDigestSize,copy,reset,reset,doFinal,finish];org.bouncycastle.crypto.digests.ShortenedDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.SkeinDigest[reset,copy,getAlgorithmName,getDigestSize,getByteLength,init,reset,update,update,doFinal];org.bouncycastle.crypto.digests.SkeinEngine[copy,reset,getOutputSize,getBlockSize,init,reset,update,update,doFinal];org.bouncycastle.crypto.digests.TigerDigest[getAlgorithmName,getDigestSize,update,update,unpackWord,doFinal,reset,getByteLength,copy,reset];org.bouncycastle.crypto.digests.WhirlpoolDigest[getAlgorithmName,getDigestSize,doFinal,reset,update,update,getByteLength,copy,reset];org.bouncycastle.crypto.ec.CustomNamedCurves[getByName,getByOID,getOID,getName,getNames];org.bouncycastle.crypto.ec.ECElGamalDecryptor[init,decrypt];org.bouncycastle.crypto.ec.ECElGamalEncryptor[init,encrypt];org.bouncycastle.crypto.ec.ECFixedTransform[init,transform,getTransformValue];org.bouncycastle.crypto.ec.ECNewPublicKeyTransform[init,transform];org.bouncycastle.crypto.ec.ECNewRandomnessTransform[init,transform,getTransformValue];org.bouncycastle.crypto.ec.ECPair[getX,getY,equals,equals,hashCode];org.bouncycastle.crypto.encodings.ISO9796d1Encoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,setPadBits,getPadBits,processBlock];org.bouncycastle.crypto.encodings.OAEPEncoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,processBlock,encodeBlock,decodeBlock];org.bouncycastle.crypto.encodings.PKCS1Encoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.AESEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.AESFastEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.AESLightEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.ARIAEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.BlowfishEngine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.CAST5Engine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.CAST6Engine[getAlgorithmName,reset,getBlockSize];org.bouncycastle.crypto.engines.CamelliaEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.CamelliaLightEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.ChaCha7539Engine[getAlgorithmName,salsaCore];org.bouncycastle.crypto.engines.ChaChaEngine[getAlgorithmName,chachaCore,salsaCore];org.bouncycastle.crypto.engines.CramerShoupCiphertext[getU1,setU1,getU2,setU2,getE,setE,getV,setV,toString,toByteArray];org.bouncycastle.crypto.engines.CramerShoupCoreEngine[init,init,getInputBlockSize,getOutputBlockSize,convertInput,convertOutput,encryptBlock,decryptBlock];org.bouncycastle.crypto.engines.CryptoProWrapEngine[init];org.bouncycastle.crypto.engines.DESEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DESedeEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DESedeWrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.DSTU7624Engine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DSTU7624WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.ElGamalEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.GOST28147Engine[init,getAlgorithmName,getBlockSize,processBlock,reset,getSBox,getSBoxName];org.bouncycastle.crypto.engines.GOST28147WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.GOST3412_2015Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.Grain128Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.Grainv1Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.HC128Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.HC256Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.IDEAEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.IESEngine[init,init,init,getCipher,getMac,processBlock];org.bouncycastle.crypto.engines.ISAACEngine[init,returnByte,processBytes,getAlgorithmName,reset];org.bouncycastle.crypto.engines.NaccacheSternEngine[init,setDebug,getInputBlockSize,getOutputBlockSize,processBlock,encrypt,addCryptedBlocks,processData];org.bouncycastle.crypto.engines.NoekeonEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.NullEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.OldIESEngine[init,init,init,getCipher,getMac,processBlock];org.bouncycastle.crypto.engines.RC2Engine[init,reset,getAlgorithmName,getBlockSize,processBlock];org.bouncycastle.crypto.engines.RC2WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RC4Engine[init,getAlgorithmName,returnByte,processBytes,reset];org.bouncycastle.crypto.engines.RC532Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RC564Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RC6Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RFC3211WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RFC3394WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RFC5649WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RSABlindedEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RSABlindingEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RSAEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RijndaelEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.SEEDEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.SM2Engine[init,processBlock];org.bouncycastle.crypto.engines.SM4Engine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.Salsa20Engine[init,getAlgorithmName,returnByte,processBytes,skip,seekTo,getPosition,reset,salsaCore];org.bouncycastle.crypto.engines.SerpentEngineBase[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.Shacal2Engine[reset,getAlgorithmName,getBlockSize,init,setKey,processBlock];org.bouncycastle.crypto.engines.SkipjackEngine[init,getAlgorithmName,getBlockSize,processBlock,reset,encryptBlock,decryptBlock];org.bouncycastle.crypto.engines.TEAEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.ThreefishEngine[init,init,getAlgorithmName,getBlockSize,reset,processBlock,processBlock,bytesToWord,wordToBytes];org.bouncycastle.crypto.engines.TnepresEngine[getAlgorithmName];org.bouncycastle.crypto.engines.TwofishEngine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.VMPCEngine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.VMPCKSA3Engine[getAlgorithmName];org.bouncycastle.crypto.engines.XSalsa20Engine[getAlgorithmName,salsaCore];org.bouncycastle.crypto.engines.XTEAEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.examples.DESExample[main];org.bouncycastle.crypto.examples.JPAKEExample[main];org.bouncycastle.crypto.generators.BCrypt[passwordToByteArray,generate];org.bouncycastle.crypto.generators.BaseKDFBytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.CramerShoupKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.CramerShoupParametersGenerator[init,generateParameters,generateParameters];org.bouncycastle.crypto.generators.DESKeyGenerator[init,generateKey];org.bouncycastle.crypto.generators.DESedeKeyGenerator[init,generateKey];org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DHKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DHParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.DSAKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DSAParametersGenerator[init,init,generateParameters];org.bouncycastle.crypto.generators.DSTU4145KeyPairGenerator[generateKeyPair];org.bouncycastle.crypto.generators.ECKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.ElGamalKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.ElGamalParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator[generate];org.bouncycastle.crypto.generators.GOST3410KeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.GOST3410ParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.HKDFBytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.KDFCounterBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.KDFDoublePipelineIterationBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.KDFFeedbackBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.MGF1BytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.NaccacheSternKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.OpenBSDBCrypt[generate,generate,checkPassword];org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator[init,generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS12ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.Poly1305KeyGenerator[init,generateKey,clamp,checkKey];org.bouncycastle.crypto.generators.RSABlindingFactorGenerator[init,generateBlindingFactor];org.bouncycastle.crypto.generators.RSAKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.SCrypt[generate];org.bouncycastle.crypto.io.CipherInputStream[read,read,read,skip,available,close,mark,reset,markSupported];org.bouncycastle.crypto.io.CipherOutputStream[write,write,write,flush,close];org.bouncycastle.crypto.io.DigestInputStream[read,read,getDigest];org.bouncycastle.crypto.io.DigestOutputStream[write,write,getDigest];org.bouncycastle.crypto.io.MacInputStream[read,read,getMac];org.bouncycastle.crypto.io.MacOutputStream[write,write,getMac];org.bouncycastle.crypto.io.SignerInputStream[read,read,getSigner];org.bouncycastle.crypto.io.SignerOutputStream[write,write,getSigner];org.bouncycastle.crypto.kems.ECIESKeyEncapsulation[init,encrypt,encrypt,decrypt,decrypt];org.bouncycastle.crypto.kems.RSAKeyEncapsulation[init,encrypt,encrypt,decrypt,decrypt];org.bouncycastle.crypto.macs.BlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CBCBlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CFBBlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.DSTU7564Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.DSTU7624Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.GMac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.GOST28147Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.HMac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.ISO9797Alg3Mac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.KGMac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.OldHMac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.Poly1305[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.SipHash[getAlgorithmName,getMacSize,init,update,update,doFinal,doFinal,reset];org.bouncycastle.crypto.macs.SkeinMac[getAlgorithmName,init,getMacSize,reset,update,update,doFinal];org.bouncycastle.crypto.macs.VMPCMac[doFinal,getAlgorithmName,getMacSize,init,reset,update,update];org.bouncycastle.crypto.modes.CBCBlockCipher[getUnderlyingCipher,init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.modes.CCMBlockCipher[getUnderlyingCipher,init,getAlgorithmName,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset,getMac,getUpdateOutputSize,getOutputSize,processPacket,processPacket];org.bouncycastle.crypto.modes.CFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,encryptBlock,decryptBlock,getCurrentIV,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.CTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.EAXBlockCipher[getAlgorithmName,getUnderlyingCipher,getBlockSize,init,reset,processAADByte,processAADBytes,processByte,processBytes,doFinal,getMac,getUpdateOutputSize,getOutputSize];org.bouncycastle.crypto.modes.G3413CBCBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.modes.G3413CFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.G3413CTRBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.G3413OFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.GCFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.GCMBlockCipher[getUnderlyingCipher,getAlgorithmName,init,getMac,getOutputSize,getUpdateOutputSize,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.modes.GOFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.KCCMBlockCipher[init,getAlgorithmName,getUnderlyingCipher,processAADByte,processAADBytes,processByte,processBytes,processPacket,doFinal,getMac,getUpdateOutputSize,getOutputSize,reset];org.bouncycastle.crypto.modes.KCTRBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.KGCMBlockCipher[init,getAlgorithmName,getUnderlyingCipher,processAADByte,processAADBytes,processByte,processBytes,doFinal,getMac,getUpdateOutputSize,getOutputSize,reset];org.bouncycastle.crypto.modes.KXTSBlockCipher[getOutputSize,getUpdateOutputSize,init,processByte,processBytes,doFinal,reset,getUnderlyingCipher,getBlockSize];org.bouncycastle.crypto.modes.NISTCTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.OCBBlockCipher[getUnderlyingCipher,getAlgorithmName,init,getMac,getOutputSize,getUpdateOutputSize,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.modes.OFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.OldCTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher[getUnderlyingCipher,getAlgorithmName,getBlockSize,processBlock,reset,init];org.bouncycastle.crypto.modes.PGPCFBBlockCipher[getUnderlyingCipher,getAlgorithmName,getBlockSize,processBlock,reset,init];org.bouncycastle.crypto.modes.PaddedBlockCipher[getOutputSize,getUpdateOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.SICBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,skip,seekTo,getPosition,getUnderlyingCipher];org.bouncycastle.crypto.modes.gcm.BasicGCMExponentiator[init,exponentiateX];org.bouncycastle.crypto.modes.gcm.BasicGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.GCMUtil[oneAsBytes,oneAsInts,oneAsLongs,asBytes,asBytes,asBytes,asBytes,asInts,asInts,asLongs,asLongs,copy,copy,divideP,multiply,multiply,multiply,multiplyP,multiplyP,multiplyP,multiplyP,multiplyP3,multiplyP4,multiplyP7,multiplyP8,multiplyP8,multiplyP8,multiplyP8,pAsLongs,square,xor,xor,xor,xor,xor,xor,xor,xor,xor,xor];org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator[init,exponentiateX];org.bouncycastle.crypto.modes.gcm.Tables4kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.Tables64kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_128[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_256[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_512[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_128[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_256[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_512[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.Tables16kKGCMMultiplier_512[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.Tables4kKGCMMultiplier_128[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.Tables8kKGCMMultiplier_256[init,multiplyH];org.bouncycastle.crypto.paddings.ISO10126d2Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.ISO7816d4Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.PKCS7Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher[init,getOutputSize,getUpdateOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,getBlockSize,reset];org.bouncycastle.crypto.paddings.TBCPadding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.X923Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.ZeroBytePadding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.params.AEADParameters[getKey,getMacSize,getAssociatedText,getNonce];org.bouncycastle.crypto.params.AsymmetricKeyParameter[isPrivate];org.bouncycastle.crypto.params.CCMParameters[getKey,getMacSize,getAssociatedText,getNonce];org.bouncycastle.crypto.params.CramerShoupKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.CramerShoupKeyParameters[getParameters,equals,hashCode,isPrivate];org.bouncycastle.crypto.params.CramerShoupParameters[equals,hashCode,getG1,getG2,getP,getH];org.bouncycastle.crypto.params.CramerShoupPrivateKeyParameters[getX1,getX2,getY1,getY2,getZ,setPk,getPk,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.CramerShoupPublicKeyParameters[getC,getD,getH,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DESParameters[isWeakKey,setOddParity,getKey];org.bouncycastle.crypto.params.DESedeParameters[isWeakKey,isWeakKey,isRealEDEKey,isReal2Key,isReal3Key,setOddParity,getKey];org.bouncycastle.crypto.params.DHKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.DHKeyParameters[getParameters,equals,hashCode,isPrivate];org.bouncycastle.crypto.params.DHMQVPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHMQVPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHParameters[getP,getG,getQ,getJ,getM,getL,getValidationParameters,equals,hashCode];org.bouncycastle.crypto.params.DHPrivateKeyParameters[getX,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DHPublicKeyParameters[getY,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DHUPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHUPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHValidationParameters[getCounter,getSeed,equals,hashCode];org.bouncycastle.crypto.params.DSAKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.DSAKeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.DSAParameterGenerationParameters[getL,getN,getCertainty,getRandom,getUsageIndex];org.bouncycastle.crypto.params.DSAParameters[getP,getQ,getG,getValidationParameters,equals,hashCode];org.bouncycastle.crypto.params.DSAPrivateKeyParameters[getX,getParameters,isPrivate];org.bouncycastle.crypto.params.DSAPublicKeyParameters[getY,getParameters,isPrivate];org.bouncycastle.crypto.params.DSAValidationParameters[getCounter,getSeed,getUsageIndex,hashCode,equals];org.bouncycastle.crypto.params.ECDHUPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.ECDHUPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.ECDomainParameters[getCurve,getG,getN,getH,getHInv,getSeed,equals,hashCode];org.bouncycastle.crypto.params.ECKeyGenerationParameters[getDomainParameters,getRandom,getStrength];org.bouncycastle.crypto.params.ECKeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.ECNamedDomainParameters[getName,getCurve,getG,getN,getH,getHInv,getSeed,equals,hashCode];org.bouncycastle.crypto.params.ECPrivateKeyParameters[getD,getParameters,isPrivate];org.bouncycastle.crypto.params.ECPublicKeyParameters[getQ,getParameters,isPrivate];org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.ElGamalKeyParameters[getParameters,hashCode,equals,isPrivate];org.bouncycastle.crypto.params.ElGamalParameters[getP,getG,getL,equals,hashCode];org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters[getX,equals,hashCode,getParameters,isPrivate];org.bouncycastle.crypto.params.ElGamalPublicKeyParameters[getY,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410KeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.GOST3410KeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410Parameters[getP,getQ,getA,getValidationParameters,hashCode,equals];org.bouncycastle.crypto.params.GOST3410PrivateKeyParameters[getX,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410PublicKeyParameters[getY,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410ValidationParameters[getC,getX0,getCL,getX0L,equals,hashCode];org.bouncycastle.crypto.params.HKDFParameters[skipExtractParameters,defaultParameters,getIKM,skipExtract,getSalt,getInfo];org.bouncycastle.crypto.params.IESParameters[getDerivationV,getEncodingV,getMacKeySize];org.bouncycastle.crypto.params.IESWithCipherParameters[getCipherKeySize,getDerivationV,getEncodingV,getMacKeySize];org.bouncycastle.crypto.params.ISO18033KDFParameters[getSeed];org.bouncycastle.crypto.params.KDFCounterParameters[getKI,getFixedInputData,getFixedInputDataCounterPrefix,getFixedInputDataCounterSuffix,getR];org.bouncycastle.crypto.params.KDFDoublePipelineIterationParameters[createWithCounter,createWithoutCounter,getKI,useCounter,getR,getFixedInputData];org.bouncycastle.crypto.params.KDFFeedbackParameters[createWithCounter,createWithoutCounter,getKI,getIV,useCounter,getR,getFixedInputData];org.bouncycastle.crypto.params.KDFParameters[getSharedSecret,getIV];org.bouncycastle.crypto.params.KeyParameter[getKey];org.bouncycastle.crypto.params.MGFParameters[getSeed];org.bouncycastle.crypto.params.MQVPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.MQVPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.NaccacheSternKeyGenerationParameters[getCertainty,getCntSmallPrimes,isDebug,getRandom,getStrength];org.bouncycastle.crypto.params.NaccacheSternKeyParameters[getG,getLowerSigmaBound,getModulus,isPrivate];org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters[getPhi_n,getSmallPrimes,getG,getLowerSigmaBound,getModulus,isPrivate];org.bouncycastle.crypto.params.ParametersWithID[getID,getParameters];org.bouncycastle.crypto.params.ParametersWithIV[getIV,getParameters];org.bouncycastle.crypto.params.ParametersWithRandom[getRandom,getParameters];org.bouncycastle.crypto.params.ParametersWithSBox[getSBox,getParameters];org.bouncycastle.crypto.params.ParametersWithSalt[getSalt,getParameters];org.bouncycastle.crypto.params.ParametersWithUKM[getUKM,getParameters];org.bouncycastle.crypto.params.RC2Parameters[getEffectiveKeyBits,getKey];org.bouncycastle.crypto.params.RC5Parameters[getKey,getRounds];org.bouncycastle.crypto.params.RSABlindingParameters[getPublicKey,getBlindingFactor];org.bouncycastle.crypto.params.RSAKeyGenerationParameters[getPublicExponent,getCertainty,getRandom,getStrength];org.bouncycastle.crypto.params.RSAKeyParameters[getModulus,getExponent,isPrivate];org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters[getPublicExponent,getP,getQ,getDP,getDQ,getQInv,getModulus,getExponent,isPrivate];org.bouncycastle.crypto.params.SM2KeyExchangePrivateParameters[isInitiator,getStaticPrivateKey,getStaticPublicPoint,getEphemeralPrivateKey,getEphemeralPublicPoint];org.bouncycastle.crypto.params.SM2KeyExchangePublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.SRP6GroupParameters[getG,getN];org.bouncycastle.crypto.params.SkeinParameters[getParameters,getKey,getPersonalisation,getPublicKey,getKeyIdentifier,getNonce];org.bouncycastle.crypto.params.TweakableBlockCipherParameters[getKey,getTweak];org.bouncycastle.crypto.parsers.DHIESPublicKeyParser[readKey];org.bouncycastle.crypto.parsers.ECIESPublicKeyParser[readKey];org.bouncycastle.crypto.prng.BasicEntropySourceProvider[get];org.bouncycastle.crypto.prng.DigestRandomGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.EntropyUtil[generateSeed];org.bouncycastle.crypto.prng.FixedSecureRandom[nextBytes,generateSeed,nextInt,nextLong,isExhausted];org.bouncycastle.crypto.prng.ReversedWindowGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.SP800SecureRandom[setSeed,setSeed,nextBytes,generateSeed,reseed];org.bouncycastle.crypto.prng.SP800SecureRandomBuilder[setPersonalizationString,setSecurityStrength,setEntropyBitsRequired,buildHash,buildCTR,buildHMAC];org.bouncycastle.crypto.prng.ThreadedSeedGenerator[generateSeed];org.bouncycastle.crypto.prng.VMPCRandomGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.X931SecureRandom[setSeed,setSeed,nextBytes,generateSeed];org.bouncycastle.crypto.prng.X931SecureRandomBuilder[setDateTimeVector,build];org.bouncycastle.crypto.prng.drbg.CTRSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.DualECPoints[getSeedLen,getMaxOutlen,getP,getQ,getSecurityStrength,getCofactor];org.bouncycastle.crypto.prng.drbg.DualECSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.HMacSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.HashSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.signers.DSADigestSigner[init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.DSASigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.DSTU4145Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECDSASigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECGOST3410Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECGOST3410_2012Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECNRSigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.GOST3410Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.GenericSigner[init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.HMacDSAKCalculator[isDeterministic,init,init,nextK];org.bouncycastle.crypto.signers.ISO9796d2PSSSigner[init,updateWithRecoveredMessage,update,update,reset,generateSignature,verifySignature,hasFullMessage,getRecoveredMessage];org.bouncycastle.crypto.signers.ISO9796d2Signer[init,updateWithRecoveredMessage,update,update,reset,generateSignature,verifySignature,hasFullMessage,getRecoveredMessage];org.bouncycastle.crypto.signers.ISOTrailers[getTrailer,noTrailerAvailable];org.bouncycastle.crypto.signers.PSSSigner[init,update,update,reset,generateSignature,verifySignature];org.bouncycastle.crypto.signers.RSADigestSigner[getAlgorithmName,init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.RandomDSAKCalculator[isDeterministic,init,init,nextK];org.bouncycastle.crypto.signers.SM2Signer[init,update,update,verifySignature,reset,generateSignature];org.bouncycastle.crypto.signers.X931Signer[init,update,update,reset,generateSignature,verifySignature];org.bouncycastle.crypto.tls.AbstractTlsCipherFactory[createCipher];org.bouncycastle.crypto.tls.AbstractTlsClient[init,getSessionToResume,getClientHelloRecordLayerVersion,getClientVersion,isFallback,getClientExtensions,getMinimumVersion,notifyServerVersion,getCompressionMethods,notifySessionID,notifySelectedCipherSuite,notifySelectedCompressionMethod,processServerExtensions,processServerSupplementalData,getClientSupplementalData,getCompression,getCipher,notifyNewSessionTicket];org.bouncycastle.crypto.tls.AbstractTlsKeyExchange[init,processServerCertificate,processServerCredentials,requiresServerKeyExchange,generateServerKeyExchange,skipServerKeyExchange,processServerKeyExchange,skipClientCredentials,processClientCertificate,processClientKeyExchange];org.bouncycastle.crypto.tls.AbstractTlsPeer[shouldUseGMTUnixTime,notifySecureRenegotiation,notifyAlertRaised,notifyAlertReceived,notifyHandshakeComplete];org.bouncycastle.crypto.tls.AbstractTlsServer[init,notifyClientVersion,notifyFallback,notifyOfferedCipherSuites,notifyOfferedCompressionMethods,processClientExtensions,getServerVersion,getSelectedCipherSuite,getSelectedCompressionMethod,getServerExtensions,getServerSupplementalData,getCertificateStatus,getCertificateRequest,processClientSupplementalData,notifyClientCertificate,getCompression,getCipher,getNewSessionTicket];org.bouncycastle.crypto.tls.AbstractTlsSigner[init,generateRawSignature,verifyRawSignature,createSigner,createVerifyer];org.bouncycastle.crypto.tls.AbstractTlsSignerCredentials[getSignatureAndHashAlgorithm];org.bouncycastle.crypto.tls.AlertDescription[getName,getText];org.bouncycastle.crypto.tls.AlertLevel[getName,getText];org.bouncycastle.crypto.tls.BasicTlsPSKIdentity[skipIdentityHint,notifyIdentityHint,getPSKIdentity,getPSK];org.bouncycastle.crypto.tls.ByteQueue[nextTwoPow,addData,available,copyTo,read,readFrom,removeData,removeData,removeData,shrink];org.bouncycastle.crypto.tls.ByteQueueInputStream[addBytes,peek,read,read,read,skip,available,close];org.bouncycastle.crypto.tls.ByteQueueOutputStream[getBuffer,write,write];org.bouncycastle.crypto.tls.CertChainType[isValid];org.bouncycastle.crypto.tls.Certificate[getCertificateList,getCertificateAt,getLength,isEmpty,encode,parse];org.bouncycastle.crypto.tls.CertificateRequest[getCertificateTypes,getSupportedSignatureAlgorithms,getCertificateAuthorities,encode,parse];org.bouncycastle.crypto.tls.CertificateStatus[getStatusType,getResponse,getOCSPResponse,encode,parse];org.bouncycastle.crypto.tls.CertificateStatusRequest[getStatusType,getRequest,getOCSPStatusRequest,encode,parse];org.bouncycastle.crypto.tls.CertificateURL[getType,getURLAndHashList,encode,parse];org.bouncycastle.crypto.tls.Chacha20Poly1305[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.CipherSuite[isSCSV];org.bouncycastle.crypto.tls.DTLSClientProtocol[connect];org.bouncycastle.crypto.tls.DTLSServerProtocol[getVerifyRequests,setVerifyRequests,accept];org.bouncycastle.crypto.tls.DTLSTransport[getReceiveLimit,getSendLimit,receive,send,close];org.bouncycastle.crypto.tls.DefaultTlsAgreementCredentials[getCertificate,generateAgreement];org.bouncycastle.crypto.tls.DefaultTlsCipherFactory[createCipher];org.bouncycastle.crypto.tls.DefaultTlsClient[getCipherSuites,getKeyExchange,getMinimumVersion];org.bouncycastle.crypto.tls.DefaultTlsEncryptionCredentials[getCertificate,decryptPreMasterSecret];org.bouncycastle.crypto.tls.DefaultTlsSRPGroupVerifier[accept];org.bouncycastle.crypto.tls.DefaultTlsServer[getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.DefaultTlsSignerCredentials[getCertificate,generateCertificateSignature,getSignatureAndHashAlgorithm];org.bouncycastle.crypto.tls.DigitallySigned[getAlgorithm,getSignature,encode,parse];org.bouncycastle.crypto.tls.ECBasisType[isValid];org.bouncycastle.crypto.tls.FiniteFieldDHEGroup[isValid];org.bouncycastle.crypto.tls.HashAlgorithm[getName,getText,isPrivate];org.bouncycastle.crypto.tls.HeartbeatExtension[getMode,encode,parse];org.bouncycastle.crypto.tls.HeartbeatMessage[encode,parse];org.bouncycastle.crypto.tls.HeartbeatMessageType[isValid];org.bouncycastle.crypto.tls.HeartbeatMode[isValid];org.bouncycastle.crypto.tls.MaxFragmentLength[isValid];org.bouncycastle.crypto.tls.NameType[isValid];org.bouncycastle.crypto.tls.NamedCurve[isValid,refersToASpecificNamedCurve];org.bouncycastle.crypto.tls.NewSessionTicket[getTicketLifetimeHint,getTicket,encode,parse];org.bouncycastle.crypto.tls.OCSPStatusRequest[getResponderIDList,getRequestExtensions,encode,parse];org.bouncycastle.crypto.tls.PSKTlsClient[getCipherSuites,getKeyExchange,getAuthentication,getMinimumVersion];org.bouncycastle.crypto.tls.PSKTlsServer[getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.ProtocolVersion[getFullVersion,getMajorVersion,getMinorVersion,isDTLS,isSSL,isTLS,getEquivalentTLSVersion,isEqualOrEarlierVersionOf,isLaterVersionOf,equals,equals,hashCode,get,toString];org.bouncycastle.crypto.tls.SRPTlsClient[getCipherSuites,getClientExtensions,processServerExtensions,getKeyExchange,getAuthentication,getMinimumVersion];org.bouncycastle.crypto.tls.SRPTlsServer[processClientExtensions,getSelectedCipherSuite,getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.SSL3Mac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.tls.SecurityParameters[getEntity,getCipherSuite,getCompressionAlgorithm,getPrfAlgorithm,getVerifyDataLength,getMasterSecret,getClientRandom,getServerRandom,getSessionHash,getPskIdentity,getPSKIdentity,getSRPIdentity];org.bouncycastle.crypto.tls.ServerDHParams[getPublicKey,encode,parse];org.bouncycastle.crypto.tls.ServerName[getNameType,getName,getHostName,encode,parse];org.bouncycastle.crypto.tls.ServerNameList[getServerNameList,encode,parse];org.bouncycastle.crypto.tls.ServerOnlyTlsAuthentication[getClientCredentials];org.bouncycastle.crypto.tls.ServerSRPParams[getB,getG,getN,getS,encode,parse];org.bouncycastle.crypto.tls.SessionParameters[clear,copy,getCipherSuite,getCompressionAlgorithm,getMasterSecret,getPeerCertificate,getPskIdentity,getPSKIdentity,getSRPIdentity,readServerExtensions];org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm[getHash,getSignature,equals,hashCode,encode,parse];org.bouncycastle.crypto.tls.SimulatedTlsSRPIdentityManager[getRFC5054Default,getLoginParameters];org.bouncycastle.crypto.tls.SupplementalDataEntry[getDataType,getData];org.bouncycastle.crypto.tls.TlsAEADCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsBlockCipher[getWriteMac,getReadMac,getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsClientProtocol[connect,getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsDHEKeyExchange[processServerCredentials,generateServerKeyExchange,processServerKeyExchange];org.bouncycastle.crypto.tls.TlsDHKeyExchange[init,skipServerCredentials,processServerCertificate,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientCertificate,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsDHUtils[addNegotiatedDHEGroupsClientExtension,addNegotiatedDHEGroupsServerExtension,getNegotiatedDHEGroupsClientExtension,getNegotiatedDHEGroupsServerExtension,createNegotiatedDHEGroupsClientExtension,createNegotiatedDHEGroupsServerExtension,readNegotiatedDHEGroupsClientExtension,readNegotiatedDHEGroupsServerExtension,getParametersForDHEGroup,containsDHECipherSuites,isDHECipherSuite,areCompatibleParameters,calculateDHBasicAgreement,generateDHKeyPair,generateEphemeralClientKeyExchange,generateEphemeralServerKeyExchange,validateDHParameters,validateDHPublicKey,readDHParameter,writeDHParameter];org.bouncycastle.crypto.tls.TlsDSASigner[generateRawSignature,verifyRawSignature,createSigner,createVerifyer];org.bouncycastle.crypto.tls.TlsDSSSigner[isValidPublicKey];org.bouncycastle.crypto.tls.TlsECCUtils[addSupportedEllipticCurvesExtension,addSupportedPointFormatsExtension,getSupportedEllipticCurvesExtension,getSupportedPointFormatsExtension,createSupportedEllipticCurvesExtension,createSupportedPointFormatsExtension,readSupportedEllipticCurvesExtension,readSupportedPointFormatsExtension,getNameOfNamedCurve,getParametersForNamedCurve,hasAnySupportedNamedCurves,containsECCCipherSuites,isECCCipherSuite,areOnSameCurve,isSupportedNamedCurve,isCompressionPreferred,serializeECFieldElement,serializeECPoint,serializeECPublicKey,deserializeECFieldElement,deserializeECPoint,deserializeECPublicKey,calculateECDHBasicAgreement,generateECKeyPair,generateEphemeralClientKeyExchange,validateECPublicKey,readECExponent,readECFieldElement,readECParameter,readECParameters,writeECExponent,writeECFieldElement,writeECFieldElement,writeECParameter,writeExplicitECParameters,writeECPoint,writeNamedECParameters];org.bouncycastle.crypto.tls.TlsECDHEKeyExchange[processServerCredentials,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials];org.bouncycastle.crypto.tls.TlsECDHKeyExchange[init,skipServerCredentials,processServerCertificate,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientCertificate,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsECDSASigner[isValidPublicKey];org.bouncycastle.crypto.tls.TlsExtensionsUtils[ensureExtensionsInitialised,addEncryptThenMACExtension,addExtendedMasterSecretExtension,addHeartbeatExtension,addMaxFragmentLengthExtension,addPaddingExtension,addServerNameExtension,addStatusRequestExtension,addTruncatedHMacExtension,getHeartbeatExtension,getMaxFragmentLengthExtension,getPaddingExtension,getServerNameExtension,getStatusRequestExtension,hasEncryptThenMACExtension,hasExtendedMasterSecretExtension,hasTruncatedHMacExtension,createEmptyExtensionData,createEncryptThenMACExtension,createExtendedMasterSecretExtension,createHeartbeatExtension,createMaxFragmentLengthExtension,createPaddingExtension,createServerNameExtension,createStatusRequestExtension,createTruncatedHMacExtension,readEncryptThenMACExtension,readExtendedMasterSecretExtension,readHeartbeatExtension,readMaxFragmentLengthExtension,readPaddingExtension,readServerNameExtension,readStatusRequestExtension,readTruncatedHMacExtension];org.bouncycastle.crypto.tls.TlsFatalAlert[getAlertDescription,getCause];org.bouncycastle.crypto.tls.TlsFatalAlertReceived[getAlertDescription,getCause];org.bouncycastle.crypto.tls.TlsMac[getMACSecret,getSize,calculateMac,calculateMacConstantTime];org.bouncycastle.crypto.tls.TlsNullCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsNullCompression[compress,decompress];org.bouncycastle.crypto.tls.TlsPSKKeyExchange[skipServerCredentials,processServerCredentials,generateServerKeyExchange,processServerCertificate,requiresServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsProtocol[getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsRSAKeyExchange[skipServerCredentials,processServerCredentials,processServerCertificate,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsRSASigner[generateRawSignature,verifyRawSignature,createSigner,createVerifyer,isValidPublicKey];org.bouncycastle.crypto.tls.TlsRSAUtils[generateEncryptedPreMasterSecret,safeDecryptPreMasterSecret];org.bouncycastle.crypto.tls.TlsSRPKeyExchange[init,skipServerCredentials,processServerCertificate,processServerCredentials,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsSRPLoginParameters[getGroup,getSalt,getVerifier];org.bouncycastle.crypto.tls.TlsSRPUtils[addSRPExtension,getSRPExtension,createSRPExtension,readSRPExtension,readSRPParameter,writeSRPParameter,isSRPCipherSuite];org.bouncycastle.crypto.tls.TlsSRTPUtils[addUseSRTPExtension,getUseSRTPExtension,createUseSRTPExtension,readUseSRTPExtension];org.bouncycastle.crypto.tls.TlsServerProtocol[accept,getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsStreamCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsUtils[checkUint8,checkUint8,checkUint8,checkUint16,checkUint16,checkUint24,checkUint24,checkUint32,checkUint48,checkUint64,isValidUint8,isValidUint8,isValidUint8,isValidUint16,isValidUint16,isValidUint24,isValidUint24,isValidUint32,isValidUint48,isValidUint64,isSSL,isTLSv11,isTLSv11,isTLSv12,isTLSv12,writeUint8,writeUint8,writeUint8,writeUint8,writeUint16,writeUint16,writeUint24,writeUint24,writeUint32,writeUint32,writeUint48,writeUint48,writeUint64,writeUint64,writeOpaque8,writeOpaque16,writeOpaque24,writeUint8Array,writeUint8Array,writeUint8ArrayWithUint8Length,writeUint8ArrayWithUint8Length,writeUint16Array,writeUint16Array,writeUint16ArrayWithUint16Length,writeUint16ArrayWithUint16Length,encodeOpaque8,encodeUint8ArrayWithUint8Length,encodeUint16ArrayWithUint16Length,readUint8,readUint8,readUint16,readUint16,readUint24,readUint24,readUint32,readUint32,readUint48,readUint48,readAllOrNothing,readFully,readFully,readOpaque8,readOpaque16,readOpaque24,readUint8Array,readUint16Array,readVersion,readVersion,readVersionRaw,readVersionRaw,readASN1Object,readDERObject,writeGMTUnixTime,writeVersion,writeVersion,getAllSignatureAlgorithms,getDefaultDSSSignatureAlgorithms,getDefaultECDSASignatureAlgorithms,getDefaultRSASignatureAlgorithms,getDefaultSupportedSignatureAlgorithms,getSignatureAndHashAlgorithm,getExtensionData,hasExpectedEmptyExtensionData,importSession,isSignatureAlgorithmsExtensionAllowed,addSignatureAlgorithmsExtension,getSignatureAlgorithmsExtension,createSignatureAlgorithmsExtension,readSignatureAlgorithmsExtension,encodeSupportedSignatureAlgorithms,parseSupportedSignatureAlgorithms,verifySupportedSignatureAlgorithm,PRF,PRF_legacy,createHash,createHash,cloneHash,createPRFHash,clonePRFHash,getHashAlgorithmForPRFAlgorithm,getOIDForHashAlgorithm,hasSigningCapability,createTlsSigner,getCipherType,getEncryptionAlgorithm,getKeyExchangeAlgorithm,getMACAlgorithm,getMinimumVersion,isAEADCipherSuite,isBlockCipherSuite,isStreamCipherSuite,isValidCipherSuiteForSignatureAlgorithms,isValidCipherSuiteForVersion,getUsableSignatureAlgorithms];org.bouncycastle.crypto.tls.UDPTransport[getReceiveLimit,getSendLimit,receive,send,close];org.bouncycastle.crypto.tls.URLAndHash[getURL,getSHA1Hash,encode,parse];org.bouncycastle.crypto.tls.UseSRTPData[getProtectionProfiles,getMki];org.bouncycastle.crypto.util.DERMacData[getMacData];org.bouncycastle.crypto.util.DEROtherInfo[getEncoded];org.bouncycastle.crypto.util.DigestFactory[createMD5,createSHA1,createSHA224,createSHA256,createSHA384,createSHA512,createSHA512_224,createSHA512_256,createSHA3_224,createSHA3_256,createSHA3_384,createSHA3_512];org.bouncycastle.crypto.util.PBKDF2Config[getIterationCount,getPRF,getSaltLength,getAlgorithm];org.bouncycastle.crypto.util.PBKDFConfig[getAlgorithm];org.bouncycastle.crypto.util.Pack[bigEndianToInt,bigEndianToInt,intToBigEndian,intToBigEndian,intToBigEndian,intToBigEndian,bigEndianToLong,bigEndianToLong,longToBigEndian,longToBigEndian,longToBigEndian,longToBigEndian,littleEndianToInt,littleEndianToInt,littleEndianToInt,intToLittleEndian,intToLittleEndian,intToLittleEndian,intToLittleEndian,littleEndianToLong,littleEndianToLong,longToLittleEndian,longToLittleEndian,longToLittleEndian,longToLittleEndian];org.bouncycastle.crypto.util.PrivateKeyFactory[createKey,createKey,createKey];org.bouncycastle.crypto.util.PrivateKeyInfoFactory[createPrivateKeyInfo];org.bouncycastle.crypto.util.PublicKeyFactory[createKey,createKey,createKey,createKey];org.bouncycastle.crypto.util.ScryptConfig[getCostParameter,getBlockSize,getParallelizationParameter,getSaltLength,getAlgorithm];org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory[createSubjectPublicKeyInfo]" setup: - def traceConfigInstrumentation; + def traceConfigInstrumentation when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) then: traceConfigInstrumentation.classMethodsToTrace.size() == 471 } def "test list invalid method list"() { - final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Server[];org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];"; + final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Server[];org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];" setup: - def traceConfigInstrumentation; + def traceConfigInstrumentation when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) then: traceConfigInstrumentation.classMethodsToTrace.size() == 0 } def "test list invalid separation"() { - final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey]org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];"; + final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey]org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];" setup: - def traceConfigInstrumentation; + def traceConfigInstrumentation when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) then: traceConfigInstrumentation.classMethodsToTrace.size() == 0 } def "test list invalid class"() { - final interestingClasses = "orgbouncycastlecrypto@3AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];"; + final interestingClasses = "orgbouncycastlecrypto@3AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];" setup: - def traceConfigInstrumentation; + def traceConfigInstrumentation when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) then: traceConfigInstrumentation.classMethodsToTrace.size() == 0 } def "test list without trailing semi-colon"() { - final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset]"; + final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset]" setup: - def traceConfigInstrumentation; + def traceConfigInstrumentation when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses); + traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) then: traceConfigInstrumentation.classMethodsToTrace.size() == 2 From 811051d111e2342a063230918688923596bca140 Mon Sep 17 00:00:00 2001 From: Blinkingor Date: Tue, 28 Jan 2020 16:06:23 +0100 Subject: [PATCH 30/37] Remove overlapping tests and fix failing unit test --- .../TraceConfigInstrumentation.java | 8 +- .../TraceConfigInstrumentationTest.groovy | 102 ------------------ 2 files changed, 2 insertions(+), 108 deletions(-) delete mode 100644 dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy diff --git a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java index 549466cf9d..d798482ac6 100644 --- a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java +++ b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java @@ -48,7 +48,7 @@ public class TraceConfigInstrumentation implements Instrumenter { private boolean validateConfigString(String configString) { for (String clazz : configString.split(";")) { - if (!clazz.matches(CONFIG_FORMAT)) { + if (!clazz.trim().matches(CONFIG_FORMAT)) { return false; } } @@ -56,11 +56,7 @@ public class TraceConfigInstrumentation implements Instrumenter { } public TraceConfigInstrumentation() { - this(Config.get().getTraceMethods()); - } - - public TraceConfigInstrumentation(final String configString) { - + String configString = Config.get().getTraceMethods(); if (configString == null || configString.trim().isEmpty()) { classMethodsToTrace = Collections.emptyMap(); diff --git a/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy b/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy deleted file mode 100644 index 96f0326a24..0000000000 --- a/dd-java-agent/instrumentation/trace-annotation/src/test/groovy/TraceConfigInstrumentationTest.groovy +++ /dev/null @@ -1,102 +0,0 @@ -import datadog.trace.agent.test.AgentTestRunner -import datadog.trace.agent.test.utils.ConfigUtils -import datadog.trace.instrumentation.trace_annotation.TraceConfigInstrumentation - -class TraceConfigInstrumentationTest extends AgentTestRunner { - - def "test no arg constructor simple"() { - final interestingClass = "java.lang.String[toString]" - setup: - ConfigUtils.updateConfig { - System.setProperty("dd.trace.methods", interestingClass) - } - def traceConfigInstrumentation - - when: - traceConfigInstrumentation = new TraceConfigInstrumentation() - - then: - traceConfigInstrumentation.classMethodsToTrace.size() == 1 - traceConfigInstrumentation.classMethodsToTrace.containsKey("java.lang.String") - traceConfigInstrumentation.classMethodsToTrace.get("java.lang.String").contains("toString") - } - - def "test no arg constructor multi"() { - final interestingClass = "java.lang.String[toString];java.math.BigDecimal[negate, floatValue];" - setup: - ConfigUtils.updateConfig { - System.setProperty("dd.trace.methods", interestingClass) - } - def traceConfigInstrumentation - - when: - traceConfigInstrumentation = new TraceConfigInstrumentation() - - then: - traceConfigInstrumentation.classMethodsToTrace.size() == 2 - traceConfigInstrumentation.classMethodsToTrace.containsKey("java.lang.String") - traceConfigInstrumentation.classMethodsToTrace.containsKey("java.math.BigDecimal") - traceConfigInstrumentation.classMethodsToTrace.get("java.math.BigDecimal").contains("negate") - traceConfigInstrumentation.classMethodsToTrace.get("java.math.BigDecimal").contains("floatValue") - } - - def "test large list valid"() { - final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Server[init,init,generateServerCredentials,calculateSecret,verifyClientEvidenceMessage,calculateServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];org.bouncycastle.crypto.agreement.srp.SRP6VerifierGenerator[init,init,generateVerifier];org.bouncycastle.crypto.commitments.GeneralHashCommitter[commit,isRevealed];org.bouncycastle.crypto.commitments.HashCommitter[commit,isRevealed];org.bouncycastle.crypto.digests.Blake2bDigest[update,update,doFinal,reset,getAlgorithmName,getDigestSize,getByteLength,clearKey,clearSalt];org.bouncycastle.crypto.digests.Blake2sDigest[update,update,doFinal,reset,getAlgorithmName,getDigestSize,getByteLength,clearKey,clearSalt];org.bouncycastle.crypto.digests.DSTU7564Digest[getAlgorithmName,getDigestSize,getByteLength,update,update,doFinal,reset,copy,reset];org.bouncycastle.crypto.digests.GOST3411Digest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength,copy,reset];org.bouncycastle.crypto.digests.GOST3411_2012Digest[getByteLength,update,update,doFinal,reset,reset];org.bouncycastle.crypto.digests.GOST3411_2012_256Digest[getAlgorithmName,getDigestSize,doFinal,copy];org.bouncycastle.crypto.digests.GOST3411_2012_512Digest[getAlgorithmName,getDigestSize,copy];org.bouncycastle.crypto.digests.GeneralDigest[update,update,finish,reset,getByteLength];org.bouncycastle.crypto.digests.KeccakDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.LongDigest[update,update,finish,reset,getByteLength];org.bouncycastle.crypto.digests.MD2Digest[getAlgorithmName,getDigestSize,doFinal,reset,update,update,getByteLength,copy,reset];org.bouncycastle.crypto.digests.MD4Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.MD5Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.NonMemoableDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.NullDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset];org.bouncycastle.crypto.digests.RIPEMD128Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD160Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD256Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.RIPEMD320Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,finish];org.bouncycastle.crypto.digests.SHA1Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA224Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA256Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA384Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA3Digest[getAlgorithmName,doFinal];org.bouncycastle.crypto.digests.SHA512Digest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHA512tDigest[getAlgorithmName,getDigestSize,doFinal,reset,copy,reset,getEncodedState,finish];org.bouncycastle.crypto.digests.SHAKEDigest[getAlgorithmName,doFinal,doFinal,doOutput];org.bouncycastle.crypto.digests.SM3Digest[getAlgorithmName,getDigestSize,copy,reset,reset,doFinal,finish];org.bouncycastle.crypto.digests.ShortenedDigest[getAlgorithmName,getDigestSize,update,update,doFinal,reset,getByteLength];org.bouncycastle.crypto.digests.SkeinDigest[reset,copy,getAlgorithmName,getDigestSize,getByteLength,init,reset,update,update,doFinal];org.bouncycastle.crypto.digests.SkeinEngine[copy,reset,getOutputSize,getBlockSize,init,reset,update,update,doFinal];org.bouncycastle.crypto.digests.TigerDigest[getAlgorithmName,getDigestSize,update,update,unpackWord,doFinal,reset,getByteLength,copy,reset];org.bouncycastle.crypto.digests.WhirlpoolDigest[getAlgorithmName,getDigestSize,doFinal,reset,update,update,getByteLength,copy,reset];org.bouncycastle.crypto.ec.CustomNamedCurves[getByName,getByOID,getOID,getName,getNames];org.bouncycastle.crypto.ec.ECElGamalDecryptor[init,decrypt];org.bouncycastle.crypto.ec.ECElGamalEncryptor[init,encrypt];org.bouncycastle.crypto.ec.ECFixedTransform[init,transform,getTransformValue];org.bouncycastle.crypto.ec.ECNewPublicKeyTransform[init,transform];org.bouncycastle.crypto.ec.ECNewRandomnessTransform[init,transform,getTransformValue];org.bouncycastle.crypto.ec.ECPair[getX,getY,equals,equals,hashCode];org.bouncycastle.crypto.encodings.ISO9796d1Encoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,setPadBits,getPadBits,processBlock];org.bouncycastle.crypto.encodings.OAEPEncoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,processBlock,encodeBlock,decodeBlock];org.bouncycastle.crypto.encodings.PKCS1Encoding[getUnderlyingCipher,init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.AESEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.AESFastEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.AESLightEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.ARIAEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.BlowfishEngine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.CAST5Engine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.CAST6Engine[getAlgorithmName,reset,getBlockSize];org.bouncycastle.crypto.engines.CamelliaEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.CamelliaLightEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.ChaCha7539Engine[getAlgorithmName,salsaCore];org.bouncycastle.crypto.engines.ChaChaEngine[getAlgorithmName,chachaCore,salsaCore];org.bouncycastle.crypto.engines.CramerShoupCiphertext[getU1,setU1,getU2,setU2,getE,setE,getV,setV,toString,toByteArray];org.bouncycastle.crypto.engines.CramerShoupCoreEngine[init,init,getInputBlockSize,getOutputBlockSize,convertInput,convertOutput,encryptBlock,decryptBlock];org.bouncycastle.crypto.engines.CryptoProWrapEngine[init];org.bouncycastle.crypto.engines.DESEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DESedeEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DESedeWrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.DSTU7624Engine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.DSTU7624WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.ElGamalEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.GOST28147Engine[init,getAlgorithmName,getBlockSize,processBlock,reset,getSBox,getSBoxName];org.bouncycastle.crypto.engines.GOST28147WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.GOST3412_2015Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.Grain128Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.Grainv1Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.HC128Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.HC256Engine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.IDEAEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.IESEngine[init,init,init,getCipher,getMac,processBlock];org.bouncycastle.crypto.engines.ISAACEngine[init,returnByte,processBytes,getAlgorithmName,reset];org.bouncycastle.crypto.engines.NaccacheSternEngine[init,setDebug,getInputBlockSize,getOutputBlockSize,processBlock,encrypt,addCryptedBlocks,processData];org.bouncycastle.crypto.engines.NoekeonEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.NullEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.OldIESEngine[init,init,init,getCipher,getMac,processBlock];org.bouncycastle.crypto.engines.RC2Engine[init,reset,getAlgorithmName,getBlockSize,processBlock];org.bouncycastle.crypto.engines.RC2WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RC4Engine[init,getAlgorithmName,returnByte,processBytes,reset];org.bouncycastle.crypto.engines.RC532Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RC564Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RC6Engine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.RFC3211WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RFC3394WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RFC5649WrapEngine[init,getAlgorithmName,wrap,unwrap];org.bouncycastle.crypto.engines.RSABlindedEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RSABlindingEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RSAEngine[init,getInputBlockSize,getOutputBlockSize,processBlock];org.bouncycastle.crypto.engines.RijndaelEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.SEEDEngine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.SM2Engine[init,processBlock];org.bouncycastle.crypto.engines.SM4Engine[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.Salsa20Engine[init,getAlgorithmName,returnByte,processBytes,skip,seekTo,getPosition,reset,salsaCore];org.bouncycastle.crypto.engines.SerpentEngineBase[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.engines.Shacal2Engine[reset,getAlgorithmName,getBlockSize,init,setKey,processBlock];org.bouncycastle.crypto.engines.SkipjackEngine[init,getAlgorithmName,getBlockSize,processBlock,reset,encryptBlock,decryptBlock];org.bouncycastle.crypto.engines.TEAEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.engines.ThreefishEngine[init,init,getAlgorithmName,getBlockSize,reset,processBlock,processBlock,bytesToWord,wordToBytes];org.bouncycastle.crypto.engines.TnepresEngine[getAlgorithmName];org.bouncycastle.crypto.engines.TwofishEngine[init,getAlgorithmName,processBlock,reset,getBlockSize];org.bouncycastle.crypto.engines.VMPCEngine[getAlgorithmName,init,processBytes,reset,returnByte];org.bouncycastle.crypto.engines.VMPCKSA3Engine[getAlgorithmName];org.bouncycastle.crypto.engines.XSalsa20Engine[getAlgorithmName,salsaCore];org.bouncycastle.crypto.engines.XTEAEngine[getAlgorithmName,getBlockSize,init,processBlock,reset];org.bouncycastle.crypto.examples.DESExample[main];org.bouncycastle.crypto.examples.JPAKEExample[main];org.bouncycastle.crypto.generators.BCrypt[passwordToByteArray,generate];org.bouncycastle.crypto.generators.BaseKDFBytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.CramerShoupKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.CramerShoupParametersGenerator[init,generateParameters,generateParameters];org.bouncycastle.crypto.generators.DESKeyGenerator[init,generateKey];org.bouncycastle.crypto.generators.DESedeKeyGenerator[init,generateKey];org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DHKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DHParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.DSAKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.DSAParametersGenerator[init,init,generateParameters];org.bouncycastle.crypto.generators.DSTU4145KeyPairGenerator[generateKeyPair];org.bouncycastle.crypto.generators.ECKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.ElGamalKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.ElGamalParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator[generate];org.bouncycastle.crypto.generators.GOST3410KeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.GOST3410ParametersGenerator[init,generateParameters];org.bouncycastle.crypto.generators.HKDFBytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.KDFCounterBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.KDFDoublePipelineIterationBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.KDFFeedbackBytesGenerator[init,getMac,generateBytes];org.bouncycastle.crypto.generators.MGF1BytesGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.generators.NaccacheSternKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.OpenBSDBCrypt[generate,generate,checkPassword];org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator[init,generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS12ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator[generateDerivedParameters,generateDerivedParameters,generateDerivedMacParameters,init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.generators.Poly1305KeyGenerator[init,generateKey,clamp,checkKey];org.bouncycastle.crypto.generators.RSABlindingFactorGenerator[init,generateBlindingFactor];org.bouncycastle.crypto.generators.RSAKeyPairGenerator[init,generateKeyPair];org.bouncycastle.crypto.generators.SCrypt[generate];org.bouncycastle.crypto.io.CipherInputStream[read,read,read,skip,available,close,mark,reset,markSupported];org.bouncycastle.crypto.io.CipherOutputStream[write,write,write,flush,close];org.bouncycastle.crypto.io.DigestInputStream[read,read,getDigest];org.bouncycastle.crypto.io.DigestOutputStream[write,write,getDigest];org.bouncycastle.crypto.io.MacInputStream[read,read,getMac];org.bouncycastle.crypto.io.MacOutputStream[write,write,getMac];org.bouncycastle.crypto.io.SignerInputStream[read,read,getSigner];org.bouncycastle.crypto.io.SignerOutputStream[write,write,getSigner];org.bouncycastle.crypto.kems.ECIESKeyEncapsulation[init,encrypt,encrypt,decrypt,decrypt];org.bouncycastle.crypto.kems.RSAKeyEncapsulation[init,encrypt,encrypt,decrypt,decrypt];org.bouncycastle.crypto.macs.BlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CBCBlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CFBBlockCipherMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.CMac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.DSTU7564Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.DSTU7624Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.GMac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.GOST28147Mac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.HMac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.ISO9797Alg3Mac[getAlgorithmName,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.KGMac[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.OldHMac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.Poly1305[init,getAlgorithmName,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.macs.SipHash[getAlgorithmName,getMacSize,init,update,update,doFinal,doFinal,reset];org.bouncycastle.crypto.macs.SkeinMac[getAlgorithmName,init,getMacSize,reset,update,update,doFinal];org.bouncycastle.crypto.macs.VMPCMac[doFinal,getAlgorithmName,getMacSize,init,reset,update,update];org.bouncycastle.crypto.modes.CBCBlockCipher[getUnderlyingCipher,init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.modes.CCMBlockCipher[getUnderlyingCipher,init,getAlgorithmName,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset,getMac,getUpdateOutputSize,getOutputSize,processPacket,processPacket];org.bouncycastle.crypto.modes.CFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,encryptBlock,decryptBlock,getCurrentIV,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.CTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.EAXBlockCipher[getAlgorithmName,getUnderlyingCipher,getBlockSize,init,reset,processAADByte,processAADBytes,processByte,processBytes,doFinal,getMac,getUpdateOutputSize,getOutputSize];org.bouncycastle.crypto.modes.G3413CBCBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset];org.bouncycastle.crypto.modes.G3413CFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.G3413CTRBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.G3413OFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.GCFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.GCMBlockCipher[getUnderlyingCipher,getAlgorithmName,init,getMac,getOutputSize,getUpdateOutputSize,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.modes.GOFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.KCCMBlockCipher[init,getAlgorithmName,getUnderlyingCipher,processAADByte,processAADBytes,processByte,processBytes,processPacket,doFinal,getMac,getUpdateOutputSize,getOutputSize,reset];org.bouncycastle.crypto.modes.KCTRBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.KGCMBlockCipher[init,getAlgorithmName,getUnderlyingCipher,processAADByte,processAADBytes,processByte,processBytes,doFinal,getMac,getUpdateOutputSize,getOutputSize,reset];org.bouncycastle.crypto.modes.KXTSBlockCipher[getOutputSize,getUpdateOutputSize,init,processByte,processBytes,doFinal,reset,getUnderlyingCipher,getBlockSize];org.bouncycastle.crypto.modes.NISTCTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.OCBBlockCipher[getUnderlyingCipher,getAlgorithmName,init,getMac,getOutputSize,getUpdateOutputSize,processAADByte,processAADBytes,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.modes.OFBBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,getUnderlyingCipher];org.bouncycastle.crypto.modes.OldCTSBlockCipher[getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher[getUnderlyingCipher,getAlgorithmName,getBlockSize,processBlock,reset,init];org.bouncycastle.crypto.modes.PGPCFBBlockCipher[getUnderlyingCipher,getAlgorithmName,getBlockSize,processBlock,reset,init];org.bouncycastle.crypto.modes.PaddedBlockCipher[getOutputSize,getUpdateOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,init,getBlockSize,reset];org.bouncycastle.crypto.modes.SICBlockCipher[init,getAlgorithmName,getBlockSize,processBlock,reset,skip,seekTo,getPosition,getUnderlyingCipher];org.bouncycastle.crypto.modes.gcm.BasicGCMExponentiator[init,exponentiateX];org.bouncycastle.crypto.modes.gcm.BasicGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.GCMUtil[oneAsBytes,oneAsInts,oneAsLongs,asBytes,asBytes,asBytes,asBytes,asInts,asInts,asLongs,asLongs,copy,copy,divideP,multiply,multiply,multiply,multiplyP,multiplyP,multiplyP,multiplyP,multiplyP3,multiplyP4,multiplyP7,multiplyP8,multiplyP8,multiplyP8,multiplyP8,pAsLongs,square,xor,xor,xor,xor,xor,xor,xor,xor,xor,xor];org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator[init,exponentiateX];org.bouncycastle.crypto.modes.gcm.Tables4kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.Tables64kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_128[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_256[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.BasicKGCMMultiplier_512[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_128[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_256[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.KGCMUtil_512[add,copy,equal,multiply,multiplyX,multiplyX8,one,square,x,zero];org.bouncycastle.crypto.modes.kgcm.Tables16kKGCMMultiplier_512[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.Tables4kKGCMMultiplier_128[init,multiplyH];org.bouncycastle.crypto.modes.kgcm.Tables8kKGCMMultiplier_256[init,multiplyH];org.bouncycastle.crypto.paddings.ISO10126d2Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.ISO7816d4Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.PKCS7Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher[init,getOutputSize,getUpdateOutputSize,processByte,processBytes,doFinal,getUnderlyingCipher,getBlockSize,reset];org.bouncycastle.crypto.paddings.TBCPadding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.X923Padding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.paddings.ZeroBytePadding[init,getPaddingName,addPadding,padCount];org.bouncycastle.crypto.params.AEADParameters[getKey,getMacSize,getAssociatedText,getNonce];org.bouncycastle.crypto.params.AsymmetricKeyParameter[isPrivate];org.bouncycastle.crypto.params.CCMParameters[getKey,getMacSize,getAssociatedText,getNonce];org.bouncycastle.crypto.params.CramerShoupKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.CramerShoupKeyParameters[getParameters,equals,hashCode,isPrivate];org.bouncycastle.crypto.params.CramerShoupParameters[equals,hashCode,getG1,getG2,getP,getH];org.bouncycastle.crypto.params.CramerShoupPrivateKeyParameters[getX1,getX2,getY1,getY2,getZ,setPk,getPk,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.CramerShoupPublicKeyParameters[getC,getD,getH,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DESParameters[isWeakKey,setOddParity,getKey];org.bouncycastle.crypto.params.DESedeParameters[isWeakKey,isWeakKey,isRealEDEKey,isReal2Key,isReal3Key,setOddParity,getKey];org.bouncycastle.crypto.params.DHKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.DHKeyParameters[getParameters,equals,hashCode,isPrivate];org.bouncycastle.crypto.params.DHMQVPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHMQVPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHParameters[getP,getG,getQ,getJ,getM,getL,getValidationParameters,equals,hashCode];org.bouncycastle.crypto.params.DHPrivateKeyParameters[getX,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DHPublicKeyParameters[getY,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.DHUPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHUPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.DHValidationParameters[getCounter,getSeed,equals,hashCode];org.bouncycastle.crypto.params.DSAKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.DSAKeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.DSAParameterGenerationParameters[getL,getN,getCertainty,getRandom,getUsageIndex];org.bouncycastle.crypto.params.DSAParameters[getP,getQ,getG,getValidationParameters,equals,hashCode];org.bouncycastle.crypto.params.DSAPrivateKeyParameters[getX,getParameters,isPrivate];org.bouncycastle.crypto.params.DSAPublicKeyParameters[getY,getParameters,isPrivate];org.bouncycastle.crypto.params.DSAValidationParameters[getCounter,getSeed,getUsageIndex,hashCode,equals];org.bouncycastle.crypto.params.ECDHUPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.ECDHUPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.ECDomainParameters[getCurve,getG,getN,getH,getHInv,getSeed,equals,hashCode];org.bouncycastle.crypto.params.ECKeyGenerationParameters[getDomainParameters,getRandom,getStrength];org.bouncycastle.crypto.params.ECKeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.ECNamedDomainParameters[getName,getCurve,getG,getN,getH,getHInv,getSeed,equals,hashCode];org.bouncycastle.crypto.params.ECPrivateKeyParameters[getD,getParameters,isPrivate];org.bouncycastle.crypto.params.ECPublicKeyParameters[getQ,getParameters,isPrivate];org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.ElGamalKeyParameters[getParameters,hashCode,equals,isPrivate];org.bouncycastle.crypto.params.ElGamalParameters[getP,getG,getL,equals,hashCode];org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters[getX,equals,hashCode,getParameters,isPrivate];org.bouncycastle.crypto.params.ElGamalPublicKeyParameters[getY,hashCode,equals,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410KeyGenerationParameters[getParameters,getRandom,getStrength];org.bouncycastle.crypto.params.GOST3410KeyParameters[getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410Parameters[getP,getQ,getA,getValidationParameters,hashCode,equals];org.bouncycastle.crypto.params.GOST3410PrivateKeyParameters[getX,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410PublicKeyParameters[getY,getParameters,isPrivate];org.bouncycastle.crypto.params.GOST3410ValidationParameters[getC,getX0,getCL,getX0L,equals,hashCode];org.bouncycastle.crypto.params.HKDFParameters[skipExtractParameters,defaultParameters,getIKM,skipExtract,getSalt,getInfo];org.bouncycastle.crypto.params.IESParameters[getDerivationV,getEncodingV,getMacKeySize];org.bouncycastle.crypto.params.IESWithCipherParameters[getCipherKeySize,getDerivationV,getEncodingV,getMacKeySize];org.bouncycastle.crypto.params.ISO18033KDFParameters[getSeed];org.bouncycastle.crypto.params.KDFCounterParameters[getKI,getFixedInputData,getFixedInputDataCounterPrefix,getFixedInputDataCounterSuffix,getR];org.bouncycastle.crypto.params.KDFDoublePipelineIterationParameters[createWithCounter,createWithoutCounter,getKI,useCounter,getR,getFixedInputData];org.bouncycastle.crypto.params.KDFFeedbackParameters[createWithCounter,createWithoutCounter,getKI,getIV,useCounter,getR,getFixedInputData];org.bouncycastle.crypto.params.KDFParameters[getSharedSecret,getIV];org.bouncycastle.crypto.params.KeyParameter[getKey];org.bouncycastle.crypto.params.MGFParameters[getSeed];org.bouncycastle.crypto.params.MQVPrivateParameters[getStaticPrivateKey,getEphemeralPrivateKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.MQVPublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.NaccacheSternKeyGenerationParameters[getCertainty,getCntSmallPrimes,isDebug,getRandom,getStrength];org.bouncycastle.crypto.params.NaccacheSternKeyParameters[getG,getLowerSigmaBound,getModulus,isPrivate];org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters[getPhi_n,getSmallPrimes,getG,getLowerSigmaBound,getModulus,isPrivate];org.bouncycastle.crypto.params.ParametersWithID[getID,getParameters];org.bouncycastle.crypto.params.ParametersWithIV[getIV,getParameters];org.bouncycastle.crypto.params.ParametersWithRandom[getRandom,getParameters];org.bouncycastle.crypto.params.ParametersWithSBox[getSBox,getParameters];org.bouncycastle.crypto.params.ParametersWithSalt[getSalt,getParameters];org.bouncycastle.crypto.params.ParametersWithUKM[getUKM,getParameters];org.bouncycastle.crypto.params.RC2Parameters[getEffectiveKeyBits,getKey];org.bouncycastle.crypto.params.RC5Parameters[getKey,getRounds];org.bouncycastle.crypto.params.RSABlindingParameters[getPublicKey,getBlindingFactor];org.bouncycastle.crypto.params.RSAKeyGenerationParameters[getPublicExponent,getCertainty,getRandom,getStrength];org.bouncycastle.crypto.params.RSAKeyParameters[getModulus,getExponent,isPrivate];org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters[getPublicExponent,getP,getQ,getDP,getDQ,getQInv,getModulus,getExponent,isPrivate];org.bouncycastle.crypto.params.SM2KeyExchangePrivateParameters[isInitiator,getStaticPrivateKey,getStaticPublicPoint,getEphemeralPrivateKey,getEphemeralPublicPoint];org.bouncycastle.crypto.params.SM2KeyExchangePublicParameters[getStaticPublicKey,getEphemeralPublicKey];org.bouncycastle.crypto.params.SRP6GroupParameters[getG,getN];org.bouncycastle.crypto.params.SkeinParameters[getParameters,getKey,getPersonalisation,getPublicKey,getKeyIdentifier,getNonce];org.bouncycastle.crypto.params.TweakableBlockCipherParameters[getKey,getTweak];org.bouncycastle.crypto.parsers.DHIESPublicKeyParser[readKey];org.bouncycastle.crypto.parsers.ECIESPublicKeyParser[readKey];org.bouncycastle.crypto.prng.BasicEntropySourceProvider[get];org.bouncycastle.crypto.prng.DigestRandomGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.EntropyUtil[generateSeed];org.bouncycastle.crypto.prng.FixedSecureRandom[nextBytes,generateSeed,nextInt,nextLong,isExhausted];org.bouncycastle.crypto.prng.ReversedWindowGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.SP800SecureRandom[setSeed,setSeed,nextBytes,generateSeed,reseed];org.bouncycastle.crypto.prng.SP800SecureRandomBuilder[setPersonalizationString,setSecurityStrength,setEntropyBitsRequired,buildHash,buildCTR,buildHMAC];org.bouncycastle.crypto.prng.ThreadedSeedGenerator[generateSeed];org.bouncycastle.crypto.prng.VMPCRandomGenerator[addSeedMaterial,addSeedMaterial,nextBytes,nextBytes];org.bouncycastle.crypto.prng.X931SecureRandom[setSeed,setSeed,nextBytes,generateSeed];org.bouncycastle.crypto.prng.X931SecureRandomBuilder[setDateTimeVector,build];org.bouncycastle.crypto.prng.drbg.CTRSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.DualECPoints[getSeedLen,getMaxOutlen,getP,getQ,getSecurityStrength,getCofactor];org.bouncycastle.crypto.prng.drbg.DualECSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.HMacSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.prng.drbg.HashSP800DRBG[getBlockSize,generate,reseed];org.bouncycastle.crypto.signers.DSADigestSigner[init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.DSASigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.DSTU4145Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECDSASigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECGOST3410Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECGOST3410_2012Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.ECNRSigner[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.GOST3410Signer[init,generateSignature,verifySignature];org.bouncycastle.crypto.signers.GenericSigner[init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.HMacDSAKCalculator[isDeterministic,init,init,nextK];org.bouncycastle.crypto.signers.ISO9796d2PSSSigner[init,updateWithRecoveredMessage,update,update,reset,generateSignature,verifySignature,hasFullMessage,getRecoveredMessage];org.bouncycastle.crypto.signers.ISO9796d2Signer[init,updateWithRecoveredMessage,update,update,reset,generateSignature,verifySignature,hasFullMessage,getRecoveredMessage];org.bouncycastle.crypto.signers.ISOTrailers[getTrailer,noTrailerAvailable];org.bouncycastle.crypto.signers.PSSSigner[init,update,update,reset,generateSignature,verifySignature];org.bouncycastle.crypto.signers.RSADigestSigner[getAlgorithmName,init,update,update,generateSignature,verifySignature,reset];org.bouncycastle.crypto.signers.RandomDSAKCalculator[isDeterministic,init,init,nextK];org.bouncycastle.crypto.signers.SM2Signer[init,update,update,verifySignature,reset,generateSignature];org.bouncycastle.crypto.signers.X931Signer[init,update,update,reset,generateSignature,verifySignature];org.bouncycastle.crypto.tls.AbstractTlsCipherFactory[createCipher];org.bouncycastle.crypto.tls.AbstractTlsClient[init,getSessionToResume,getClientHelloRecordLayerVersion,getClientVersion,isFallback,getClientExtensions,getMinimumVersion,notifyServerVersion,getCompressionMethods,notifySessionID,notifySelectedCipherSuite,notifySelectedCompressionMethod,processServerExtensions,processServerSupplementalData,getClientSupplementalData,getCompression,getCipher,notifyNewSessionTicket];org.bouncycastle.crypto.tls.AbstractTlsKeyExchange[init,processServerCertificate,processServerCredentials,requiresServerKeyExchange,generateServerKeyExchange,skipServerKeyExchange,processServerKeyExchange,skipClientCredentials,processClientCertificate,processClientKeyExchange];org.bouncycastle.crypto.tls.AbstractTlsPeer[shouldUseGMTUnixTime,notifySecureRenegotiation,notifyAlertRaised,notifyAlertReceived,notifyHandshakeComplete];org.bouncycastle.crypto.tls.AbstractTlsServer[init,notifyClientVersion,notifyFallback,notifyOfferedCipherSuites,notifyOfferedCompressionMethods,processClientExtensions,getServerVersion,getSelectedCipherSuite,getSelectedCompressionMethod,getServerExtensions,getServerSupplementalData,getCertificateStatus,getCertificateRequest,processClientSupplementalData,notifyClientCertificate,getCompression,getCipher,getNewSessionTicket];org.bouncycastle.crypto.tls.AbstractTlsSigner[init,generateRawSignature,verifyRawSignature,createSigner,createVerifyer];org.bouncycastle.crypto.tls.AbstractTlsSignerCredentials[getSignatureAndHashAlgorithm];org.bouncycastle.crypto.tls.AlertDescription[getName,getText];org.bouncycastle.crypto.tls.AlertLevel[getName,getText];org.bouncycastle.crypto.tls.BasicTlsPSKIdentity[skipIdentityHint,notifyIdentityHint,getPSKIdentity,getPSK];org.bouncycastle.crypto.tls.ByteQueue[nextTwoPow,addData,available,copyTo,read,readFrom,removeData,removeData,removeData,shrink];org.bouncycastle.crypto.tls.ByteQueueInputStream[addBytes,peek,read,read,read,skip,available,close];org.bouncycastle.crypto.tls.ByteQueueOutputStream[getBuffer,write,write];org.bouncycastle.crypto.tls.CertChainType[isValid];org.bouncycastle.crypto.tls.Certificate[getCertificateList,getCertificateAt,getLength,isEmpty,encode,parse];org.bouncycastle.crypto.tls.CertificateRequest[getCertificateTypes,getSupportedSignatureAlgorithms,getCertificateAuthorities,encode,parse];org.bouncycastle.crypto.tls.CertificateStatus[getStatusType,getResponse,getOCSPResponse,encode,parse];org.bouncycastle.crypto.tls.CertificateStatusRequest[getStatusType,getRequest,getOCSPStatusRequest,encode,parse];org.bouncycastle.crypto.tls.CertificateURL[getType,getURLAndHashList,encode,parse];org.bouncycastle.crypto.tls.Chacha20Poly1305[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.CipherSuite[isSCSV];org.bouncycastle.crypto.tls.DTLSClientProtocol[connect];org.bouncycastle.crypto.tls.DTLSServerProtocol[getVerifyRequests,setVerifyRequests,accept];org.bouncycastle.crypto.tls.DTLSTransport[getReceiveLimit,getSendLimit,receive,send,close];org.bouncycastle.crypto.tls.DefaultTlsAgreementCredentials[getCertificate,generateAgreement];org.bouncycastle.crypto.tls.DefaultTlsCipherFactory[createCipher];org.bouncycastle.crypto.tls.DefaultTlsClient[getCipherSuites,getKeyExchange,getMinimumVersion];org.bouncycastle.crypto.tls.DefaultTlsEncryptionCredentials[getCertificate,decryptPreMasterSecret];org.bouncycastle.crypto.tls.DefaultTlsSRPGroupVerifier[accept];org.bouncycastle.crypto.tls.DefaultTlsServer[getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.DefaultTlsSignerCredentials[getCertificate,generateCertificateSignature,getSignatureAndHashAlgorithm];org.bouncycastle.crypto.tls.DigitallySigned[getAlgorithm,getSignature,encode,parse];org.bouncycastle.crypto.tls.ECBasisType[isValid];org.bouncycastle.crypto.tls.FiniteFieldDHEGroup[isValid];org.bouncycastle.crypto.tls.HashAlgorithm[getName,getText,isPrivate];org.bouncycastle.crypto.tls.HeartbeatExtension[getMode,encode,parse];org.bouncycastle.crypto.tls.HeartbeatMessage[encode,parse];org.bouncycastle.crypto.tls.HeartbeatMessageType[isValid];org.bouncycastle.crypto.tls.HeartbeatMode[isValid];org.bouncycastle.crypto.tls.MaxFragmentLength[isValid];org.bouncycastle.crypto.tls.NameType[isValid];org.bouncycastle.crypto.tls.NamedCurve[isValid,refersToASpecificNamedCurve];org.bouncycastle.crypto.tls.NewSessionTicket[getTicketLifetimeHint,getTicket,encode,parse];org.bouncycastle.crypto.tls.OCSPStatusRequest[getResponderIDList,getRequestExtensions,encode,parse];org.bouncycastle.crypto.tls.PSKTlsClient[getCipherSuites,getKeyExchange,getAuthentication,getMinimumVersion];org.bouncycastle.crypto.tls.PSKTlsServer[getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.ProtocolVersion[getFullVersion,getMajorVersion,getMinorVersion,isDTLS,isSSL,isTLS,getEquivalentTLSVersion,isEqualOrEarlierVersionOf,isLaterVersionOf,equals,equals,hashCode,get,toString];org.bouncycastle.crypto.tls.SRPTlsClient[getCipherSuites,getClientExtensions,processServerExtensions,getKeyExchange,getAuthentication,getMinimumVersion];org.bouncycastle.crypto.tls.SRPTlsServer[processClientExtensions,getSelectedCipherSuite,getCredentials,getKeyExchange];org.bouncycastle.crypto.tls.SSL3Mac[getAlgorithmName,getUnderlyingDigest,init,getMacSize,update,update,doFinal,reset];org.bouncycastle.crypto.tls.SecurityParameters[getEntity,getCipherSuite,getCompressionAlgorithm,getPrfAlgorithm,getVerifyDataLength,getMasterSecret,getClientRandom,getServerRandom,getSessionHash,getPskIdentity,getPSKIdentity,getSRPIdentity];org.bouncycastle.crypto.tls.ServerDHParams[getPublicKey,encode,parse];org.bouncycastle.crypto.tls.ServerName[getNameType,getName,getHostName,encode,parse];org.bouncycastle.crypto.tls.ServerNameList[getServerNameList,encode,parse];org.bouncycastle.crypto.tls.ServerOnlyTlsAuthentication[getClientCredentials];org.bouncycastle.crypto.tls.ServerSRPParams[getB,getG,getN,getS,encode,parse];org.bouncycastle.crypto.tls.SessionParameters[clear,copy,getCipherSuite,getCompressionAlgorithm,getMasterSecret,getPeerCertificate,getPskIdentity,getPSKIdentity,getSRPIdentity,readServerExtensions];org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm[getHash,getSignature,equals,hashCode,encode,parse];org.bouncycastle.crypto.tls.SimulatedTlsSRPIdentityManager[getRFC5054Default,getLoginParameters];org.bouncycastle.crypto.tls.SupplementalDataEntry[getDataType,getData];org.bouncycastle.crypto.tls.TlsAEADCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsBlockCipher[getWriteMac,getReadMac,getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsClientProtocol[connect,getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsDHEKeyExchange[processServerCredentials,generateServerKeyExchange,processServerKeyExchange];org.bouncycastle.crypto.tls.TlsDHKeyExchange[init,skipServerCredentials,processServerCertificate,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientCertificate,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsDHUtils[addNegotiatedDHEGroupsClientExtension,addNegotiatedDHEGroupsServerExtension,getNegotiatedDHEGroupsClientExtension,getNegotiatedDHEGroupsServerExtension,createNegotiatedDHEGroupsClientExtension,createNegotiatedDHEGroupsServerExtension,readNegotiatedDHEGroupsClientExtension,readNegotiatedDHEGroupsServerExtension,getParametersForDHEGroup,containsDHECipherSuites,isDHECipherSuite,areCompatibleParameters,calculateDHBasicAgreement,generateDHKeyPair,generateEphemeralClientKeyExchange,generateEphemeralServerKeyExchange,validateDHParameters,validateDHPublicKey,readDHParameter,writeDHParameter];org.bouncycastle.crypto.tls.TlsDSASigner[generateRawSignature,verifyRawSignature,createSigner,createVerifyer];org.bouncycastle.crypto.tls.TlsDSSSigner[isValidPublicKey];org.bouncycastle.crypto.tls.TlsECCUtils[addSupportedEllipticCurvesExtension,addSupportedPointFormatsExtension,getSupportedEllipticCurvesExtension,getSupportedPointFormatsExtension,createSupportedEllipticCurvesExtension,createSupportedPointFormatsExtension,readSupportedEllipticCurvesExtension,readSupportedPointFormatsExtension,getNameOfNamedCurve,getParametersForNamedCurve,hasAnySupportedNamedCurves,containsECCCipherSuites,isECCCipherSuite,areOnSameCurve,isSupportedNamedCurve,isCompressionPreferred,serializeECFieldElement,serializeECPoint,serializeECPublicKey,deserializeECFieldElement,deserializeECPoint,deserializeECPublicKey,calculateECDHBasicAgreement,generateECKeyPair,generateEphemeralClientKeyExchange,validateECPublicKey,readECExponent,readECFieldElement,readECParameter,readECParameters,writeECExponent,writeECFieldElement,writeECFieldElement,writeECParameter,writeExplicitECParameters,writeECPoint,writeNamedECParameters];org.bouncycastle.crypto.tls.TlsECDHEKeyExchange[processServerCredentials,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials];org.bouncycastle.crypto.tls.TlsECDHKeyExchange[init,skipServerCredentials,processServerCertificate,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientCertificate,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsECDSASigner[isValidPublicKey];org.bouncycastle.crypto.tls.TlsExtensionsUtils[ensureExtensionsInitialised,addEncryptThenMACExtension,addExtendedMasterSecretExtension,addHeartbeatExtension,addMaxFragmentLengthExtension,addPaddingExtension,addServerNameExtension,addStatusRequestExtension,addTruncatedHMacExtension,getHeartbeatExtension,getMaxFragmentLengthExtension,getPaddingExtension,getServerNameExtension,getStatusRequestExtension,hasEncryptThenMACExtension,hasExtendedMasterSecretExtension,hasTruncatedHMacExtension,createEmptyExtensionData,createEncryptThenMACExtension,createExtendedMasterSecretExtension,createHeartbeatExtension,createMaxFragmentLengthExtension,createPaddingExtension,createServerNameExtension,createStatusRequestExtension,createTruncatedHMacExtension,readEncryptThenMACExtension,readExtendedMasterSecretExtension,readHeartbeatExtension,readMaxFragmentLengthExtension,readPaddingExtension,readServerNameExtension,readStatusRequestExtension,readTruncatedHMacExtension];org.bouncycastle.crypto.tls.TlsFatalAlert[getAlertDescription,getCause];org.bouncycastle.crypto.tls.TlsFatalAlertReceived[getAlertDescription,getCause];org.bouncycastle.crypto.tls.TlsMac[getMACSecret,getSize,calculateMac,calculateMacConstantTime];org.bouncycastle.crypto.tls.TlsNullCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsNullCompression[compress,decompress];org.bouncycastle.crypto.tls.TlsPSKKeyExchange[skipServerCredentials,processServerCredentials,generateServerKeyExchange,processServerCertificate,requiresServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsProtocol[getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsRSAKeyExchange[skipServerCredentials,processServerCredentials,processServerCertificate,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsRSASigner[generateRawSignature,verifyRawSignature,createSigner,createVerifyer,isValidPublicKey];org.bouncycastle.crypto.tls.TlsRSAUtils[generateEncryptedPreMasterSecret,safeDecryptPreMasterSecret];org.bouncycastle.crypto.tls.TlsSRPKeyExchange[init,skipServerCredentials,processServerCertificate,processServerCredentials,requiresServerKeyExchange,generateServerKeyExchange,processServerKeyExchange,validateCertificateRequest,processClientCredentials,generateClientKeyExchange,processClientKeyExchange,generatePremasterSecret];org.bouncycastle.crypto.tls.TlsSRPLoginParameters[getGroup,getSalt,getVerifier];org.bouncycastle.crypto.tls.TlsSRPUtils[addSRPExtension,getSRPExtension,createSRPExtension,readSRPExtension,readSRPParameter,writeSRPParameter,isSRPCipherSuite];org.bouncycastle.crypto.tls.TlsSRTPUtils[addUseSRTPExtension,getUseSRTPExtension,createUseSRTPExtension,readUseSRTPExtension];org.bouncycastle.crypto.tls.TlsServerProtocol[accept,getOutputStream,getInputStream,closeInput,offerInput,getAvailableInputBytes,readInput,offerOutput,getAvailableOutputBytes,readOutput,close,isClosed];org.bouncycastle.crypto.tls.TlsStreamCipher[getPlaintextLimit,encodePlaintext,decodeCiphertext];org.bouncycastle.crypto.tls.TlsUtils[checkUint8,checkUint8,checkUint8,checkUint16,checkUint16,checkUint24,checkUint24,checkUint32,checkUint48,checkUint64,isValidUint8,isValidUint8,isValidUint8,isValidUint16,isValidUint16,isValidUint24,isValidUint24,isValidUint32,isValidUint48,isValidUint64,isSSL,isTLSv11,isTLSv11,isTLSv12,isTLSv12,writeUint8,writeUint8,writeUint8,writeUint8,writeUint16,writeUint16,writeUint24,writeUint24,writeUint32,writeUint32,writeUint48,writeUint48,writeUint64,writeUint64,writeOpaque8,writeOpaque16,writeOpaque24,writeUint8Array,writeUint8Array,writeUint8ArrayWithUint8Length,writeUint8ArrayWithUint8Length,writeUint16Array,writeUint16Array,writeUint16ArrayWithUint16Length,writeUint16ArrayWithUint16Length,encodeOpaque8,encodeUint8ArrayWithUint8Length,encodeUint16ArrayWithUint16Length,readUint8,readUint8,readUint16,readUint16,readUint24,readUint24,readUint32,readUint32,readUint48,readUint48,readAllOrNothing,readFully,readFully,readOpaque8,readOpaque16,readOpaque24,readUint8Array,readUint16Array,readVersion,readVersion,readVersionRaw,readVersionRaw,readASN1Object,readDERObject,writeGMTUnixTime,writeVersion,writeVersion,getAllSignatureAlgorithms,getDefaultDSSSignatureAlgorithms,getDefaultECDSASignatureAlgorithms,getDefaultRSASignatureAlgorithms,getDefaultSupportedSignatureAlgorithms,getSignatureAndHashAlgorithm,getExtensionData,hasExpectedEmptyExtensionData,importSession,isSignatureAlgorithmsExtensionAllowed,addSignatureAlgorithmsExtension,getSignatureAlgorithmsExtension,createSignatureAlgorithmsExtension,readSignatureAlgorithmsExtension,encodeSupportedSignatureAlgorithms,parseSupportedSignatureAlgorithms,verifySupportedSignatureAlgorithm,PRF,PRF_legacy,createHash,createHash,cloneHash,createPRFHash,clonePRFHash,getHashAlgorithmForPRFAlgorithm,getOIDForHashAlgorithm,hasSigningCapability,createTlsSigner,getCipherType,getEncryptionAlgorithm,getKeyExchangeAlgorithm,getMACAlgorithm,getMinimumVersion,isAEADCipherSuite,isBlockCipherSuite,isStreamCipherSuite,isValidCipherSuiteForSignatureAlgorithms,isValidCipherSuiteForVersion,getUsableSignatureAlgorithms];org.bouncycastle.crypto.tls.UDPTransport[getReceiveLimit,getSendLimit,receive,send,close];org.bouncycastle.crypto.tls.URLAndHash[getURL,getSHA1Hash,encode,parse];org.bouncycastle.crypto.tls.UseSRTPData[getProtectionProfiles,getMki];org.bouncycastle.crypto.util.DERMacData[getMacData];org.bouncycastle.crypto.util.DEROtherInfo[getEncoded];org.bouncycastle.crypto.util.DigestFactory[createMD5,createSHA1,createSHA224,createSHA256,createSHA384,createSHA512,createSHA512_224,createSHA512_256,createSHA3_224,createSHA3_256,createSHA3_384,createSHA3_512];org.bouncycastle.crypto.util.PBKDF2Config[getIterationCount,getPRF,getSaltLength,getAlgorithm];org.bouncycastle.crypto.util.PBKDFConfig[getAlgorithm];org.bouncycastle.crypto.util.Pack[bigEndianToInt,bigEndianToInt,intToBigEndian,intToBigEndian,intToBigEndian,intToBigEndian,bigEndianToLong,bigEndianToLong,longToBigEndian,longToBigEndian,longToBigEndian,longToBigEndian,littleEndianToInt,littleEndianToInt,littleEndianToInt,intToLittleEndian,intToLittleEndian,intToLittleEndian,intToLittleEndian,littleEndianToLong,littleEndianToLong,longToLittleEndian,longToLittleEndian,longToLittleEndian,longToLittleEndian];org.bouncycastle.crypto.util.PrivateKeyFactory[createKey,createKey,createKey];org.bouncycastle.crypto.util.PrivateKeyInfoFactory[createPrivateKeyInfo];org.bouncycastle.crypto.util.PublicKeyFactory[createKey,createKey,createKey,createKey];org.bouncycastle.crypto.util.ScryptConfig[getCostParameter,getBlockSize,getParallelizationParameter,getSaltLength,getAlgorithm];org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory[createSubjectPublicKeyInfo]" - setup: - def traceConfigInstrumentation - - when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) - - then: - traceConfigInstrumentation.classMethodsToTrace.size() == 471 - } - - def "test list invalid method list"() { - final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey];org.bouncycastle.crypto.agreement.srp.SRP6Server[];org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];" - setup: - def traceConfigInstrumentation - - when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) - - then: - traceConfigInstrumentation.classMethodsToTrace.size() == 0 - } - - def "test list invalid separation"() { - final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.BufferedBlockCipher[getUnderlyingCipher,init,getBlockSize,getUpdateOutputSize,getOutputSize,processByte,processBytes,doFinal,reset];org.bouncycastle.crypto.CipherKeyGenerator[init,generateKey];org.bouncycastle.crypto.Commitment[getSecret,getCommitment];org.bouncycastle.crypto.CryptoServicesPermission[implies,equals,hashCode,getActions];org.bouncycastle.crypto.CryptoServicesRegistrar[getSecureRandom,setSecureRandom,getProperty,getSizedProperty,getSizedProperty,setThreadProperty,setGlobalProperty,clearGlobalProperty,clearThreadProperty];org.bouncycastle.crypto.EphemeralKeyPair[getKeyPair,getEncodedPublicKey];org.bouncycastle.crypto.KeyGenerationParameters[getRandom,getStrength];org.bouncycastle.crypto.PBEParametersGenerator[init,getPassword,getSalt,getIterationCount,PKCS5PasswordToBytes,PKCS5PasswordToUTF8Bytes,PKCS12PasswordToBytes];org.bouncycastle.crypto.PasswordConverter[values,valueOf];org.bouncycastle.crypto.StreamBlockCipher[getUnderlyingCipher,returnByte,processBytes];org.bouncycastle.crypto.agreement.DHAgreement[init,calculateMessage,calculateAgreement];org.bouncycastle.crypto.agreement.DHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.DHUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECMQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.ECVKOAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.MQVBasicAgreement[init,getFieldSize,calculateAgreement];org.bouncycastle.crypto.agreement.SM2KeyExchange[init,calculateKey,calculateKeyWithConfirmation];org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant[getState,createRound1PayloadToSend,validateRound1PayloadReceived,createRound2PayloadToSend,validateRound2PayloadReceived,calculateKeyingMaterial,createRound3PayloadToSend,validateRound3PayloadReceived];org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup[getP,getQ,getG];org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload[getParticipantId,getGx1,getGx2,getKnowledgeProofForX1,getKnowledgeProofForX2];org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload[getParticipantId,getA,getKnowledgeProofForX2s];org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload[getParticipantId,getMacTag];org.bouncycastle.crypto.agreement.jpake.JPAKEUtil[generateX1,generateX2,calculateS,calculateGx,calculateGA,calculateX2s,calculateA,calculateZeroKnowledgeProof,validateGx4,validateGa,validateZeroKnowledgeProof,calculateKeyingMaterial,validateParticipantIdsDiffer,validateParticipantIdsEqual,validateNotNull,calculateMacTag,validateMacTag];org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.DHKDFParameters[getAlgorithm,getKeySize,getZ,getExtraInfo];org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator[init,getDigest,generateBytes];org.bouncycastle.crypto.agreement.kdf.GSKKDFParameters[getZ,getStartCounter,getNonce];org.bouncycastle.crypto.agreement.kdf.GSKKFDGenerator[getDigest,init,generateBytes];org.bouncycastle.crypto.agreement.srp.SRP6Client[init,init,generateClientCredentials,calculateSecret,calculateClientEvidenceMessage,verifyServerEvidenceMessage,calculateSessionKey]org.bouncycastle.crypto.agreement.srp.SRP6Util[calculateK,calculateU,calculateX,generatePrivateValue,validatePublicValue,calculateM1,calculateM2,calculateKey];" - setup: - def traceConfigInstrumentation - - when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) - - then: - traceConfigInstrumentation.classMethodsToTrace.size() == 0 - } - - def "test list invalid class"() { - final interestingClasses = "orgbouncycastlecrypto@3AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset];" - setup: - def traceConfigInstrumentation - - when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) - - then: - traceConfigInstrumentation.classMethodsToTrace.size() == 0 - } - - def "test list without trailing semi-colon"() { - final interestingClasses = "org.bouncycastle.crypto.AsymmetricCipherKeyPair[getPublic,getPrivate];org.bouncycastle.crypto.BufferedAsymmetricBlockCipher[getUnderlyingCipher,getBufferPosition,init,getInputBlockSize,getOutputBlockSize,processByte,processBytes,doFinal,reset]" - setup: - def traceConfigInstrumentation - - when: - traceConfigInstrumentation = new TraceConfigInstrumentation(interestingClasses) - - then: - traceConfigInstrumentation.classMethodsToTrace.size() == 2 - } -} From db485d10da748aae90c974c60dfe3f9839767e9d Mon Sep 17 00:00:00 2001 From: Blinkingor Date: Tue, 28 Jan 2020 16:20:02 +0100 Subject: [PATCH 31/37] final configString --- .../trace_annotation/TraceConfigInstrumentation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java index d798482ac6..af8d393a73 100644 --- a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java +++ b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java @@ -56,7 +56,7 @@ public class TraceConfigInstrumentation implements Instrumenter { } public TraceConfigInstrumentation() { - String configString = Config.get().getTraceMethods(); + final String configString = Config.get().getTraceMethods(); if (configString == null || configString.trim().isEmpty()) { classMethodsToTrace = Collections.emptyMap(); From 8d831721288be231c7b3f25b4ec96614c57947f1 Mon Sep 17 00:00:00 2001 From: Blinkingor <30591503+Blikingor@users.noreply.github.com> Date: Wed, 29 Jan 2020 18:41:29 +0100 Subject: [PATCH 32/37] clazz -> segment rename --- .../trace_annotation/TraceConfigInstrumentation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java index af8d393a73..5be4930288 100644 --- a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java +++ b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceConfigInstrumentation.java @@ -47,8 +47,8 @@ public class TraceConfigInstrumentation implements Instrumenter { private final Map> classMethodsToTrace; private boolean validateConfigString(String configString) { - for (String clazz : configString.split(";")) { - if (!clazz.trim().matches(CONFIG_FORMAT)) { + for (String segment : configString.split(";")) { + if (!segment.trim().matches(CONFIG_FORMAT)) { return false; } } From 0f095f0adbafb52b745f439de6fc1f9ce1864e0e Mon Sep 17 00:00:00 2001 From: dougqh Date: Thu, 30 Jan 2020 17:44:24 -0500 Subject: [PATCH 33/37] Final clean-up - Removed unused method from earlier version - Corrected previously overlooked comments that were remnant of prior version --- .../agent/tooling/DDCachingPoolStrategy.java | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java index 7f3d3f7e83..cc5165dfa8 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java @@ -22,22 +22,15 @@ import net.bytebuddy.pool.TypePool; * *
    * There two core parts to the cache... - *
  • a cache of ID assignments for ClassLoaders - *
  • a single cache of TypeResolutions for all ClassLoaders - keyed by a custom composite key - * that combines loader ID & name + *
  • a cache of ClassLoader to WeakReference<ClassLoader> + *
  • a single cache of TypeResolutions for all ClassLoaders - keyed by a custom composite key of ClassLoader & class name *
* *

This design was chosen to create a single limited size cache that can be adjusted for the * entire application -- without having to create a large number of WeakReference objects. * - *

The ID assignment mostly assigns a single ID to each ClassLoader, but the maximumSize - * restriction means that an evicted ClassLoader could be assigned another ID later on. - * - *

For the validity of the cache, the important part is that ID assignment guarantees that no two - * ClassLoaders share the same ID. - * - *

NOTE: As an additional safe-guard, a new CacheInstance can be created if the original loader - * ID sequence is exhausted. + *

Eviction is handled almost entirely through a size restriction; however, + * softValues are still used as a further safeguard. */ @Slf4j public class DDCachingPoolStrategy implements PoolStrategy { @@ -99,11 +92,6 @@ public class DDCachingPoolStrategy implements PoolStrategy { return createCachingTypePool(loaderHash, loaderRef, classFileLocator); } - private final TypePool createNonCachingTypePool(final ClassFileLocator classFileLocator) { - return new TypePool.Default.WithLazyResolution( - TypePool.CacheProvider.NoOp.INSTANCE, classFileLocator, TypePool.Default.ReaderMode.FAST); - } - private final TypePool.CacheProvider createCacheProvider( final int loaderHash, final WeakReference loaderRef) { return new SharedResolutionCacheAdapter(loaderHash, loaderRef, sharedResolutionCache); @@ -130,8 +118,13 @@ public class DDCachingPoolStrategy implements PoolStrategy { } /** - * TypeCacheKey is key for the sharedResolutionCache. It is a mix of a cacheId/loaderId & a type - * name. + * TypeCacheKey is key for the sharedResolutionCache. + * Conceptually, it is a mix of ClassLoader & class name. + * + * For efficiency & GC purposes, it is actually composed of + * loaderHash & WeakReference<ClassLoader> + * + * The loaderHash exists to avoid calling get & strengthening the Reference. */ static final class TypeCacheKey { private final int loaderHash; @@ -169,11 +162,15 @@ public class DDCachingPoolStrategy implements PoolStrategy { return className.equals(that.className); } else if (className.equals(that.className)) { // need to perform a deeper loader check -- requires calling Reference.get - // which can strengthened the Reference, so deliberately done last + // which can strengthen the Reference, so deliberately done last // If either reference has gone null, they aren't considered equivalent // Technically, this is a bit of violation of equals semantics, since - // two equivalent references can be not equivalent. + // two equivalent references can become not equivalent. + + // In this case, it is fine because that means the ClassLoader is no + // longer live, so the entries will never match anyway and will fall + // out of the cache. ClassLoader thisLoader = loaderRef.get(); if (thisLoader == null) return false; From 235a6470fb0afd7bd317179644e66294cfd825fc Mon Sep 17 00:00:00 2001 From: dougqh Date: Thu, 30 Jan 2020 17:45:40 -0500 Subject: [PATCH 34/37] googleJavaFormat --- .../agent/tooling/DDCachingPoolStrategy.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java index cc5165dfa8..1d4cccdb35 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDCachingPoolStrategy.java @@ -23,14 +23,15 @@ import net.bytebuddy.pool.TypePool; *

    * There two core parts to the cache... *
  • a cache of ClassLoader to WeakReference<ClassLoader> - *
  • a single cache of TypeResolutions for all ClassLoaders - keyed by a custom composite key of ClassLoader & class name + *
  • a single cache of TypeResolutions for all ClassLoaders - keyed by a custom composite key of + * ClassLoader & class name *
* *

This design was chosen to create a single limited size cache that can be adjusted for the * entire application -- without having to create a large number of WeakReference objects. * - *

Eviction is handled almost entirely through a size restriction; however, - * softValues are still used as a further safeguard. + *

Eviction is handled almost entirely through a size restriction; however, softValues are still + * used as a further safeguard. */ @Slf4j public class DDCachingPoolStrategy implements PoolStrategy { @@ -118,13 +119,13 @@ public class DDCachingPoolStrategy implements PoolStrategy { } /** - * TypeCacheKey is key for the sharedResolutionCache. - * Conceptually, it is a mix of ClassLoader & class name. + * TypeCacheKey is key for the sharedResolutionCache. Conceptually, it is a mix of ClassLoader & + * class name. * - * For efficiency & GC purposes, it is actually composed of - * loaderHash & WeakReference<ClassLoader> + *

For efficiency & GC purposes, it is actually composed of loaderHash & + * WeakReference<ClassLoader> * - * The loaderHash exists to avoid calling get & strengthening the Reference. + *

The loaderHash exists to avoid calling get & strengthening the Reference. */ static final class TypeCacheKey { private final int loaderHash; From faeb0694240c564e272abe1a6fb7021cf1887b7f Mon Sep 17 00:00:00 2001 From: dougqh Date: Thu, 30 Jan 2020 18:08:49 -0500 Subject: [PATCH 35/37] Adjusting capacity check again --- .../datadog/trace/agent/tooling/CacheProviderTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy index 111763d098..73d0a1fe19 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/CacheProviderTest.groovy @@ -185,7 +185,7 @@ class CacheProviderTest extends DDSpecification { then: // cache will start to proactively free slots & size calc is approximate - poolStrat.approximateSize() > 0.9 * capacity + poolStrat.approximateSize() > 0.8 * capacity when: 10.times { @@ -196,7 +196,7 @@ class CacheProviderTest extends DDSpecification { then: // cache will start to proactively free slots & size calc is approximate - poolStrat.approximateSize() > 0.9 * capacity + poolStrat.approximateSize() > 0.8 * capacity } static newVoid() { From daae198b0863c1176c96231d19dd714f0147c61b Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Thu, 30 Jan 2020 21:53:28 -0500 Subject: [PATCH 36/37] Set dispatcher span on request instead of clear Clearing the span caused traces to be broken up and reported independently when calling forward/include. --- .../RequestDispatcherInstrumentation.java | 13 +++-- .../test/groovy/RequestDispatcherTest.groovy | 54 +++++++++++++++++-- .../test/groovy/RequestDispatcherUtils.java | 23 +++++++- 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java index 86ddbd3c69..3048b700d8 100644 --- a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java +++ b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java @@ -71,6 +71,7 @@ public final class RequestDispatcherInstrumentation extends Instrumenter.Default public static AgentScope start( @Advice.Origin("#m") final String method, @Advice.This final RequestDispatcher dispatcher, + @Advice.Local("_requestSpan") Object requestSpan, @Advice.Argument(0) final ServletRequest request) { if (activeSpan() == null) { // Don't want to generate a new top-level span @@ -87,8 +88,9 @@ public final class RequestDispatcherInstrumentation extends Instrumenter.Default // In case we lose context, inject trace into to the request. propagate().inject(span, request, SETTER); - // temporarily remove from request to avoid spring resource name bubbling up: - request.removeAttribute(DD_SPAN_ATTRIBUTE); + // temporarily replace from request to avoid spring resource name bubbling up: + requestSpan = request.getAttribute(DD_SPAN_ATTRIBUTE); + request.setAttribute(DD_SPAN_ATTRIBUTE, span); return activateSpan(span, true).setAsyncPropagation(true); } @@ -96,14 +98,17 @@ public final class RequestDispatcherInstrumentation extends Instrumenter.Default @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stop( @Advice.Enter final AgentScope scope, + @Advice.Local("_requestSpan") final Object requestSpan, @Advice.Argument(0) final ServletRequest request, @Advice.Thrown final Throwable throwable) { if (scope == null) { return; } - // now add it back... - request.setAttribute(DD_SPAN_ATTRIBUTE, scope.span()); + if (requestSpan != null) { + // now add it back... + request.setAttribute(DD_SPAN_ATTRIBUTE, requestSpan); + } DECORATE.onError(scope, throwable); DECORATE.beforeFinish(scope); diff --git a/dd-java-agent/instrumentation/servlet/src/test/groovy/RequestDispatcherTest.groovy b/dd-java-agent/instrumentation/servlet/src/test/groovy/RequestDispatcherTest.groovy index f352051753..9f272cb46f 100644 --- a/dd-java-agent/instrumentation/servlet/src/test/groovy/RequestDispatcherTest.groovy +++ b/dd-java-agent/instrumentation/servlet/src/test/groovy/RequestDispatcherTest.groovy @@ -1,15 +1,23 @@ +import datadog.opentracing.DDSpan import datadog.trace.agent.test.AgentTestRunner import javax.servlet.ServletException import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse +import static datadog.opentracing.propagation.DatadogHttpCodec.SAMPLING_PRIORITY_KEY +import static datadog.opentracing.propagation.DatadogHttpCodec.SPAN_ID_KEY +import static datadog.opentracing.propagation.DatadogHttpCodec.TRACE_ID_KEY +import static datadog.trace.agent.decorator.HttpServerDecorator.DD_SPAN_ATTRIBUTE import static datadog.trace.agent.test.utils.TraceUtils.basicSpan import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace class RequestDispatcherTest extends AgentTestRunner { - def dispatcher = new RequestDispatcherUtils(Mock(HttpServletRequest), Mock(HttpServletResponse)) + def request = Mock(HttpServletRequest) + def response = Mock(HttpServletResponse) + def mockSpan = Mock(DDSpan) + def dispatcher = new RequestDispatcherUtils(request, response) def "test dispatch no-parent"() { when: @@ -17,7 +25,17 @@ class RequestDispatcherTest extends AgentTestRunner { dispatcher.include("") then: - assertTraces(0) {} + assertTraces(2) { + trace(0, 1) { + basicSpan(it, 0, "forward-child") + } + trace(1, 1) { + basicSpan(it, 0, "include-child") + } + } + + and: + 0 * _ } def "test dispatcher #method with parent"() { @@ -28,7 +46,7 @@ class RequestDispatcherTest extends AgentTestRunner { then: assertTraces(1) { - trace(0, 2) { + trace(0, 3) { basicSpan(it, 0, "parent") span(1) { operationName "servlet.$operation" @@ -39,9 +57,22 @@ class RequestDispatcherTest extends AgentTestRunner { defaultTags() } } + basicSpan(it, 2, "$operation-child", span(1)) } } + then: + 1 * request.setAttribute(TRACE_ID_KEY, _) + 1 * request.setAttribute(SPAN_ID_KEY, _) + 1 * request.setAttribute(SAMPLING_PRIORITY_KEY, _) + then: + 1 * request.getAttribute(DD_SPAN_ATTRIBUTE) >> mockSpan + then: + 1 * request.setAttribute(DD_SPAN_ATTRIBUTE, { it.spanName == "servlet.$operation" }) + then: + 1 * request.setAttribute(DD_SPAN_ATTRIBUTE, mockSpan) + 0 * _ + where: operation | method "forward" | "forward" @@ -55,7 +86,7 @@ class RequestDispatcherTest extends AgentTestRunner { def "test dispatcher #method exception"() { setup: def ex = new ServletException("some error") - def dispatcher = new RequestDispatcherUtils(Mock(HttpServletRequest), Mock(HttpServletResponse), ex) + def dispatcher = new RequestDispatcherUtils(request, response, ex) when: runUnderTrace("parent") { @@ -67,7 +98,7 @@ class RequestDispatcherTest extends AgentTestRunner { th == ex assertTraces(1) { - trace(0, 2) { + trace(0, 3) { basicSpan(it, 0, "parent", null, ex) span(1) { operationName "servlet.$operation" @@ -80,9 +111,22 @@ class RequestDispatcherTest extends AgentTestRunner { errorTags(ex.class, ex.message) } } + basicSpan(it, 2, "$operation-child", span(1)) } } + then: + 1 * request.setAttribute(TRACE_ID_KEY, _) + 1 * request.setAttribute(SPAN_ID_KEY, _) + 1 * request.setAttribute(SAMPLING_PRIORITY_KEY, _) + then: + 1 * request.getAttribute(DD_SPAN_ATTRIBUTE) >> mockSpan + then: + 1 * request.setAttribute(DD_SPAN_ATTRIBUTE, { it.spanName == "servlet.$operation" }) + then: + 1 * request.setAttribute(DD_SPAN_ATTRIBUTE, mockSpan) + 0 * _ + where: operation | method "forward" | "forward" diff --git a/dd-java-agent/instrumentation/servlet/src/test/groovy/RequestDispatcherUtils.java b/dd-java-agent/instrumentation/servlet/src/test/groovy/RequestDispatcherUtils.java index 2f08ad74ed..2f102b4708 100644 --- a/dd-java-agent/instrumentation/servlet/src/test/groovy/RequestDispatcherUtils.java +++ b/dd-java-agent/instrumentation/servlet/src/test/groovy/RequestDispatcherUtils.java @@ -1,9 +1,12 @@ +import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace; + import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; import java.util.Set; +import java.util.concurrent.Callable; import javax.servlet.RequestDispatcher; import javax.servlet.Servlet; import javax.servlet.ServletContext; @@ -164,7 +167,15 @@ public class RequestDispatcherUtils { class TestDispatcher implements RequestDispatcher { @Override public void forward(final ServletRequest servletRequest, final ServletResponse servletResponse) - throws ServletException, IOException { + throws ServletException { + runUnderTrace( + "forward-child", + new Callable() { + @Override + public Object call() throws Exception { + return null; + } + }); if (toThrow != null) { throw toThrow; } @@ -172,7 +183,15 @@ public class RequestDispatcherUtils { @Override public void include(final ServletRequest servletRequest, final ServletResponse servletResponse) - throws ServletException, IOException { + throws ServletException { + runUnderTrace( + "include-child", + new Callable() { + @Override + public Object call() throws Exception { + return null; + } + }); if (toThrow != null) { throw toThrow; } From f78b34fd9d8a3ed65a8b09b3b0c51fe7a82774aa Mon Sep 17 00:00:00 2001 From: Brian Devins-Suresh Date: Fri, 31 Jan 2020 14:11:50 -0500 Subject: [PATCH 37/37] Version 0.42.0 --- dd-trace-java.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-trace-java.gradle b/dd-trace-java.gradle index f64130f74b..8523e660ae 100644 --- a/dd-trace-java.gradle +++ b/dd-trace-java.gradle @@ -16,7 +16,7 @@ def isCI = System.getenv("CI") != null allprojects { group = 'com.datadoghq' - version = '0.42.0-SNAPSHOT' + version = '0.42.0' if (isCI) { buildDir = "${rootDir}/workspace/${projectDir.path.replace(rootDir.path, '')}/build/"