001/* 002 * ============================================================================ 003 * Copyright © 2002-2026 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * 007 * Licensed to the public under the agreements of the GNU Lesser General Public 008 * License, version 3.0 (the "License"). You may obtain a copy of the License at 009 * 010 * http://www.gnu.org/licenses/lgpl.html 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 015 * License for the specific language governing permissions and limitations 016 * under the License. 017 */ 018 019package org.tquadrat.foundation.perflog; 020 021import static java.lang.Boolean.getBoolean; 022import static java.lang.management.ManagementFactory.getPlatformMBeanServer; 023import static javax.management.MBeanServerFactory.createMBeanServer; 024import static org.apiguardian.api.API.Status.STABLE; 025import static org.tquadrat.foundation.lang.Objects.isNull; 026import static org.tquadrat.foundation.lang.Objects.nonNull; 027import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 028import static org.tquadrat.foundation.perflog.PerformanceTracker.TrackerStatus.STATUS_READY; 029 030import javax.management.MBeanServer; 031import javax.management.MBeanServerFactory; 032import javax.management.ObjectName; 033import java.lang.Thread.UncaughtExceptionHandler; 034import java.util.Optional; 035 036import org.apiguardian.api.API; 037import org.tquadrat.foundation.annotation.ClassVersion; 038import org.tquadrat.foundation.annotation.UtilityClass; 039import org.tquadrat.foundation.exception.PrivateConstructorForStaticClassCalledError; 040import org.tquadrat.foundation.lang.StringConverter; 041import org.tquadrat.foundation.perflog.internal.PerfLogManagerImpl; 042import org.tquadrat.foundation.perflog.internal.PerformanceSectionNameImpl; 043import org.tquadrat.foundation.perflog.internal.PerformanceTrackerImpl; 044import org.tquadrat.foundation.perflog.remote.PerfLogRemote; 045 046/** 047 * <p>{@summary Several tools for the Foundation Performance Logging and 048 * Monitoring.}</p> 049 * 050 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 051 * @version $Id: PerfLogUtils.java 1258 2026-06-04 18:33:06Z tquadrat $ 052 * @since 0.25.0 053 * 054 * @UMLGraph.link 055 */ 056@ClassVersion( sourceVersion = "$Id: PerfLogUtils.java 1258 2026-06-04 18:33:06Z tquadrat $" ) 057@API( status = STABLE, since = "0.25.0" ) 058@UtilityClass 059public final class PerfLogUtils 060{ 061 /*---------------*\ 062 ====** Inner Classes **==================================================== 063 \*---------------*/ 064 /** 065 * <p>{@summary A holder for 066 * {@link PerformanceTracker} 067 * that allows to use it with try-with-resources.}</p> 068 * 069 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 070 * @version $Id: PerfLogUtils.java 1258 2026-06-04 18:33:06Z tquadrat $ 071 * @since 0.25.0 072 * 073 * @UMLGraph.link 074 */ 075 @ClassVersion( sourceVersion = "$Id: PerfLogUtils.java 1258 2026-06-04 18:33:06Z tquadrat $" ) 076 @API( status = STABLE, since = "0.25.0" ) 077 public static final class PerformanceTrackerHolder implements AutoCloseable, PerformanceTracker 078 { 079 /*------------*\ 080 ====** Attributes **==================================================== 081 \*------------*/ 082 /** 083 * The flag that indicates whether 084 * {@link #close()} 085 * was already called on this instance. 086 */ 087 private boolean m_IsClosed = false; 088 089 /** 090 * <p>{@summary The reference to a volatile instance of 091 * {@link PerfLogManager}.}</p> 092 * <p>It is kept here to prevent it from prematurely being garbage 093 * collected.</p> 094 */ 095 private PerfLogManager m_Manager; 096 097 /** 098 * <p>{@summary The wrapped instance of 099 * {@link PerformanceTracker}.}</p> 100 * <p>It can be {@null}.</p> 101 */ 102 private final PerformanceTracker m_Tracker; 103 104 /*--------------*\ 105 ====** Constructors **================================================= 106 \*--------------*/ 107 /** 108 * <p>{@summary Creates a new instance of 109 * {@code PerformanceTrackerHolder} that holds an instance of 110 * {@link PerformanceTracker}.}</p> 111 * 112 * @param tracker The tracker instance to wrap. 113 * @throws ClassCastException If called with an instance of 114 * {@code Holder}. 115 */ 116 private PerformanceTrackerHolder( final PerformanceTrackerImpl tracker ) 117 { 118 m_Tracker = requireNonNullArgument( tracker, "tracker" ); 119 m_Manager = null; 120 } // PerformanceTrackerHolder() 121 122 /** 123 * <p>{@summary Creates a new instance of 124 * {@code PerformanceTrackerHolder} that holds an instance of 125 * {@link PerformanceTracker}, created by calling 126 * {@link PerfLogManager#createPerformanceTracker(PerformanceSectionName)} 127 * on the given 128 * {@link PerfLogManager} 129 * instance with the given 130 * {@link PerformanceSectionName}.}</p> 131 * 132 * @param manager The Performance Logging manager. 133 * @param name The performance section name. 134 */ 135 private PerformanceTrackerHolder( final PerfLogManager manager, final PerformanceSectionName name ) 136 { 137 final var trackerOptional = requireNonNullArgument( manager, "manager" ).createPerformanceTracker( name ); 138 if( trackerOptional.isEmpty() ) 139 { 140 m_Tracker = null; 141 m_Manager = null; 142 } 143 else 144 { 145 m_Tracker = trackerOptional.get(); 146 m_Manager = manager; 147 } 148 } // PerformanceTrackerHolder() 149 150 /** 151 * Creates a new instance of {@code PerformanceTrackerHolder} that 152 * does not hold an instance of 153 * {@link PerformanceTracker}. 154 */ 155 private PerformanceTrackerHolder() 156 { 157 m_Tracker = null; 158 m_Manager = null; 159 } // PerformanceTrackerHolder() 160 161 /*---------*\ 162 ====** Methods **====================================================== 163 \*---------*/ 164 /** 165 * {@inheritDoc} 166 */ 167 @Override 168 public final void abort() 169 { 170 if( nonNull( m_Tracker ) ) m_Tracker.abort(); 171 } // abort() 172 173 /** 174 * {@inheritDoc} 175 */ 176 @Override 177 public void abort( final String message ) 178 { 179 if( nonNull( m_Tracker ) ) m_Tracker.abort( message ); 180 } // abort() 181 182 /** 183 * {@inheritDoc} 184 */ 185 @Override 186 public void abort( final String message, final Throwable cause ) 187 { 188 if( nonNull( m_Tracker ) ) m_Tracker.abort( message, cause ); 189 } // abort() 190 191 /** 192 * {@inheritDoc} 193 */ 194 @Override 195 public final PerformanceTracker addContext( final String name, final String value ) 196 { 197 if( nonNull( m_Tracker ) ) m_Tracker.addContext( name, value ); 198 199 //---* Done *------------------------------------------------------ 200 return this; 201 } // addContext() 202 203 /** 204 * {@inheritDoc} 205 */ 206 @Override 207 public final <T> PerformanceTracker addContext( final String name, final T value, final StringConverter<T> stringConverter ) 208 { 209 if( nonNull( m_Tracker ) ) m_Tracker.addContext( name, value, stringConverter ); 210 211 //---* Done *------------------------------------------------------ 212 return this; 213 } // addContext() 214 215 /** 216 * {@inheritDoc} 217 */ 218 @Override 219 public final void close() 220 { 221 if( isActive() ) 222 { 223 stop(); 224 } 225 else 226 { 227 abort(); 228 } 229 m_IsClosed = true; 230 if( nonNull( m_Manager ) ) 231 { 232 m_Manager.close(); 233 m_Manager = null; 234 } 235 } // close() 236 237 /** 238 * {@inheritDoc} 239 */ 240 @Override 241 public final TrackerStatus getStatus() 242 { 243 final var retValue = isNull( m_Tracker ) ? STATUS_READY : m_Tracker.getStatus(); 244 245 //---* Done *------------------------------------------------------ 246 return retValue; 247 } // getStatus() 248 249 /** 250 * {@inheritDoc} 251 * <p>Throws also an 252 * {@link IllegalStateException} 253 * if this instance of {@code PerformanceTrackerHolder} was already 254 * closed.</p> 255 */ 256 @Override 257 public final PerformanceTracker reset( final boolean resetContext ) throws IllegalArgumentException 258 { 259 if( m_IsClosed ) throw new IllegalStateException( "Holder was already closed" ); 260 if( nonNull( m_Tracker ) ) m_Tracker.reset( resetContext ); 261 262 //---* Done *------------------------------------------------------ 263 return this; 264 } // reset() 265 266 /** 267 * {@inheritDoc} 268 */ 269 @Override 270 public final void start() throws IllegalArgumentException 271 { 272 if( nonNull( m_Tracker ) ) m_Tracker.start(); 273 } // start() 274 275 /** 276 * {@inheritDoc} 277 */ 278 @Override 279 public final void stop() throws IllegalArgumentException 280 { 281 if( nonNull( m_Tracker ) ) m_Tracker.stop(); 282 } // stop() 283 } 284 // class PerformanceTrackerHolder 285 286 /*-----------*\ 287 ====** Constants **======================================================== 288 \*-----------*/ 289 /** 290 * <p>{@summary The domain name part of the 291 * {@link ObjectName} 292 * identifying the 293 * {@link PerfLogMBean} 294 * in the MBean server: {@value PerfLogRemote#DOMAIN_NAME}}.</p> 295 * <p>It is also used for the creation of the MBean server, if a dedicated 296 * MBean server is needed; usually the Platform MBean server is used.</p> 297 * 298 * @see javax.management.MBeanServerFactory#createMBeanServer(String) 299 * @see java.lang.management.ManagementFactory#getPlatformMBeanServer 300 */ 301 public static final String DOMAIN_NAME = PerfLogRemote.DOMAIN_NAME; 302 303 /** 304 * The type for the 305 * {@link ObjectName} 306 * identifying the 307 * {@link PerfLogMBean} 308 * in the MBean server: {@value PerfLogRemote#MBEAN_TYPE}. 309 */ 310 public static final String MBEAN_TYPE = PerfLogRemote.MBEAN_TYPE; 311 312 /** 313 * <p>{@summary The name of the system property that controls whether to 314 * use a dedicated 315 * {@link MBeanServer}: {@value}.}</p> 316 * <p>If not provided or set to {@false}, the platform MBean server 317 * is used.</p> 318 * 319 * @see java.lang.management.ManagementFactory#getPlatformMBeanServer 320 */ 321 @SuppressWarnings( "FieldNamingConvention" ) 322 public static final String SYSTEM_PROPERTY_UsedDedicatedMBeanServer = "org.tquadrat.foundation.perflog.UseDedicatedMBeanServer"; 323 324 /*--------------*\ 325 ====** Constructors **===================================================== 326 \*--------------*/ 327 /** 328 * Not instance allowed for this class! 329 */ 330 private PerfLogUtils() { throw new PrivateConstructorForStaticClassCalledError( PerfLogUtils.class ); } 331 332 /*---------*\ 333 ====** Methods **========================================================== 334 \*---------*/ 335 /** 336 * <p>{@summary Creates an instance of 337 * {@link PerfLogManager} 338 * that handles the connection with the underlying 339 * {@link PerfLogMBean}.}</p> 340 * <p>When called multiple times with references to different 341 * {@linkplain MBeanServer MBean servers}, 342 * each of these calls will create a new instance of 343 * {@link PerfLogMBean}.</p> 344 * 345 * @param mbeanServer The MBean server that holds the 346 * {@code PerfLogMBean}. 347 * @return The new performance logging manager. 348 * 349 * @see #createPerfLogManager() 350 * @see #createPerfLogManager(UncaughtExceptionHandler) 351 * @see #obtainMBeanServer() 352 */ 353 public static final PerfLogManager createPerfLogManager( final MBeanServer mbeanServer ) 354 { 355 final var retValue = new PerfLogManagerImpl( requireNonNullArgument( mbeanServer, "mbeanServer" ), getPerfLogMBeanObjectName() ); 356 357 //---* Done *---------------------------------------------------------- 358 return retValue; 359 } // createPerfLogManager() 360 361 /** 362 * <p>{@summary Creates an instance of 363 * {@link PerfLogManager} 364 * that handles the connection with the underlying 365 * {@link PerfLogMBean}.}</p> 366 * <p>When called multiple times with references to different 367 * {@linkplain MBeanServer MBean servers}, 368 * each of these calls will create a new instance of 369 * {@link PerfLogMBean}.</p> 370 * 371 * @param mbeanServer The MBean server that holds the 372 * {@code PerfLogMBean}. 373 * @param uncaughtExceptionHandler The implementation of 374 * {@link Thread.UncaughtExceptionHandler} 375 * that is used for the timeout monitoring thread. 376 * @return The new performance logging manager. 377 * 378 * @see #createPerfLogManager() 379 * @see #createPerfLogManager(UncaughtExceptionHandler) 380 * @see #obtainMBeanServer() 381 */ 382 @SuppressWarnings( "MethodParameterNamingConvention" ) 383 public static final PerfLogManager createPerfLogManager( final MBeanServer mbeanServer, final UncaughtExceptionHandler uncaughtExceptionHandler ) 384 { 385 final var retValue = new PerfLogManagerImpl( requireNonNullArgument( mbeanServer, "mbeanServer" ), getPerfLogMBeanObjectName(), uncaughtExceptionHandler ); 386 387 //---* Done *---------------------------------------------------------- 388 return retValue; 389 } // createPerfLogManager() 390 391 /** 392 * <p>{@summary Creates an instance of 393 * {@link PerfLogManager} 394 * that handles the connection with the underlying 395 * {@link PerfLogMBean}.}</p> 396 * <p>The method uses the 397 * {@link MBeanServer} 398 * that is returned from 399 * {@link #obtainMBeanServer()}.</p> 400 * 401 * @return The new performance logging manager. 402 */ 403 public static final PerfLogManager createPerfLogManager() 404 { 405 final var mbeanServer = obtainMBeanServer(); 406 final var retValue = createPerfLogManager( mbeanServer ); 407 408 //---* Done *---------------------------------------------------------- 409 return retValue; 410 } // createPerfLogManager() 411 412 /** 413 * <p>{@summary Creates an instance of 414 * {@link PerfLogManager} 415 * that handles the connection with the underlying 416 * {@link PerfLogMBean}.}</p> 417 * <p>The method uses the 418 * {@link MBeanServer} 419 * that is returned from 420 * {@link #obtainMBeanServer()}.</p> 421 * 422 * @param uncaughtExceptionHandler The implementation of 423 * {@link Thread.UncaughtExceptionHandler} 424 * that is used for the timeout monitoring thread. 425 * 426 * @return The new performance logging manager. 427 */ 428 @SuppressWarnings( "MethodParameterNamingConvention" ) 429 public static final PerfLogManager createPerfLogManager( final UncaughtExceptionHandler uncaughtExceptionHandler ) 430 { 431 final var mbeanServer = obtainMBeanServer(); 432 final var retValue = new PerfLogManagerImpl( mbeanServer, getPerfLogMBeanObjectName(), uncaughtExceptionHandler ); 433 434 //---* Done *---------------------------------------------------------- 435 return retValue; 436 } // createPerfLogManager() 437 438 /** 439 * Creates a new instance for an implementation of 440 * {@code PerformanceSectionName} based on the given value. 441 * 442 * @param value The value for the new name. 443 * @return The new name. 444 */ 445 public static PerformanceSectionName createPerformanceSectionName( final String value ) 446 { 447 final var retValue = new PerformanceSectionNameImpl( value ); 448 449 //---* Done *---------------------------------------------------------- 450 return retValue; 451 } // createPerformanceSectionName() 452 453 /** 454 * Returns the 455 * {@link ObjectName} 456 * for the 457 * {@link PerfLogMBean}. 458 * 459 * @return The object name for the performance logging MBean. 460 */ 461 public static final ObjectName getPerfLogMBeanObjectName() { return PerfLogRemote.getPerfLogMBeanObjectName(); } 462 463 /** 464 * <p>{@summary Creates a holder for the given 465 * {@link PerformanceTracker}.}</p> 466 * <p>This is a convenience method that allows to use a performance 467 * tracker with {@code try-with-resources}.</p> 468 * 469 * @param tracker An instance of 470 * {@link Optional} 471 * that holds the tracker. 472 * @return A holder for the given tracker. 473 * @throws ClassCastException If called with an instance of 474 * {@code Holder} instead of a raw 475 * {@link PerformanceTracker}. 476 */ 477 @SuppressWarnings( {"OptionalUsedAsFieldOrParameterType"} ) 478 public static final PerformanceTrackerHolder hold( final Optional<? extends PerformanceTracker> tracker ) 479 { 480 final var retValue = requireNonNullArgument( tracker, "tracker" ).map( v -> new PerformanceTrackerHolder( (PerformanceTrackerImpl) v ) ).orElseGet( PerformanceTrackerHolder::new ); 481 482 //---* Done *---------------------------------------------------------- 483 return retValue; 484 } // hold() 485 486 /** 487 * <p>{@summary Creates a 488 * {@link PerformanceTracker} 489 * for the 490 * {@link PerformanceSection} 491 * with the given 492 * {@linkplain PerformanceSectionName name}.}</p> 493 * <p>It creates an instance of 494 * {@link PerfLogManager} 495 * on the fly, using the 496 * {@link MBeanServer} 497 * returned by 498 * {@link #obtainMBeanServer()}.</p> 499 * <p>This is a convenience method that allows to use a performance 500 * tracker with {@code try-with-resources}.</p> 501 * 502 * @param name The name of the performance section. 503 * @return A holder for the given tracker. 504 */ 505 public static final PerformanceTrackerHolder hold( final PerformanceSectionName name ) 506 { 507 final var retValue = new PerformanceTrackerHolder( createPerfLogManager(), name ); 508 509 //---* Done *---------------------------------------------------------- 510 return retValue; 511 } // hold() 512 513 /** 514 * <p>{@summary Creates a 515 * {@link PerformanceTracker} 516 * for the 517 * {@link PerformanceSection} 518 * with the given 519 * {@linkplain PerformanceSectionName name}.}</p> 520 * <p>This is a convenience method that allows to use a performance 521 * tracker with {@code try-with-resources}.</p> 522 * 523 * @param manager The Performance Logging Manager that connects to the 524 * {@link PerfLogMBean}. 525 * @param name The name of the performance section. 526 * @return A holder for the given tracker. 527 */ 528 public static final PerformanceTrackerHolder hold( final PerfLogManager manager, final PerformanceSectionName name ) 529 { 530 final var retValue = hold( requireNonNullArgument( manager, "manager" ).createPerformanceTracker( name ) ); 531 532 //---* Done *---------------------------------------------------------- 533 return retValue; 534 } // hold() 535 536 /** 537 * <p>{@summary Creates a 538 * {@link PerformanceTracker} 539 * for the 540 * {@link PerformanceSection} 541 * with the given name.}</p> 542 * <p>It creates an instance of 543 * {@link PerfLogManager} 544 * on the fly, using the 545 * {@link MBeanServer} 546 * returned by 547 * {@link #obtainMBeanServer()}.</p> 548 * <p>This is a convenience method that allows to use a performance 549 * tracker with {@code try-with-resources}.</p> 550 * 551 * @param value The name of the performance section. 552 * @return A holder for the given tracker. 553 */ 554 public static final PerformanceTrackerHolder hold( final String value ) 555 { 556 final var retValue = hold( createPerformanceSectionName( value ) ); 557 558 //---* Done *---------------------------------------------------------- 559 return retValue; 560 } // hold() 561 562 /** 563 * <p>{@summary Creates a holder for the given 564 * {@link PerformanceTracker} 565 * and immediately starts it.}</p> 566 * <p>This is a convenience method that allows to use a performance 567 * tracker with {@code try-with-resources}.</p> 568 * 569 * @param tracker An instance of 570 * {@link Optional} 571 * that holds the tracker. 572 * @return A holder for the given tracker. 573 */ 574 @SuppressWarnings( "OptionalUsedAsFieldOrParameterType" ) 575 public static final PerformanceTrackerHolder holdAndStart( final Optional<? extends PerformanceTracker> tracker ) 576 { 577 final var retValue = hold( tracker ); 578 retValue.start(); 579 580 //---* Done *---------------------------------------------------------- 581 return retValue; 582 } // holdAndStart() 583 584 /** 585 * <p>{@summary Creates a 586 * {@link PerformanceTracker} 587 * for the 588 * {@link PerformanceSection} 589 * with the given 590 * {@linkplain PerformanceSectionName name} 591 * and immediately starts it.}</p> 592 * <p>It creates an instance of 593 * {@link PerfLogManager} 594 * on the fly, using the 595 * {@link MBeanServer} 596 * returned by 597 * {@link #obtainMBeanServer()}.</p> 598 * <p>This is a convenience method that allows to use a performance 599 * tracker with {@code try-with-resources}.</p> 600 * 601 * @param name The name of the performance section. 602 * @return A holder for the given tracker. 603 */ 604 public static final PerformanceTrackerHolder holdAndStart( final PerformanceSectionName name ) 605 { 606 final var retValue = hold( name ); 607 retValue.start(); 608 609 //---* Done *---------------------------------------------------------- 610 return retValue; 611 } // holdAndStart() 612 613 /** 614 * <p>{@summary Creates a 615 * {@link PerformanceTracker} 616 * for the 617 * {@link PerformanceSection} 618 * with the given 619 * {@linkplain PerformanceSectionName name} 620 * and immediately starts it.}</p> 621 * <p>It creates an instance of 622 * {@link PerfLogManager} 623 * on the fly, using the 624 * {@link MBeanServer} 625 * returned by 626 * {@link #obtainMBeanServer()}.</p> 627 * <p>This is a convenience method that allows to use a performance 628 * tracker with {@code try-with-resources}.</p> 629 * 630 * @param manager The Performance Logging Manager that connects to the 631 * {@link PerfLogMBean}. 632 * @param name The name of the performance section. 633 * @return A holder for the given tracker. 634 */ 635 public static final PerformanceTrackerHolder holdAndStart( final PerfLogManager manager, final PerformanceSectionName name ) 636 { 637 final var retValue = hold( manager, name ); 638 retValue.start(); 639 640 //---* Done *---------------------------------------------------------- 641 return retValue; 642 } // holdAndStart() 643 644 /** 645 * <p>{@summary Creates a 646 * {@link PerformanceTracker} 647 * for the 648 * {@link PerformanceSection} 649 * with the given name and immediately starts it.}</p> 650 * <p>It creates an instance of 651 * {@link PerfLogManager} 652 * on the fly, using the 653 * {@link MBeanServer} 654 * returned by 655 * {@link #obtainMBeanServer()}.</p> 656 * <p>This is a convenience method that allows to use a performance 657 * tracker with {@code try-with-resources}.</p> 658 * 659 * @param value The name of the performance section. 660 * @return A holder for the given tracker. 661 */ 662 public static final PerformanceTrackerHolder holdAndStart( final String value ) 663 { 664 final var retValue = hold( value ); 665 retValue.start(); 666 667 //---* Done *---------------------------------------------------------- 668 return retValue; 669 } // holdAndStart() 670 671 /** 672 * <p>{@summary Retrieves the 673 * {@link MBeanServer} 674 * that is used for the registration of the 675 * {@link PerfLogMBean}.}</p> 676 * <p>If the system property 677 * {@value #SYSTEM_PROPERTY_UsedDedicatedMBeanServer} 678 * is set to {@true}, a dedicated MBean server for the domain 679 * {@value PerfLogRemote#DOMAIN_NAME} 680 * will be used, otherwise the MBean server that is returned by 681 * {@link java.lang.management.ManagementFactory#getPlatformMBeanServer()} 682 * is returned.</p> 683 * 684 * @return The MBean server. 685 * 686 * @see #SYSTEM_PROPERTY_UsedDedicatedMBeanServer 687 */ 688 public static final MBeanServer obtainMBeanServer() 689 { 690 final MBeanServer retValue; 691 //noinspection AccessOfSystemProperties 692 if( getBoolean( SYSTEM_PROPERTY_UsedDedicatedMBeanServer ) ) 693 { 694 retValue = MBeanServerFactory.findMBeanServer( null ) 695 .stream() 696 .filter( mbs -> mbs.getDefaultDomain().equals( DOMAIN_NAME ) ) 697 .findFirst() 698 .orElseGet( () -> createMBeanServer( DOMAIN_NAME ) ); 699 } 700 else 701 { 702 retValue = getPlatformMBeanServer(); 703 } 704 705 //---* Done *---------------------------------------------------------- 706 return retValue; 707 } // obtainMBeanServer() 708} 709// class PerfLogUtils 710 711/* 712 * End of File 713 */