test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java
changeset 54297 f98f158c1db8
parent 52125 28375a1de254
equal deleted inserted replaced
54296:dc66ada06693 54297:f98f158c1db8
     1 /*
     1 /*
     2  * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    27  * @summary Exercise the java.lang.instrument.Instrumentation APIs on classes archived
    27  * @summary Exercise the java.lang.instrument.Instrumentation APIs on classes archived
    28  *          using CDS/AppCDSv1/AppCDSv2.
    28  *          using CDS/AppCDSv1/AppCDSv2.
    29  * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes
    29  * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes
    30  * @requires vm.cds
    30  * @requires vm.cds
    31  * @requires vm.flavor != "minimal"
    31  * @requires vm.flavor != "minimal"
    32  * @modules java.base/jdk.internal.misc
       
    33  *          jdk.jartool/sun.tools.jar
       
    34  *          java.management
       
    35  * @build sun.hotspot.WhiteBox
    32  * @build sun.hotspot.WhiteBox
    36  *        InstrumentationApp
    33  *        InstrumentationApp
    37  *        InstrumentationClassFileTransformer
    34  *        InstrumentationClassFileTransformer
    38  *        InstrumentationRegisterClassFileTransformer
    35  *        InstrumentationRegisterClassFileTransformer
    39  * @run main/othervm InstrumentationTest
    36  * @run main/othervm InstrumentationTest
    41 
    38 
    42 // Note: TestCommon is from /test/hotspot/jtreg/runtime/appcds/TestCommon.java
    39 // Note: TestCommon is from /test/hotspot/jtreg/runtime/appcds/TestCommon.java
    43 // Note: Util       is from /test/hotspot/jtreg/runtime/appcds/test-classes/TestCommon.java
    40 // Note: Util       is from /test/hotspot/jtreg/runtime/appcds/test-classes/TestCommon.java
    44 
    41 
    45 import com.sun.tools.attach.VirtualMachine;
    42 import com.sun.tools.attach.VirtualMachine;
    46 import com.sun.tools.attach.VirtualMachineDescriptor;
       
    47 import java.io.File;
    43 import java.io.File;
    48 import java.io.FileOutputStream;
    44 import java.io.FileInputStream;
    49 import java.util.List;
    45 import java.util.Scanner;
    50 import jdk.test.lib.Asserts;
    46 import jdk.test.lib.Asserts;
    51 import jdk.test.lib.cds.CDSOptions;
    47 import jdk.test.lib.cds.CDSOptions;
    52 import jdk.test.lib.process.OutputAnalyzer;
    48 import jdk.test.lib.process.OutputAnalyzer;
    53 import jdk.test.lib.process.ProcessTools;
    49 import jdk.test.lib.process.ProcessTools;
    54 
    50 
   177     static AgentAttachThread doAttach(boolean attachAgent, String flagFile, String agentJar) throws Throwable {
   173     static AgentAttachThread doAttach(boolean attachAgent, String flagFile, String agentJar) throws Throwable {
   178         if (!attachAgent) {
   174         if (!attachAgent) {
   179             return null;
   175             return null;
   180         }
   176         }
   181 
   177 
   182         // We use the flagFile to prevent the child process to make progress, until we have
   178         // Hand-shake protocol with the child process
   183         // attached to it.
   179         // [1] Parent process (this process) launches child process (InstrumentationApp)
       
   180         //     and then waits until child process writes its pid into the flagFile.
       
   181         // [2] Child process process starts up, writes its pid into the flagFile,
       
   182         //     and waits for the flagFile to be deleted.
       
   183         // [3] When parent process gets the pid, it attaches to the child process
       
   184         //     (if we attempt to attach to a process too early, the SIGQUIT
       
   185         //     may cause the child to die) and deletes the flagFile.
       
   186         // [4] Child process resumes execution.
       
   187 
   184         File f = new File(flagFile);
   188         File f = new File(flagFile);
   185         try (FileOutputStream o = new FileOutputStream(f)) {
   189         f.delete();
   186             o.write(1);
   190         if (f.exists()) {
   187         }
   191             throw new RuntimeException("Flag file should not exist: " + f);
   188         if (!f.exists()) {
       
   189             throw new RuntimeException("Failed to create " + f);
       
   190         }
   192         }
   191 
   193 
   192         // At this point, the child process is not yet launched. Note that
   194         // At this point, the child process is not yet launched. Note that
   193         // TestCommon.exec() and OutputAnalyzer.OutputAnalyzer() both block
   195         // TestCommon.exec() and OutputAnalyzer.OutputAnalyzer() both block
   194         // until the child process has finished.
   196         // until the child process has finished.
   195         //
   197         //
   196         // So, we will launch a AgentAttachThread which will poll the system
   198         // So, we will launch a AgentAttachThread which will poll the flagFile
   197         // until the child process is launched, and then do the attachment.
   199         // until the child process is launched.
   198         // The child process is uniquely identified by having flagFile in its
       
   199         // command-line -- see AgentAttachThread.getPid().
       
   200         AgentAttachThread t = new AgentAttachThread(flagFile, agentJar);
   200         AgentAttachThread t = new AgentAttachThread(flagFile, agentJar);
   201         t.start();
   201         t.start();
   202         return t;
   202         return t;
   203     }
   203     }
   204 
   204 
   223             while (true) {
   223             while (true) {
   224                 // Keep polling until the child process has been launched. If for some
   224                 // Keep polling until the child process has been launched. If for some
   225                 // reason the child process fails to launch, this test will be terminated
   225                 // reason the child process fails to launch, this test will be terminated
   226                 // by JTREG's time-out mechanism.
   226                 // by JTREG's time-out mechanism.
   227                 Thread.sleep(100);
   227                 Thread.sleep(100);
   228                 List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
   228                 File f = new File(flagFile);
   229                 for (VirtualMachineDescriptor vmd : vmds) {
   229                 if (f.exists() && f.length() > 100) {
   230                     if (vmd.displayName().contains(flagFile) && vmd.displayName().contains("InstrumentationApp")) {
   230                     try (FileInputStream in = new FileInputStream(f)) {
   231                         // We use flagFile (which has the PID of this process) as a unique identifier
   231                         Scanner scanner = new Scanner(in);
   232                         // to ident the child process, which we want to attach to.
   232                         return Long.toString(scanner.nextLong());
   233                         System.out.println("Process found: " + vmd.id() + " " + vmd.displayName());
   233                     } catch (Throwable t) {
   234                         return vmd.id();
   234                         // This may happen on Windows if the child process has not
       
   235                         // fully closed the output stream to the flagFile
       
   236                         System.out.println("Ignored: " + t);
       
   237                         t.printStackTrace(System.out);
       
   238                         continue;
   235                     }
   239                     }
   236                 }
   240                 }
   237             }
   241             }
   238         }
   242         }
   239 
   243 
   240         public void run() {
   244         public void run() {
   241             try {
   245             try {
   242                 String pid = getPid(flagFile);
   246                 String pid = getPid(flagFile);
       
   247                 System.out.println("child pid = " + pid);
   243                 VirtualMachine vm = VirtualMachine.attach(pid);
   248                 VirtualMachine vm = VirtualMachine.attach(pid);
   244                 System.out.println(agentJar);
   249                 System.out.println(agentJar);
   245                 vm.loadAgent(agentJar);
   250                 vm.loadAgent(agentJar);
   246             } catch (Throwable t) {
   251             } catch (Throwable t) {
   247                 t.printStackTrace();
   252                 t.printStackTrace();