Skip to content
Commits on Source (9)
......@@ -10,7 +10,7 @@ The [latest release][] is available from [Maven Central][] as:
<dependency>
<groupId>com.google.code.java-allocation-instrumenter</groupId>
<artifactId>java-allocation-instrumenter</artifactId>
<version>3.0</version>
<version>3.0.1</version>
</dependency>
```
......@@ -50,6 +50,6 @@ For more information on how to get or use the allocation instrumenter, see [Gett
[java.lang.instrument]: http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html
[ASM]: http://asm.ow2.org/
[latest release]: https://github.com/google/allocation-instrumenter/releases/tag/java-allocation-instrumenter-3.0
[Maven Central]: http://search.maven.org/#artifactdetails%7Ccom.google.code.java-allocation-instrumenter%7Cjava-allocation-instrumenter%7C3.0%7Cjar
[latest release]: https://github.com/google/allocation-instrumenter/releases/tag/java-allocation-instrumenter-3.0.1
[Maven Central]: http://search.maven.org/#artifactdetails%7Ccom.google.code.java-allocation-instrumenter%7Cjava-allocation-instrumenter%7C3.0.1%7Cjar
[Getting Started]: https://github.com/google/allocation-instrumenter/wiki
java-allocation-instrumenter (3.1.0-1) unstable; urgency=medium
* Team upload.
* New upstream release
- Updated the build dependencies
* Standards-Version updated to 4.2.1
* Switch to debhelper level 11
* Removed the no longer used debian/orig-tar.sh script
* Use salsa.debian.org Vcs-* URLs
-- Emmanuel Bourg <ebourg@apache.org> Tue, 23 Oct 2018 16:38:18 +0200
java-allocation-instrumenter (3.0.1-1) unstable; urgency=medium
* New upstream release
......
......@@ -2,23 +2,28 @@ Source: java-allocation-instrumenter
Section: java
Priority: optional
Maintainer: Debian Java maintainers <pkg-java-maintainers@lists.alioth.debian.org>
Uploaders: Tim Potter <tpot@hp.com>,
Uploaders:
Tim Potter <tpot@hp.com>,
Kai-Chung Yan <seamlikok@gmail.com>
Build-Depends: debhelper (>= 9),
Build-Depends:
debhelper (>= 11),
default-jdk-doc,
default-jdk-headless | default-jdk,
javahelper,
junit,
libasm-java,
libbuild-helper-maven-plugin-java,
libguava-java,
libjarjar-maven-plugin-java,
libmaven-javadoc-plugin-java,
libmaven-source-plugin-java,
libmaven-shade-plugin-java,
libreplacer-java,
maven-debian-helper
Standards-Version: 3.9.8
Standards-Version: 4.2.1
Vcs-Git: https://://anonscm.debian.org/git/java-team/java-allocation-instrumenter.git
Vcs-Browser: https://salsa.debian.org/java-team/java-allocation-instrumenter
Homepage: https://github.com/google/allocation-instrumenter
Vcs-Git: https://://anonscm.debian.org/git/pkg-java/java-allocation-instrumenter.git
Vcs-Browser: https://anonscm.debian.org/cgit/pkg-java/java-allocation-instrumenter.git
Package: libjava-allocation-instrumenter-java
Architecture: all
......
......@@ -4,11 +4,8 @@ export JAVA_HOME=/usr/lib/jvm/default-java
export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8
%:
dh $@ --buildsystem=maven --with javahelper
dh $@ --with javahelper
override_dh_auto_clean:
dh_auto_clean
$(RM) debian/maven.rules debian/maven.publishedRules debian/maven.cleanIgnoreRules
get-orig-source:
uscan --download-current-version --force-download --rename
......@@ -28,7 +28,7 @@
<groupId>com.google.code.java-allocation-instrumenter</groupId>
<artifactId>java-allocation-instrumenter</artifactId>
<packaging>jar</packaging>
<version>3.0.1</version>
<version>3.1.0</version>
<name>java-allocation-instrumenter</name>
<description>
......@@ -72,7 +72,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<projectAsmVersion>5.0.3</projectAsmVersion>
<projectAsmVersion>6.0</projectAsmVersion>
<gpg.skip>true</gpg.skip>
</properties>
......@@ -110,7 +110,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
<version>23.5-android</version>
</dependency>
<dependency>
<groupId>junit</groupId>
......@@ -123,11 +123,11 @@
<build>
<defaultGoal>package</defaultGoal>
<plugins>
<!-- ensure java version -->
<!-- specify target Java version -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<version>3.6.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
......@@ -137,7 +137,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<version>2.10</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
......@@ -148,7 +148,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.1</version>
<version>2.5.3</version>
<configuration>
<arguments>-DenableCiProfile=true</arguments>
</configuration>
......@@ -157,7 +157,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
......@@ -171,7 +171,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.1</version>
<version>2.10.4</version>
<executions>
<execution>
<id>attach-javadocs</id>
......@@ -188,19 +188,79 @@
<show>public</show>
</configuration>
</plugin>
<!-- embed dependencies -->
<!-- preprocess bootstrap method -->
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>jarjar-maven-plugin</artifactId>
<version>1.9</version>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<id>embed-jars</id>
<phase>prepare-package</phase>
<phase>generate-sources</phase>
<goals>
<goal>jarjar</goal>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>${project.basedir}/src/main/java/com/google/monitoring/runtime/instrumentation/Bootstrap.java.in</file>
<outputFile>${project.build.directory}/generated-sources/java/com/google/monitoring/runtime/instrumentation/AllocationInstrumenterBootstrap.java</outputFile>
<replacements>
<replacement>
<token>CLASS_NAME</token>
<value>AllocationInstrumenter</value>
</replacement>
<replacement>
<token>PACKAGE</token>
<value>com.google.monitoring.runtime.instrumentation</value>
</replacement>
<replacement>
<token>PATH_TO_CLASS</token>
<value>com/google/monitoring/runtime/instrumentation</value>
</replacement>
<replacement>
<token>PREMAIN_CLASS</token>
<value>com.google.monitoring.runtime.instrumentation.AllocationInstrumenter</value>
</replacement>
<replacement>
<token>GENERATOR</token>
<value>https://github.com/google/allocation-instrumenter/blob/master/pom.xml</value>
</replacement>
</replacements>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/java/</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<!-- shade Guava and ASM; strip module-info file from ASM -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
</execution>
</executions>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<artifactSet>
<includes>
<include>org.ow2.asm:asm</include>
<include>org.ow2.asm:asm-analysis</include>
......@@ -210,15 +270,40 @@
<include>org.ow2.asm:asm-xml</include>
<include>com.google.guava:guava</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/module-info.class</exclude>
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.google.common.</pattern>
<shadedPattern>com.google.monitoring.runtime.instrumentation.common.</shadedPattern>
</relocation>
<relocation>
<pattern>org.objectweb.asm.</pattern>
<shadedPattern>com.google.monitoring.runtime.instrumentation.asm.</shadedPattern>
</relocation>
</relocations>
</configuration>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>jarjar-maven-plugin</artifactId>
<version>1.9</version>
<executions>
<execution>
<id>embed-jars</id>
<phase>prepare-package</phase>
<goals>
<goal>jarjar</goal>
</goals>
<configuration>
<rules>
<rule>
<pattern>org.objectweb.asm.**</pattern>
<result>com.google.monitoring.runtime.instrumentation.asm.@1</result>
</rule>
<rule>
<pattern>com.google.common.**</pattern>
<result>com.google.monitoring.runtime.instrumentation.common.@0</result>
</rule>
<keep>
<pattern>com.google.monitoring.runtime.instrumentation.common.collect.ComputingCache</pattern>
<pattern>com.google.monitoring.runtime.instrumentation.common.collect.ComputingConcurrentHashMap</pattern>
......@@ -241,12 +326,11 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<version>3.0.2</version>
<configuration>
<archive>
<manifestEntries>
<Boot-Class-Path>./${project.artifactId}-${project.version}.${project.packaging}</Boot-Class-Path>
<Premain-Class>com.google.monitoring.runtime.instrumentation.AllocationInstrumenter</Premain-Class>
<Premain-Class>com.google.monitoring.runtime.instrumentation.AllocationInstrumenterBootstrap</Premain-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
<Main-Class>NotSuitableAsMain</Main-Class>
......@@ -257,7 +341,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.4</version>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
......
......@@ -27,8 +27,6 @@ import org.objectweb.asm.commons.JSRInlinerAdapter;
* A <code>ClassVisitor</code> that processes methods with a
* <code>AllocationMethodAdapter</code> to instrument heap allocations.
*
* @author jeremymanson@google.com (Jeremy Manson)
* @author fischman@google.com (Ami Fischman) (Original Author)
*/
class AllocationClassAdapter extends ClassVisitor {
private final String recorderClass;
......@@ -36,7 +34,7 @@ class AllocationClassAdapter extends ClassVisitor {
public AllocationClassAdapter(ClassVisitor cv, String recorderClass,
String recorderMethod) {
super(Opcodes.ASM5, cv);
super(Opcodes.ASM6, cv);
this.recorderClass = recorderClass;
this.recorderMethod = recorderMethod;
}
......
......@@ -36,8 +36,6 @@ import java.util.logging.Logger;
* looks like it will be allocating heap memory allowing users to implement heap
* profiling schemes.
*
* @author Ami Fischman
* @author Jeremy Manson
*/
public class AllocationInstrumenter implements ClassFileTransformer {
static final Logger logger =
......@@ -161,7 +159,7 @@ public class AllocationInstrumenter implements ClassFileTransformer {
/**
* Given the bytes representing a class, go through all the bytecode in it and
* instrument any occurences of new/newarray/anewarray/multianewarray with
* instrument any occurrences of new/newarray/anewarray/multianewarray with
* pre- and post-allocation hooks. Even more fun, intercept calls to the
* reflection API's Array.newInstance() and instrument those too.
*
......
......@@ -32,7 +32,6 @@ import java.util.regex.Pattern;
* to record the allocation being done for profiling.
* Instruments bytecodes that allocate heap memory to call a recording hook.
*
* @author Ami Fischman
*/
class AllocationMethodAdapter extends MethodVisitor {
/**
......@@ -148,13 +147,6 @@ class AllocationMethodAdapter extends MethodVisitor {
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class",
"getName", "()Ljava/lang/String;", false);
// -> stack: ... class classNameDotted
super.visitLdcInsn('.');
// -> stack: ... class classNameDotted '.'
super.visitLdcInsn('/');
// -> stack: ... class classNameDotted '.' '/'
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String",
"replace", "(CC)Ljava/lang/String;", false);
// -> stack: ... class className
}
// Helper method to compute the product of an integer array and push it on
......@@ -551,14 +543,37 @@ class AllocationMethodAdapter extends MethodVisitor {
// below we note the partial product of dimensions 1 to X-1 as productToX
// (so productTo1 == 1 == no dimensions yet). We denote by aref0 the
// array reference at the current nesting level (the containing aref's [0]
// element). If we hit a level whose arraylength is 0 there's no point
// continuing so we shortcut out.
// element). If we hit a level whose arraylength is 0 or whose
// reference is null, there's no point continuing, so we shortcut
// out.
// This approach works pretty well when you create a new array with the
// newarray bytecodes. You can also create a new array by cloning an
// existing array; an existing multidimensional array might have had some
// of its [0] elements nulled out. We currently deal with this by bailing
// out, but arguably we should do something more principled (like calculate
// the size of the multidimensional array from scratch if you are using
// clone()).
// TODO(java-platform-team): Do something about modified multidimensional
// arrays and clone().
Label zeroDimension = new Label();
super.visitInsn(Opcodes.DUP); // -> stack: ... origaref aref0
super.visitLdcInsn(1); // -> stack: ... origaref aref0 productTo1
for (int i = 0; i < dimCount; ++i) {
// pre: stack: ... origaref aref0 productToI
super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref productToI aref
super.visitInsn(Opcodes.DUP);
Label nonNullDimension = new Label();
// -> stack: ... origaref productToI aref aref
super.visitJumpInsn(Opcodes.IFNONNULL, nonNullDimension);
// -> stack: ... origaref productToI aref
super.visitInsn(Opcodes.SWAP);
// -> stack: ... origaref aref productToI
super.visitJumpInsn(Opcodes.GOTO, zeroDimension);
super.visitLabel(nonNullDimension);
// -> stack: ... origaref productToI aref
super.visitInsn(Opcodes.DUP_X1);
// -> stack: ... origaref aref0 productToI aref
super.visitInsn(Opcodes.ARRAYLENGTH);
......
......@@ -30,8 +30,6 @@ import com.google.common.collect.MapMaker;
* The logic for recording allocations, called from bytecode rewritten by
* {@link AllocationInstrumenter}.
*
* @author jeremymanson@google.com (Jeremy Manson)
* @author fischman@google.com (Ami Fischman)
*/
public class AllocationRecorder {
static {
......@@ -233,6 +231,10 @@ public class AllocationRecorder {
// optional samplers. However, you don't need the optional samplers in
// the common case, so I thought I'd save some space.
if (count >= 0) {
desc = desc.replace('.', '/');
}
// Copy value into local variable to prevent NPE that occurs when
// instrumentation field is set to null by this class's shutdown hook
// after another thread passed the null check but has yet to call
......
package PACKAGE;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.util.jar.JarFile;
import javax.annotation.Generated;
/**
* Add the agent to the bootclasspath before invoking premain().
*
* <p>In order to rewrite classes that are loaded by the bootstrap class loader to point to
* agent-provided instrumentation, the agent needs to be loaded by the bootstrap class loader.
*
* <p>There are three ways of doing this. The first requires that we add "Boot-Class-Path: &lt;JAR file
* name&gt;" to the agent's manifest. That only works when we know the exact name of the output JAR.
* That's not the case in various environments. For example, Maven-released JARs often bake a
* version number into their JAR names. The second is to add the JAR to the bootclasspath on the
* command line, but that's awful, as well as unsupported in Java 9.
*
* <p>The third is to use Instrumentation#appendToBootstrapClassLoaderSearch, which works as
* advertised. We can dynamically determine the name of the JAR containing this class (i.e., the
* agent), and then add that JAR to the bootstrap class path. The problem with this approach is that
* the agent's premain class is loaded prior to our ability to call that function, so it can't do
* the things we need the agent to be in the bootstrap class path to do. One workaround for this is
* to create a class that does nothing but call appendToBootstrapClassLoaderSearch on the agent's
* JAR file, and then calls into the real premain function (like the one below). Rather than
* replicating this class for every agent we might write, we use generated code.
*
* <p>This file is pre-processed to include the correct name of the class being used as a premain
* before being compiled and integrated into the agent.
*/
@Generated(value = "GENERATOR")
public class CLASS_NAMEBootstrap {
public static void premain(String agentArgs, Instrumentation inst) {
try {
// First, find the JAR file containing the agent and append it to the bootclasspath.
String resourceName = "PATH_TO_CLASS";
java.net.URL url = ClassLoader.getSystemResource(resourceName);
JarFile jarfile = ((JarURLConnection) url.openConnection()).getJarFile();
inst.appendToBootstrapClassLoaderSearch(jarfile);
// Now invoke the real premain. We do not require that the premain class be available at
// compile time. Some agents bake it into the main JAR file. We use reflection to
// invoke it.
Class<?> premainClass = Class.forName("PREMAIN_CLASS");
Method pm = premainClass.getDeclaredMethod("premain", String.class, Instrumentation.class);
pm.invoke(null, agentArgs, inst);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
......@@ -27,7 +27,6 @@ package com.google.monitoring.runtime.instrumentation;
*
* @param <T> The class that will be sampled with this ConstructorCallback
*
* @author Jeremy Manson
*/
public interface ConstructorCallback<T> {
/**
......
......@@ -39,7 +39,6 @@ import java.util.logging.Logger;
* by a javaagent; end-users will want to add {@link ConstructorCallback}s by
* invoking {@link #instrumentClass(Class, ConstructorCallback)}.
*
* @author Jeremy Manson
*/
public class ConstructorInstrumenter implements ClassFileTransformer {
// Implementation details: uses the java.lang.instrument API to
......@@ -161,7 +160,7 @@ public class ConstructorInstrumenter implements ClassFileTransformer {
public LocalVariablesSorter lvs = null;
Class<?> cl;
ConstructorMethodAdapter(MethodVisitor mv, Class<?> cl) {
super(Opcodes.ASM5, mv);
super(Opcodes.ASM6, mv);
this.cl = cl;
}
......@@ -227,7 +226,7 @@ public class ConstructorInstrumenter implements ClassFileTransformer {
static class ConstructorClassAdapter extends ClassVisitor {
Class<?> cl;
public ConstructorClassAdapter(ClassVisitor cv, Class<?> cl) {
super(Opcodes.ASM5, cv);
super(Opcodes.ASM6, cv);
this.cl = cl;
}
......
......@@ -19,7 +19,6 @@ package com.google.monitoring.runtime.instrumentation;
/**
* This interface describes a function that is used to sample an allocation.
*
* @author jeremymanson@google.com (Jeremy Manson)
*/
public interface Sampler {
/**
......
......@@ -63,7 +63,6 @@ import java.io.IOException;
* the same logic in a subclass. The code here has been slightly
* cleaned up for readability.
*
* @author jeremymanson@google.com (Jeremy Manson)
*/
class StaticClassWriter extends ClassWriter {
......
......@@ -33,7 +33,6 @@ import java.util.logging.Logger;
* Currently, it only checks to see if the methods are of the correct length
* for Java methods (&lt;64K).
*
* @author jeremymanson@google.com (Jeremy Manson)
*/
public class VerifyingClassAdapter extends ClassVisitor {
private static final Logger logger =
......@@ -59,7 +58,7 @@ public class VerifyingClassAdapter extends ClassVisitor {
*/
public VerifyingClassAdapter(ClassWriter cw, byte [] original,
String className) {
super(Opcodes.ASM5, cw);
super(Opcodes.ASM6, cw);
state = State.UNKNOWN;
message = "The class has not finished being examined";
this.cw = cw;
......