简体   繁体   中英

Java Newbie: How to use Java Agent From the Command Line for Instrumentation

I am attempting to load a java agent to use java.lang.instrument.Instrumentation to measure the size of an object. Here is my Java:

package com.example.memory.usage;

import java.lang.instrument.Instrumentation;
import java.util.*;


public class MemoryUsage {

    public static void main(String[] args) throws Exception {

        Random random = new Random();

        Set<Integer> integerSet = new HashSet<>();

        for(int i = 0; i < pixels; i++) {
            if(random.nextDouble() < 0.20) {
                integerSet.add(i);
            }
        }

        System.out.println(ObjectSizeFetcher.getObjectSize(integerSet));
    }

    public static class ObjectSizeFetcher {
        private static Instrumentation instrumentation;

        public static void premain(String args, Instrumentation inst) {
            System.out.println("Premain ... " + inst);
            instrumentation = inst;
        }

        public static long getObjectSize(Object o) {
            return instrumentation.getObjectSize(o);
        }
    }
}

As this is a Maven project, here is my pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>memory-usage</artifactId>
<version>1.0-SNAPSHOT</version>

<build>
    <finalName>memory-usage</finalName>
    <plugins>
        <!-- Compiler -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.0</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
            </configuration>
        </plugin>

        <!-- Jar -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>com.example.memory.usage.MemoryUsage</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

        <!-- Assembly -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>attached</goal>
                    </goals>
                    <phase>package</phase>
                    <configuration>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                        <archive>
                            <manifest>
                                <mainClass>com.example.memory.usage.MemoryUsage</mainClass>
                            </manifest>
                            <manifestEntries>
                                <Premain-Class>java.lang.instrument.Instrumentation</Premain-Class>
                            </manifestEntries>
                        </archive>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
</project>

No I do not know what to do next. Please help. I ran

$ mvn clean package

and then

$ java -jar target/memory-usage-jar-with-dependencies.jar

which gives me this exception:

Exception in thread "main" java.lang.NullPointerException
    at com.example.memory.usage.MemoryUsage$ObjectSizeFetcher.getObjectSize(MemoryUsage.java:42)
    at com.example.memory.usage.MemoryUsage.main(MemoryUsage.java:29)

What should I do to run this?

The launch mechanism is considered JVM/JRE specific. However, the package-summary of the instrumentation API tells you:

Command-Line Interface

An implementation is not required to provide a way to start agents from the command-line interface. On implementations that do provide a way to start agents from the command-line interface, an agent is started by adding this option to the command-line:

 -javaagent:jarpath[=options] 

jarpath is the path to the agent JAR file. options is the agent options. This switch may be used multiple times on the same command-line, thus creating multiple agents. More than one agent may use the same jarpath . An agent JAR file must conform to the JAR file specification.


The launcher documentation also provides a hint:

-javaagent:jarpath[=options]

Loads the specified Java programming language agent. For more information about instrumenting Java applications, see the java.lang.instrument package description in the Java API documentation at http://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html


But note that you have to specify the right agent class in your manifest. As far as I can see you're specifying java.lang.instrument.Instrumentation as premain class which is nonsense. In your code, the class containing the premain method is com.example.memory.usage.MemoryUsage$ObjectSizeFetcher and hence you should specify that class…

You call getObjectSize statically. The variable instrumentation needs to be initialized (ie instrumentation = new Instrumentation(); )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM