/** {@inheritDoc} */ protected void getNewMonitors(Map<String, Monitor> map) throws MonitorException { assert Thread.holdsLock(this); int used = prologue.getUsed(); long modificationTime = prologue.getModificationTimeStamp(); if ((used > lastUsed) || (lastModificationTime > modificationTime)) { lastUsed = used; lastModificationTime = modificationTime; Monitor monitor = getNextMonitorEntry(); while (monitor != null) { String name = monitor.getName(); // guard against duplicate entries if (!map.containsKey(name)) { map.put(name, monitor); /* * insertedMonitors is null when called from pollFor() * via buildMonitorMap(). Since we update insertedMonitors * at the end of buildMonitorMap(), it's ok to skip the * add here. */ if (insertedMonitors != null) { insertedMonitors.add(monitor); } } monitor = getNextMonitorEntry(); } } }
/** * method to make adjustments for known counter problems. This method depends on the availability * of certain counters, which is generally guaranteed by the synchWithTarget() method. */ protected void kludge(Map<String, Monitor> map) { if (Boolean.getBoolean("sun.jvmstat.perfdata.disableKludge")) { // bypass all kludges return; } String name = "java.vm.version"; StringMonitor jvm_version = (StringMonitor) map.get(name); if (jvm_version == null) { jvm_version = (StringMonitor) findByAlias(name); } name = "java.vm.name"; StringMonitor jvm_name = (StringMonitor) map.get(name); if (jvm_name == null) { jvm_name = (StringMonitor) findByAlias(name); } name = "hotspot.vm.args"; StringMonitor args = (StringMonitor) map.get(name); if (args == null) { args = (StringMonitor) findByAlias(name); } assert ((jvm_name != null) && (jvm_version != null) && (args != null)); if (jvm_name.stringValue().indexOf("HotSpot") >= 0) { if (jvm_version.stringValue().startsWith("1.4.2")) { kludgeMantis(map, args); } } }
/** Method to dump debugging information */ private void dumpAll(Map map, int lvmid) { if (DEBUG) { Set keys = map.keySet(); System.err.println("Dump for " + lvmid); int j = 0; for (Iterator i = keys.iterator(); i.hasNext(); j++) { Monitor monitor = (Monitor) map.get(i.next()); System.err.println(j + "\t" + monitor.getName() + "=" + monitor.getValue()); } System.err.println("nextEntry = " + nextEntry + " pollForEntry = " + pollForEntry); System.err.println("Buffer info:"); System.err.println("buffer = " + buffer); } }
/** * Method to poll the instrumentation memory for a counter with the given name. The polling period * is bounded by the timeLimit argument. */ protected Monitor pollFor(Map<String, Monitor> map, String name, long timeLimit) throws MonitorException { Monitor monitor = null; log("polling for: " + lvmid + "," + name + " "); pollForEntry = nextEntry; while ((monitor = map.get(name)) == null) { log("."); try { Thread.sleep(20); } catch (InterruptedException e) { } long t = System.currentTimeMillis(); if ((t > timeLimit) || (overflow.intValue() > 0)) { lognl("failed: " + lvmid + "," + name); dumpAll(map, lvmid); throw new MonitorException("Could not find expected counter"); } getNewMonitors(map); } lognl("success: " + lvmid + "," + name); return monitor; }
/** {@inheritDoc} */ protected void buildMonitorMap(Map<String, Monitor> map) throws MonitorException { assert Thread.holdsLock(this); // start at the beginning of the buffer buffer.rewind(); // create pseudo monitors buildPseudoMonitors(map); // position buffer to start of the data section buffer.position(prologue.getSize()); nextEntry = buffer.position(); perfDataItem = 0; int used = prologue.getUsed(); long modificationTime = prologue.getModificationTimeStamp(); Monitor m = getNextMonitorEntry(); while (m != null) { map.put(m.getName(), m); m = getNextMonitorEntry(); } /* * set the last modification data. These are set to the values * recorded before parsing the data structure. This allows the * the data structure to be modified while the Map is being built. * The Map may contain more entries than indicated based on the * time stamp, but this is handled by ignoring duplicate entries * when the Map is updated in getNewMonitors(). */ lastUsed = used; lastModificationTime = modificationTime; // synchronize with the target jvm synchWithTarget(map); // work around 1.4.2 counter inititization bugs kludge(map); insertedMonitors = new ArrayList<Monitor>(map.values()); }
/** Build the pseudo monitors used to map the prolog data into counters. */ protected void buildPseudoMonitors(Map<String, Monitor> map) { Monitor monitor = null; String name = null; IntBuffer ib = null; name = PerfDataBufferPrologue.PERFDATA_MAJOR_NAME; ib = prologue.majorVersionBuffer(); monitor = new PerfIntegerMonitor(name, Units.NONE, Variability.CONSTANT, false, ib); map.put(name, monitor); name = PerfDataBufferPrologue.PERFDATA_MINOR_NAME; ib = prologue.minorVersionBuffer(); monitor = new PerfIntegerMonitor(name, Units.NONE, Variability.CONSTANT, false, ib); map.put(name, monitor); name = PerfDataBufferPrologue.PERFDATA_BUFFER_SIZE_NAME; ib = prologue.sizeBuffer(); monitor = new PerfIntegerMonitor(name, Units.BYTES, Variability.MONOTONIC, false, ib); map.put(name, monitor); name = PerfDataBufferPrologue.PERFDATA_BUFFER_USED_NAME; ib = prologue.usedBuffer(); monitor = new PerfIntegerMonitor(name, Units.BYTES, Variability.MONOTONIC, false, ib); map.put(name, monitor); name = PerfDataBufferPrologue.PERFDATA_OVERFLOW_NAME; ib = prologue.overflowBuffer(); monitor = new PerfIntegerMonitor(name, Units.BYTES, Variability.MONOTONIC, false, ib); map.put(name, monitor); this.overflow = (IntegerMonitor) monitor; name = PerfDataBufferPrologue.PERFDATA_MODTIMESTAMP_NAME; LongBuffer lb = prologue.modificationTimeStampBuffer(); monitor = new PerfLongMonitor(name, Units.TICKS, Variability.MONOTONIC, false, lb); map.put(name, monitor); }
/** * method to repair the 1.4.2 parallel scavenge counters that are incorrectly initialized by the * JVM when UseAdaptiveSizePolicy is set. This bug couldn't be fixed for 1.4.2 FCS due to putback * restrictions. */ private void kludgeMantis(Map<String, Monitor> map, StringMonitor args) { /* * the HotSpot 1.4.2 JVM with the +UseParallelGC option along * with its default +UseAdaptiveSizePolicy option has a bug with * the initialization of the sizes of the eden and survivor spaces. * See bugid 4890736. * * note - use explicit 1.4.2 counter names here - don't update * to latest counter names or attempt to find aliases. */ String cname = "hotspot.gc.collector.0.name"; StringMonitor collector = (StringMonitor) map.get(cname); if (collector.stringValue().compareTo("PSScavenge") == 0) { boolean adaptiveSizePolicy = true; /* * HotSpot processes the -XX:Flags/.hotspotrc arguments prior to * processing the command line arguments. This allows the command * line arguments to override any defaults set in .hotspotrc */ cname = "hotspot.vm.flags"; StringMonitor flags = (StringMonitor) map.get(cname); String allArgs = flags.stringValue() + " " + args.stringValue(); /* * ignore the -XX: prefix as it only applies to the arguments * passed from the command line (i.e. the invocation api). * arguments passed through .hotspotrc omit the -XX: prefix. */ int ahi = allArgs.lastIndexOf("+AggressiveHeap"); int aspi = allArgs.lastIndexOf("-UseAdaptiveSizePolicy"); if (ahi != -1) { /* * +AggressiveHeap was set, check if -UseAdaptiveSizePolicy * is set after +AggressiveHeap. */ // if ((aspi != -1) && (aspi > ahi)) { adaptiveSizePolicy = false; } } else { /* * +AggressiveHeap not set, must be +UseParallelGC. The * relative position of -UseAdaptiveSizePolicy is not * important in this case, as it will override the * UseParallelGC default (+UseAdaptiveSizePolicy) if it * appears anywhere in the JVM arguments. */ if (aspi != -1) { adaptiveSizePolicy = false; } } if (adaptiveSizePolicy) { // adjust the buggy AdaptiveSizePolicy size counters. // first remove the real counters. String eden_size = "hotspot.gc.generation.0.space.0.size"; String s0_size = "hotspot.gc.generation.0.space.1.size"; String s1_size = "hotspot.gc.generation.0.space.2.size"; map.remove(eden_size); map.remove(s0_size); map.remove(s1_size); // get the maximum new generation size String new_max_name = "hotspot.gc.generation.0.capacity.max"; LongMonitor new_max = (LongMonitor) map.get(new_max_name); /* * replace the real counters with pseudo counters that are * initialized to to the correct values. The maximum size of * the eden and survivor spaces are supposed to be: * max_eden_size = new_size - (2*alignment). * max_survivor_size = new_size - (2*alignment). * since we don't know the alignment value used, and because * of other parallel scavenge bugs that result in oversized * spaces, we just set the maximum size of each space to the * full new gen size. */ Monitor monitor = null; LongBuffer lb = LongBuffer.allocate(1); lb.put(new_max.longValue()); monitor = new PerfLongMonitor(eden_size, Units.BYTES, Variability.CONSTANT, false, lb); map.put(eden_size, monitor); monitor = new PerfLongMonitor(s0_size, Units.BYTES, Variability.CONSTANT, false, lb); map.put(s0_size, monitor); monitor = new PerfLongMonitor(s1_size, Units.BYTES, Variability.CONSTANT, false, lb); map.put(s1_size, monitor); } } }