hotspot/test/serviceability/jvmti/8036666/GetObjectLockCount.java
changeset 23518 00028482ef09
child 35594 cc13089c6327
equal deleted inserted replaced
23517:27c4307d6cda 23518:00028482ef09
       
     1 /*
       
     2  * Copyright 2014 SAP AG.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     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
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 import java.io.BufferedReader;
       
    25 import java.io.IOException;
       
    26 import java.io.InputStream;
       
    27 import java.io.InputStreamReader;
       
    28 import java.util.Iterator;
       
    29 import java.util.List;
       
    30 import java.util.Map;
       
    31 
       
    32 import com.sun.jdi.AbsentInformationException;
       
    33 import com.sun.jdi.Bootstrap;
       
    34 import com.sun.jdi.LocalVariable;
       
    35 import com.sun.jdi.Location;
       
    36 import com.sun.jdi.ObjectReference;
       
    37 import com.sun.jdi.ReferenceType;
       
    38 import com.sun.jdi.StackFrame;
       
    39 import com.sun.jdi.ThreadReference;
       
    40 import com.sun.jdi.Value;
       
    41 import com.sun.jdi.VirtualMachine;
       
    42 import com.sun.jdi.connect.Connector;
       
    43 import com.sun.jdi.connect.Connector.Argument;
       
    44 import com.sun.jdi.connect.IllegalConnectorArgumentsException;
       
    45 import com.sun.jdi.connect.LaunchingConnector;
       
    46 import com.sun.jdi.connect.VMStartException;
       
    47 import com.sun.jdi.event.BreakpointEvent;
       
    48 import com.sun.jdi.event.ClassPrepareEvent;
       
    49 import com.sun.jdi.event.Event;
       
    50 import com.sun.jdi.event.EventQueue;
       
    51 import com.sun.jdi.event.EventSet;
       
    52 import com.sun.jdi.event.VMDeathEvent;
       
    53 import com.sun.jdi.event.VMDisconnectEvent;
       
    54 import com.sun.jdi.event.VMStartEvent;
       
    55 import com.sun.jdi.request.BreakpointRequest;
       
    56 import com.sun.jdi.request.ClassPrepareRequest;
       
    57 import com.sun.jdi.request.EventRequestManager;
       
    58 
       
    59 
       
    60 /*
       
    61  * @test GetObjectLockCount.java
       
    62  * @bug 8036666
       
    63  * @key regression
       
    64  * @summary verify jvm returns correct lock recursion count
       
    65  * @run compile -g RecursiveObjectLock.java
       
    66  * @run main/othervm GetObjectLockCount
       
    67  * @author axel.siebenborn@sap.com
       
    68  */
       
    69 
       
    70 public class GetObjectLockCount {
       
    71 
       
    72     public static final String CLASS_NAME  = "RecursiveObjectLock";
       
    73     public static final String METHOD_NAME = "breakpoint1";
       
    74     public static final String ARGUMENTS = "";
       
    75 
       
    76 
       
    77     /**
       
    78      * Find a com.sun.jdi.CommandLineLaunch connector
       
    79      */
       
    80     static LaunchingConnector findLaunchingConnector() {
       
    81         List <Connector> connectors = Bootstrap.virtualMachineManager().allConnectors();
       
    82         Iterator <Connector> iter = connectors.iterator();
       
    83         while (iter.hasNext()) {
       
    84             Connector connector = iter.next();
       
    85             if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) {
       
    86                 return (LaunchingConnector)connector;
       
    87             }
       
    88         }
       
    89         throw new Error("No launching connector");
       
    90     }
       
    91 
       
    92     static VirtualMachine launchTarget(String mainArgs) {
       
    93         LaunchingConnector connector = findLaunchingConnector();
       
    94         Map<String, Argument>  arguments = connectorArguments(connector, mainArgs);
       
    95         try {
       
    96             return (VirtualMachine) connector.launch(arguments);
       
    97         } catch (IOException exc) {
       
    98             throw new Error("Unable to launch target VM: " + exc);
       
    99         } catch (IllegalConnectorArgumentsException exc) {
       
   100             throw new Error("Internal error: " + exc);
       
   101         } catch (VMStartException exc) {
       
   102             throw new Error("Target VM failed to initialize: " +
       
   103                     exc.getMessage());
       
   104         }
       
   105     }
       
   106     /**
       
   107      * Return the launching connector's arguments.
       
   108      */
       
   109     static Map <String,Connector.Argument> connectorArguments(LaunchingConnector connector, String mainArgs) {
       
   110         Map<String,Connector.Argument> arguments = connector.defaultArguments();
       
   111 
       
   112         Connector.Argument mainArg = (Connector.Argument)arguments.get("main");
       
   113         if (mainArg == null) {
       
   114             throw new Error("Bad launching connector");
       
   115         }
       
   116         mainArg.setValue(mainArgs);
       
   117 
       
   118         Connector.Argument optionsArg = (Connector.Argument)arguments.get("options");
       
   119         if (optionsArg == null) {
       
   120             throw new Error("Bad launching connector");
       
   121         }
       
   122         optionsArg.setValue(ARGUMENTS);
       
   123         return arguments;
       
   124     }
       
   125 
       
   126     private static void addClassWatch(VirtualMachine vm) {
       
   127         EventRequestManager erm = vm.eventRequestManager();
       
   128         ClassPrepareRequest classPrepareRequest = erm
       
   129                 .createClassPrepareRequest();
       
   130         classPrepareRequest.addClassFilter(CLASS_NAME);
       
   131         classPrepareRequest.setEnabled(true);
       
   132     }
       
   133 
       
   134     private static void addBreakpoint(VirtualMachine vm, ReferenceType refType) {
       
   135         Location breakpointLocation = null;
       
   136         List<Location> locs;
       
   137         try {
       
   138             locs = refType.allLineLocations();
       
   139             for (Location loc: locs) {
       
   140                 if (loc.method().name().equals(METHOD_NAME)) {
       
   141                     breakpointLocation = loc;
       
   142                     break;
       
   143                 }
       
   144             }
       
   145         } catch (AbsentInformationException e) {
       
   146             // TODO Auto-generated catch block
       
   147             e.printStackTrace();
       
   148         }
       
   149         if (breakpointLocation != null) {
       
   150             EventRequestManager evtReqMgr = vm.eventRequestManager();
       
   151             BreakpointRequest bReq = evtReqMgr.createBreakpointRequest(breakpointLocation);
       
   152             bReq.setSuspendPolicy(BreakpointRequest.SUSPEND_ALL);
       
   153             bReq.enable();
       
   154         }
       
   155     }
       
   156 
       
   157     /**
       
   158      * @param args
       
   159      * @throws InterruptedException
       
   160      */
       
   161     public static void main(String[] args) throws InterruptedException  {
       
   162 
       
   163         VirtualMachine vm = launchTarget(CLASS_NAME);
       
   164 
       
   165         // process events
       
   166         EventQueue eventQueue = vm.eventQueue();
       
   167         // resume the vm
       
   168         boolean launched = false;
       
   169 
       
   170         while (!launched) {
       
   171             EventSet eventSet = eventQueue.remove();
       
   172             for (Event event : eventSet) {
       
   173                 if (event instanceof VMStartEvent) {
       
   174                     System.out.println("Vm launched");
       
   175                     // set watch field on already loaded classes
       
   176                     List<ReferenceType> referenceTypes = vm.classesByName(CLASS_NAME);
       
   177                     for (ReferenceType refType : referenceTypes) {
       
   178                         System.out.println("Found Class");
       
   179                         addBreakpoint(vm, refType);
       
   180                     }
       
   181 
       
   182                     // watch for loaded classes
       
   183                     addClassWatch(vm);
       
   184                     vm.resume();
       
   185                     launched = true;
       
   186                 }
       
   187             }
       
   188         }
       
   189 
       
   190         Process process = vm.process();
       
   191 
       
   192         // Copy target's output and error to our output and error.
       
   193         Thread outThread = new StreamRedirectThread("out reader", process.getInputStream());
       
   194         Thread errThread = new StreamRedirectThread("error reader", process.getErrorStream());
       
   195 
       
   196         int recursionCount = -1;
       
   197 
       
   198         errThread.start();
       
   199         outThread.start();
       
   200         boolean connected = true;
       
   201         while (connected) {
       
   202             EventSet eventSet = eventQueue.remove();
       
   203             for (Event event : eventSet) {
       
   204                 if (event instanceof VMDeathEvent || event instanceof VMDisconnectEvent) {
       
   205                     // exit
       
   206                     connected = false;
       
   207                 }
       
   208                 else if (event instanceof ClassPrepareEvent) {
       
   209                     // watch field on loaded class
       
   210                     System.out.println("ClassPrepareEvent");
       
   211                     ClassPrepareEvent classPrepEvent = (ClassPrepareEvent) event;
       
   212                     ReferenceType refType = classPrepEvent.referenceType();
       
   213                     addBreakpoint(vm, refType);
       
   214                 } else if (event instanceof BreakpointEvent) {
       
   215                     recursionCount = getLockRecursions(vm);
       
   216                     System.out.println("resume...");
       
   217                 }
       
   218             }
       
   219             eventSet.resume();
       
   220         }
       
   221         // Shutdown begins when event thread terminates
       
   222         try {
       
   223             errThread.join(); // Make sure output is forwarded
       
   224             outThread.join();
       
   225         } catch (InterruptedException e) {
       
   226             // we don't interrupt
       
   227             e.printStackTrace();
       
   228         }
       
   229         if (recursionCount != 3) {
       
   230             throw new AssertionError("recursions: expected 3, but was " + recursionCount);
       
   231         }
       
   232     }
       
   233 
       
   234     public static int getLockRecursions(VirtualMachine vm) {
       
   235         List <ThreadReference> threads = vm.allThreads();
       
   236         for (ThreadReference thread : threads) {
       
   237             if (thread.name().equals("main")) {
       
   238 
       
   239                 System.out.println("Found main thread.");
       
   240                 try{
       
   241                     StackFrame frame = thread.frame(3);
       
   242                     return frame.thisObject().entryCount();
       
   243                 } catch (Exception e) {
       
   244                     e.printStackTrace();
       
   245                 }
       
   246             }
       
   247             System.out.println("Main thread not found!");
       
   248         }
       
   249         return -1;
       
   250     }
       
   251 }
       
   252 
       
   253 class StreamRedirectThread extends Thread {
       
   254 
       
   255     private final BufferedReader in;
       
   256 
       
   257     private static final int BUFFER_SIZE = 2048;
       
   258 
       
   259     /**
       
   260      * Set up for copy.
       
   261      * @param name  Name of the thread
       
   262      * @param in    Stream to copy from
       
   263      */
       
   264     StreamRedirectThread(String name, InputStream in) {
       
   265         super(name);
       
   266         this.in = new BufferedReader(new InputStreamReader(in));
       
   267     }
       
   268 
       
   269     /**
       
   270      * Copy.
       
   271      */
       
   272     public void run() {
       
   273         try {
       
   274             String line;
       
   275             while ((line = in.readLine ()) != null) {
       
   276                 System.out.println("testvm: " + line);
       
   277             }
       
   278             System.out.flush();
       
   279         } catch(IOException exc) {
       
   280             System.err.println("Child I/O Transfer - " + exc);
       
   281             exc.printStackTrace();
       
   282         }
       
   283     }
       
   284 }