1 /* 2 * Copyright (c) 1999, 2017, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.jdi; 27 28 import java.lang.ref.WeakReference; 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.Iterator; 32 import java.util.List; 33 34 import com.sun.jdi.ThreadGroupReference; 35 import com.sun.jdi.ThreadReference; 36 import com.sun.jdi.VirtualMachine; 37 38 class VMState { 39 private final VirtualMachineImpl vm; 40 41 // Listeners 42 private final List<WeakReference<VMListener>> listeners = new ArrayList<>(); // synchronized (this) 43 private boolean notifyingListeners = false; // synchronized (this) 44 45 /* 46 * Certain information can be cached only when the entire VM is 47 * suspended and there are no pending resumes. The fields below 48 * are used to track whether there are pending resumes. (There 49 * is an assumption that JDWP command ids are increasing over time.) 50 */ 51 private int lastCompletedCommandId = 0; // synchronized (this) 52 private int lastResumeCommandId = 0; // synchronized (this) 53 54 // This is cached only while the VM is suspended 55 private static class Cache { 56 List<ThreadGroupReference> groups = null; // cached Top Level ThreadGroups 57 List<ThreadReference> threads = null; // cached Threads 58 } 59 60 private Cache cache = null; // synchronized (this) 61 private static final Cache markerCache = new Cache(); 62 63 private void disableCache() { 64 synchronized (this) { 65 cache = null; 66 } 67 } 68 69 private void enableCache() { 70 synchronized (this) { 71 cache = markerCache; 72 } 80 return cache; 81 } 82 } 83 84 VMState(VirtualMachineImpl vm) { 85 this.vm = vm; 86 } 87 88 /** 89 * Is the VM currently suspended, for the purpose of caching? 90 * Must be called synchronized on vm.state() 91 */ 92 boolean isSuspended() { 93 return cache != null; 94 } 95 96 /* 97 * A JDWP command has been completed (reply has been received). 98 * Update data that tracks pending resume commands. 99 */ 100 synchronized void notifyCommandComplete(int id) { 101 lastCompletedCommandId = id; 102 } 103 104 synchronized void freeze() { 105 if (cache == null && (lastCompletedCommandId >= lastResumeCommandId)) { 106 /* 107 * No pending resumes to worry about. The VM is suspended 108 * and additional state can be cached. Notify all 109 * interested listeners. 110 */ 111 processVMAction(new VMAction(vm, VMAction.VM_SUSPENDED)); 112 enableCache(); 113 } 114 } 115 116 synchronized PacketStream thawCommand(CommandSender sender) { 117 PacketStream stream = sender.send(); 118 lastResumeCommandId = stream.id(); 119 thaw(); 120 return stream; 121 } 122 123 /** 124 * All threads are resuming 125 */ 126 void thaw() { 127 thaw(null); 128 } 129 130 /** 131 * Tell listeners to invalidate suspend-sensitive caches. 132 * If resumingThread != null, then only that thread is being 133 * resumed. 134 */ 135 synchronized void thaw(ThreadReference resumingThread) { 136 if (cache != null) { 137 if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) { 138 vm.printTrace("Clearing VM suspended cache"); | 1 /* 2 * Copyright (c) 1999, 2018, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.jdi; 27 28 import java.lang.ref.WeakReference; 29 import java.util.*; 30 31 import com.sun.jdi.ThreadGroupReference; 32 import com.sun.jdi.ThreadReference; 33 import com.sun.jdi.VirtualMachine; 34 35 class VMState { 36 private final VirtualMachineImpl vm; 37 38 // Listeners 39 private final List<WeakReference<VMListener>> listeners = new ArrayList<>(); // synchronized (this) 40 private boolean notifyingListeners = false; // synchronized (this) 41 42 /* 43 * Certain information can be cached only when the entire VM is 44 * suspended and there are no pending resumes. The field below 45 * is used to track whether there are pending resumes. 46 */ 47 private final Set<Integer> pendingResumeCommands = Collections.synchronizedSet(new HashSet<>()); 48 49 // This is cached only while the VM is suspended 50 private static class Cache { 51 List<ThreadGroupReference> groups = null; // cached Top Level ThreadGroups 52 List<ThreadReference> threads = null; // cached Threads 53 } 54 55 private Cache cache = null; // synchronized (this) 56 private static final Cache markerCache = new Cache(); 57 58 private void disableCache() { 59 synchronized (this) { 60 cache = null; 61 } 62 } 63 64 private void enableCache() { 65 synchronized (this) { 66 cache = markerCache; 67 } 75 return cache; 76 } 77 } 78 79 VMState(VirtualMachineImpl vm) { 80 this.vm = vm; 81 } 82 83 /** 84 * Is the VM currently suspended, for the purpose of caching? 85 * Must be called synchronized on vm.state() 86 */ 87 boolean isSuspended() { 88 return cache != null; 89 } 90 91 /* 92 * A JDWP command has been completed (reply has been received). 93 * Update data that tracks pending resume commands. 94 */ 95 void notifyCommandComplete(int id) { 96 pendingResumeCommands.remove(id); 97 } 98 99 synchronized void freeze() { 100 if (cache == null && (pendingResumeCommands.isEmpty())) { 101 /* 102 * No pending resumes to worry about. The VM is suspended 103 * and additional state can be cached. Notify all 104 * interested listeners. 105 */ 106 processVMAction(new VMAction(vm, VMAction.VM_SUSPENDED)); 107 enableCache(); 108 } 109 } 110 111 synchronized PacketStream thawCommand(CommandSender sender) { 112 PacketStream stream = sender.send(); 113 pendingResumeCommands.add(stream.id()); 114 thaw(); 115 return stream; 116 } 117 118 /** 119 * All threads are resuming 120 */ 121 void thaw() { 122 thaw(null); 123 } 124 125 /** 126 * Tell listeners to invalidate suspend-sensitive caches. 127 * If resumingThread != null, then only that thread is being 128 * resumed. 129 */ 130 synchronized void thaw(ThreadReference resumingThread) { 131 if (cache != null) { 132 if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) { 133 vm.printTrace("Clearing VM suspended cache"); |