Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 51 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
51
Dung lượng
598,59 KB
Nội dung
for (String option: options) System.out.println (option); } } The source code introduces public static void agentmain(String agentArgs, Instrumentation inst) as the entry point into the agent. According to the JDK 6 docu- mentation for the java.lang.instrument package (introduced by Java 5), it is likely that an application will be running and its public static void main(String [] args) method will have been invoked before the virtual machine invokes agentmain(). ■Note According to the JDK documentation, the target virtual machine will attempt to locate and invoke a public static void agentmain(String agentArgs) method if it cannot locate public static void agentmain(String agentArgs, Instrumentation inst) . If it cannot find this fallback method, the target virtual machine and its application will keep running, without the agent running in the background. The target virtual machine/application will also keep running if either agentmain() method throws an exception; the uncaught exception is ignored. The agentmain() method specifies a String parameter that identifies any arguments passed to this method. These arguments originate from the arguments string passed to options in loadAgent(String agent, String options) (described in Table 7-2). Because the arguments are combined into a single string, the agent is responsible for parsing them. BasicAgent refers to these arguments as options. After compiling the agent’s source code ( javac BasicAgent.java), the resulting class file must be stored in a JAR file. As stated in the JDK documentation, this JAR file’s mani- fest must contain an Agent-Class attribute that identifies the class containing an agentmain() method. Listing 7-4 presents a suitable manifest file with the Agent-Class attribute for the agent’s JAR file. Listing 7-4. manifest.mf Agent-Class: BasicAgent After creating a basicAgent.jar file via jar cvfm basicAgent.jar manifest.mf BasicAgent.class (or a similar command), you are almost ready to use the Attach API to load the JAR file’s agent into a target virtual machine. To accomplish this task, I’ve created an attach application, whose source code appears in Listing 7-5. CHAPTER 7 ■ MONITORING AND MANAGEMENT232 830-X CH07.qxd 9/20/07 2:01 PM Page 232 Listing 7-5. BasicAttach.java // BasicAttach.java // Unix compile : javac -cp $JAVA_HOME/lib/tools.jar BasicAttach.java // // Windows compile: javac -cp %JAVA_HOME%/lib/tools.jar BasicAttach.java import java.io.*; import java.util.*; import com.sun.tools.attach.*; public class BasicAttach { public static void main (String [] args) throws Exception { if (args.length != 1) { System.err.println ("Unix usage : "+ "java -cp $JAVA_HOME/lib/tools.jar:. "+ "BasicAttach appmainclassname"); System.err.println (); System.err.println ("Windows usage: "+ "java -cp %JAVA_HOME%/lib/tools.jar;. "+ "BasicAttach appmainclassname"); return; } // Return a list of running virtual machines to which we can potentially // attach. List<VirtualMachineDescriptor> vmds = VirtualMachine.list (); // Search this list for the virtual machine whose display name matches // the name passed to this application as a command-line argument. for (VirtualMachineDescriptor vmd: vmds) if (vmd.displayName ().equals (args [0])) { // Attempt to attach. CHAPTER 7 ■ MONITORING AND MANAGEMENT 233 830-X CH07.qxd 9/20/07 2:01 PM Page 233 VirtualMachine vm = VirtualMachine.attach (vmd.id ()); // Identify the location and name of the agent JAR file to // load. The location is relative to the target virtual machine // not the virtual machine running BasicAttach. The location // and JAR name are passed to the target virtual machine, which // (in this case) is responsible for loading the basicAgent.jar // file from the location. String agent = vm.getSystemProperties () .getProperty ("java.home")+File.separator+ "lib"+File.separator+"basicAgent.jar"; // Attempt to load the agent into the target virtual machine. vm.loadAgent (agent); // Detach. vm.detach (); // Attempt to attach. vm = VirtualMachine.attach (vm.id ()); // Attempt to load the agent into the target virtual machine, // specifying a comma-separated list of options. vm.loadAgent (agent, "a=b,c=d,x=y"); return; } System.out.println ("Unable to find target virtual machine"); } } According to the source code, BasicAttach requires a single command-line argument that serves as the name of an application running on a target virtual machine. The appli- cation uses this argument to locate an appropriate VirtualMachineDescriptor so that it can obtain the target virtual machine identifier and then attach to the target virtual machine. CHAPTER 7 ■ MONITORING AND MANAGEMENT234 830-X CH07.qxd 9/20/07 2:01 PM Page 234 After attaching, BasicAttach needs to locate basicAgent.jar so that this JAR file can be loaded into the target virtual machine. It assumes that basicAgent.jar is placed in the same location as the JMX agent’s management-agent.jar file. This location is the lib subdi- rectory of the target virtual machine’s JRE home directory ( %JAVA_HOME%\jre under Windows). Open a command window and run the BuggyThreads application presented earlier (if it is not already running). In another command window, compile BasicAttach.java via the instructions near the top of the source code. To attach BuggyThreads on Windows systems, invoke the following: java -cp %JAVA_HOME%/lib/tools.jar;. BasicAttach BuggyThreads On Unix systems, invoke the following: java -cp $JAVA_HOME/lib/tools.jar:. BasicAttach BuggyThreads If all goes well, BasicAttach ends immediately, returning to the command prompt with no output. In contrast, the command window that shows the output from BuggyThreads will most likely intermingle BasicAgent’s output with the BuggyThreads output. You might want to redirect the standard output device to a file when running BuggyThreads so that you can see the agent’s output. Here’s an abbreviated example of the output: Starting Thread A Starting Thread B Entering infinite loop Thread A acquiring Lock A Thread A acquiring Lock B Thread A releasing Lock B Thread B acquiring Lock B Thread A releasing Lock A Thread B acquiring Lock A Thread A releasing Lock A Thread A acquiring Lock A Thread A acquiring Lock B Thread A releasing Lock B Thread B acquiring Lock B Thread A releasing Lock A Thread B acquiring Lock A Basic agent invoked CHAPTER 7 ■ MONITORING AND MANAGEMENT 235 830-X CH07.qxd 9/20/07 2:01 PM Page 235 No options passed Thread B releasing Lock A Thread B releasing Lock B Thread B acquiring Lock B Thread B acquiring Lock A Thread B releasing Lock A Thread A acquiring Lock A Thread B releasing Lock B Thread A acquiring Lock B Basic agent invoked Options a=b c=d x=y Thread A releasing Lock B Thread A releasing Lock A Thread A acquiring Lock A Thread A acquiring Lock B Thread A releasing Lock B Thread B acquiring Lock B Improved Instrumentation API The instrumentation built into HotSpot and other virtual machines provides information about virtual machine resources, such as the number of running threads that are still alive, the peak usage of the heap memory pool since the virtual machine started, and so on. Collectively, this information is useful when you want to monitor an application’s “health” and take corrective action if its health declines. Although monitoring application health is important, you might prefer to instru- ment an application’s classes (by adding bytecodes to their methods for the purpose of gathering statistics without modifying application state or behavior) to accomplish another goal. For example, you might be interested in creating a coverage analyzer, which systematically tests application code. CHAPTER 7 ■ MONITORING AND MANAGEMENT236 830-X CH07.qxd 9/20/07 2:01 PM Page 236 ■Note Steve Cornett’s “Code Coverage Analysis” paper (http://www.bullseye.com/coverage.html) describes what a coverage analyzer does. To support instrumentation for coverage analysis, event logging, and other non- health-related tasks, Java 5 introduced the java.lang.instrument package. This package’s Instrumentation interface provides services needed to instrument classes, such as registering a transformer (a class that implements the java.lang.instrument. ClassFileTransformer interface) to take care of instrumentation. ■Note Java 5’s Instrumentation interface also provides services for redefining classes. In contrast to transformation, which focuses on changing classes from an instrumentation perspective, redefinition focuses on replacing a class’s definition. For example, you might want to develop a tool that supports fix-and-continue debugging . This is an alternative to the traditional edit-compile-debug cycle, which lets you change a program from within the debugger and continue debugging without needing to leave the debugger, recompile, enter the debugger, and restart debugging from scratch. You would use redefinition to change the class’s definition to include new class bytes resulting from compilation. Instrumentation is one of the parameters in the two-parameter agentmain() method. Both overloaded versions of this method were added in Java SE 6. Instrumentation is also one of the parameters in the two-parameter premain() method, which was introduced by Java 5 and has a parameter list identical to that of agentmain(). Unlike premain(), which is always invoked before an application’s main() method runs, agentmain() is often (but not necessarily) invoked after main() has run. Also, whereas agentmain() is invoked as a result of dynamic attach, premain() is invoked as a result of starting the virtual machine with the -javaagent option, which specifies an agent JAR file’s path and name. When an Instrumentation instance is passed to either method, the method can access the instance’s methods to transform/redefine classes. ■Note According to Simone Bordet’s “Attaching to a Mustang, explained” blog entry (http://bordet. blogspot.com/2005_11_01_archive.html ), Java SE 6 also introduces a single-parameter premain() method to complement the single-parameter agentmain() method. As with agentmain(), this method’s single parameter is also String agentArgs. Furthermore, it serves as a fallback to the two-parameter premain() method. CHAPTER 7 ■ MONITORING AND MANAGEMENT 237 830-X CH07.qxd 9/20/07 2:01 PM Page 237 Retransformation Support Java SE 6 adds four new methods to the Instrumentation interface to support retransfor- mation: • void retransformClasses(Class<?> classes) • void addTransformer(ClassFileTransformer transformer, boolean canRetransform) • boolean isModifiableClass(Class<?> theClass) • boolean isRetransformClassesSupported() Agents use these methods to retransform previously loaded classes without needing to access their class files. Sun developer Sundar Athijegannathan demonstrates the first two of these methods in his class-dumper agent, presented as an example of a useful agent in his “Retrieving .class files from a running app” blog entry ( http://blogs.sun.com/ sundararajan/entry/retrieving_class_files_from_a). He passes true as addTransformer()’s canRetransform argument so that retransformClasses() invokes transform() for each candidate class. If false were passed, transform() would not be invoked. The isModifiableClass() method returns true if a specific class can be modified via redefinition or retransformation. Java 5 made it possible to determine if the current vir- tual machine configuration supports redefinition via boolean isRedefineClassesSupported(). Java SE 6 complements this method with boolean isRetransformClassesSupported(), which returns true if retransformation is supported. ■Note Java 5 provided a Can-Redefine-Classes attribute that had to be initialized to true in an agent’s JAR manifest so that the agent could redefine classes. Java SE 6’s new Can-Retransform-Classes attribute complements this other attribute. The agent can retransform classes only if Can-Retransform-Classes is initialized to true in its JAR manifest. Native Method Support Java SE 6 adds two new methods to the Instrumentation interface that agents can use to prepare native methods for instrumentation: • void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) • boolean isNativeMethodPrefixSupported() CHAPTER 7 ■ MONITORING AND MANAGEMENT238 830-X CH07.qxd 9/20/07 2:01 PM Page 238 Native methods cannot be directly instrumented because they have no bytecodes. According to the setNativeMethodPrefix() method’s documentation, you can use a trans- former to wrap a native method call inside a nonnative method, which can be instrumented. For example, consider native boolean foo(int x). To apply instrumentation, this method must be wrapped in a same-named nonnative method: boolean foo (int x) { record entry to foo // Specifying return foo (x); would result in recursion. return $$$myagent_wrapped_foo (x); } native boolean $$$myagent_wrapped_foo (int x); A new problem arises in how to resolve the name of the called native method to the native method’s implementation name. For example, suppose the original foo name for the native method resolves to Java_somePackage_someClass_foo. Because $$$myagent_ wrapped_foo might correspond to Java_somePackage_someClass_$$$myagent_ wrapped_foo (which doesn’t exist), resolution fails. Invoking setNativeMethodPrefix() with $$$myagent_ as this method’s prefix parameter value solves this problem. After unsuccessfully trying to resolve $$$myagent_wrapped_foo to Java_somePackage_someClass_$$$myagent_wrapped_foo, the virtual machine deletes the prefix from the native name and resolves $$$myagent_wrapped_foo to Java_somePackage_ someClass_foo. ■Note For an agent to set the native method prefix, the agent’s JAR manifest must initialize Java SE 6’s Can-Set-Native-Method-Prefix attribute to true. Call the isNativeMethodPrefixSupported() method to determine this attribute’s value. Support for Additional Instrumentation Classes Finally, two more new Instrumentation methods can be used to make additional JAR files with instrumentation classes available to the bootstrap and system classloaders: • void appendToBootstrapClassLoaderSearch(JarFile jarfile) • void appendToSystemClassLoaderSearch(JarFile jarfile) CHAPTER 7 ■ MONITORING AND MANAGEMENT 239 830-X CH07.qxd 9/20/07 2:01 PM Page 239 These methods allow you to specify JAR files containing instrumentation classes that are to be defined by the bootstrap or system classloaders. When the classloader’s search for a class is unsuccessful, it will search a specified JAR file for the class. The JAR file must not contain any classes or resources other than those to be defined by the classloader for use in instrumentation. Improved JVM Tool Interface The Attach API’s VirtualMachine class includes a pair of loadAgentLibrary() methods and a pair of loadAgentPath() methods. All four methods accomplish the same goal: they load a native agent library developed with the JVM Tool Interface. The loadAgentLibrary() methods require only the name of the library. The loadAgentPath() methods require the absolute path (including the name) of the library. Java 5 introduced the JVM Tool Interface as a replacement for the JVM Debug Inter- face and JVM Profiler Interface, which were deprecated; JVM Debug is not present in Java SE 6. Java SE 6 cleans up and clarifies the JVM Tool Interface specification and offers the following new and improved features: Support for class-file retransformation: A RetransformClasses() function has been added to facilitate the dynamic transformation of classes that have previously been loaded. Access to the original class file is no longer required to instrument a loaded class. Retransformation can easily remove an applied transformation, and retransfor- mation is designed to work in a multiple-agent environment. Support for enhanced heap traversal: The IterateThroughHeap() and FollowReferences() functions have been added to traverse objects in the heap. IterateThroughHeap() traverses all reachable and unreachable objects in the heap without reporting references between objects. FollowReferences() traverses objects directly and indirectly reachable from either a specified object or heap roots (the set of system classes, for example). These functions can be used to examine the primi- tive values in arrays, Strings, and fields via special callback functions. Various heap filter flags control which objects and primitive values are reported by the callbacks. For example, JVMTI_HEAP_FILTER_TAGGED excludes tagged objects. Additional class information: GetConstantPool(), GetClassVersionNumbers(), and IsModifiableClass() functions have been added to return additional class informa- tion. Support for instrumenting native methods: SetNativeMethodPrefix() and SetNativeMethodPrefixes() functions have been added to allow native methods to be instrumented via a virtual machine-aware mechanism for wrapping these methods in nonnative methods. CHAPTER 7 ■ MONITORING AND MANAGEMENT240 830-X CH07.qxd 9/20/07 2:01 PM Page 240 Enhanced support for instrumentation under the system classloader: An AddToSystemClassLoaderSearch() function allows the system classloader to define instrumentation support classes. Support for early return from methods: “ ForceEarlyReturn” functions, such as ForceEarlyReturnObject(), have been added to allow a debugger-like agent to force a method to return from any point during its execution. Ability to access monitor stack-depth information: A GetOwnedMonitorStackDepthInfo() function has been added to obtain information about a thread’s owned monitors and the depth of the stack frame when the monitors were locked. Support for notification when a resource has been exhausted: A ResourceExhausted() function has been added to notify the virtual machine (via an event) when a critical resource, such as the heap, has been exhausted. In addition to these enhancements, Java SE 6 introduces a new JVMTI_ERROR_CLASS_ LOADER_UNSUPPORTED error code constant to indicate that the classloader does not support an operation. It also allows the AddToBootstrapClassLoaderSearch() function to be called during the live phase (the agent’s execution phase between calls to VMInit() and VMDeath()). ■Note For a JVM Tool Interface tutorial, check out “The JVM Tool Interface (JVM TI): How VM Agents Work” article ( http://java.sun.com/developer/technicalArticles/J2SE/jvm_ti/) and the JVM Tool Inter- face demos (such as heapViewer) that are included in the JDK distribution. Improved Management and JMX APIs The Management API focuses on providing a variety of MXBean interfaces and their methods for accessing virtual machine instrumentation. The JMX API focuses on provid- ing the infrastructure for the JMX agent and applications like JConsole that access the JMX agent. ■Note For background on MXBeans, check out Sun JMX team leader Eamonn McManus’s “What is an MXBean?” blog entry ( http://weblogs.java.net/blog/emcmanus/archive/ 2006/02/what_is_an_ mxbe.html). CHAPTER 7 ■ MONITORING AND MANAGEMENT 241 830-X CH07.qxd 9/20/07 2:01 PM Page 241 [...]... HTTP server (see http:/ /java. sun.com/javase/ 6/ docs/jre/api/net/httpserver/spec/index.html), this server is not a formal part of Java SE 6, which means that it is not guaranteed to be available on non-Sun implementations of Java SE 6 Therefore, rather than packages such as java. net.httpserver and java. net.httpserver.spi, the HTTP server API is stored in the following packages: • com.sun.net.httpserver:... void setExecutor(Executor executor) method You can also call public abstract Executor getExecutor() to return the current executor (the return value is null if no executor has been set) If you do not call setExecutor() prior to starting the server, or if you pass null to this method, a default implementation based on the thread created by start() is used You can stop a started server by invoking HttpServer’s... Listing 8-4 MinimalHTTPServer .java // MinimalHTTPServer .java import java. io.*; import java. net.*; import java. util.*; 265 830-X CH08.qxd 266 9/18/07 10:05 PM Page 266 CHAPTER 8 ■ NETWORKING import com.sun.net.httpserver.*; public class MinimalHTTPServer { public static void main (String [] args) throws IOException { HttpServer server = HttpServer.create (new InetSocketAddress (8000), 0); server.createContext... ■ NETWORKING Lightweight HTTP Server Despite opposition (see Bug 62 70015 “Support a light-weight HTTP server API”), Sun has included a lightweight HTTP server in Java SE 6 The server implementation supports the HTTP and HTTPS protocols Its API can be used to embed an HTTP server in your own applications ■ Note Sun introduced the lightweight HTTP server to facilitate web service testing Chapter 10 demonstrates... server program such as a web server sends a cookie to a client as part of an HTTP response A client program such as a web browser sends a cookie to the server as part of 253 830-X CH08.qxd 254 9/18/07 10:05 PM Page 254 CHAPTER 8 ■ NETWORKING an HTTP request Prior to Java 5, applications worked with the java. net.URLConnection class (and its java. net.HttpURLConnection subclass) to get an HTTP response’s... SE 6 introduces a java. net.IDN utility class that presents two constants and four methods to handle ASCII/Unicode translation The ALLOW_UNASSIGNED and USE_STD3_ ASCII_RULES flag constants can be bitwise ORed together and passed as the flag argument to two of the methods: • ALLOW_UNASSIGNED: Allows unassigned Unicode 3.2 code points to be processed Exercise caution with this constant, because its use... late 2004, Bug 61 79281 “Provide a jconsole plug-in interface to allow loading userdefined tabs” was submitted to Sun’s Bug Database, requesting that JConsole be extended with a plug-in API This API would allow a developer to introduce new tabs to JConsole’s user interface, for interacting with custom MBeans and performing other tasks This request has been fulfilled in Java SE 6 Java SE 6 supports JConsole... 9/20/07 2:01 PM Page 245 CHAPTER 7 ■ MONITORING AND MANAGEMENT ■ Note Sun JMX team member Luis-Miguel Alventosa’s “Changes to the MBeans tab look and feel in Mustang JConsole” blog entry (http://blogs.sun.com/lmalventosa/entry/changes _to_ the_ mbeans_tab) visually compares the Java 5 and Java SE 6 versions of JConsole’s MBeans tab to reveal Java SE 6 s structural changes to this tab JConsole Plug-ins and the... The Java Tutorial’s Internationalized Domain Name page, at http:/ /java. sun.com/docs/books/tutorial/ i18n/network/idn.html, the server returns a 403 Forbidden message, and the browser displays an appropriate message in an error dialog Apparently, this site’s server program checks the browser’s User-Agent header to make sure that it recognizes the browser, and sends a 403 response to any browser it does... method to fetch request cookies from this cache Unlike Java 5, Java SE 6 provides a concrete implementation of CookieHandler so that HTTP protocol handlers and applications can work with cookies The concrete java. net.CookieManager class extends CookieHandler to manage cookies A CookieManager object is initialized as follows: • With a cookie store for storing cookies The cookie store is based on the java. net.CookieStore . ( http://blogs.sun.com/lmalventosa/entry/changes _to_ the_ mbeans_tab ) visually compares the Java 5 and Java SE 6 versions of JConsole’s MBeans tab to reveal Java SE 6 s structural changes to this tab. JConsole. a developer to introduce new tabs to JConsole’s user interface, for interacting with custom MBeans and performing other tasks. This request has been fulfilled in Java SE 6. Java SE 6 supports. thread usage for multiple threads. According to Luis-Miguel, “The aim of this plugin is to show how easy it is to add a custom UI to JConsole based on the Java SE platform instrumenta- tion MXBeans in