All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oshi.hardware.CentralProcessor Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016-2022 The OSHI Project Contributors
 * SPDX-License-Identifier: MIT
 */
package oshi.hardware;

import static oshi.util.Memoizer.memoize;

import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import oshi.annotation.concurrent.Immutable;
import oshi.annotation.concurrent.ThreadSafe;
import oshi.software.os.OSProcess;
import oshi.software.os.OSThread;
import oshi.util.Constants;
import oshi.util.FileUtil;
import oshi.util.ParseUtil;
import oshi.util.Util;

/**
 * This class represents the entire Central Processing Unit (CPU) of a computer system, which may contain one or more
 * physical packages (sockets), one or more physical processors (cores), and one or more logical processors (what the
 * Operating System sees, which may include hyperthreaded cores.)
 */
@ThreadSafe
public interface CentralProcessor {

    /**
     * The CPU's identifier strings ,including name, vendor, stepping, model, and family information (also called the
     * signature of a CPU).
     * 

* The Processor Identifier is primarily associated with Intel-based chips. Attempts are made to provide comparable * values for other chip manufacturers. * * @return a {@link ProcessorIdentifier} object encapsulating CPU identifier information. */ ProcessorIdentifier getProcessorIdentifier(); /** * Maximum frequeny (in Hz), of the logical processors on this CPU. * * @return The max frequency or -1 if unknown. */ long getMaxFreq(); /** * Attempts to return the current frequency (in Hz), of the logical processors on this CPU. *

* May not be implemented on all Operating Systems. *

* On Windows, returns an estimate based on the percent of maximum frequency. On Windows systems with more than 64 * logical processors, may only return frequencies for the current processor group in the first portion of the * array. * * @return An array of processor frequencies for each logical processor on the system. Use the * {@link #getLogicalProcessors()} to correlate these frequencies with physical packages and processors. */ long[] getCurrentFreq(); /** * Returns an {@code UnmodifiableList} of the CPU's logical processors. The list will be sorted in order of * increasing NUMA node number, and then processor number. This order is (usually) consistent with other methods * providing per-processor results. *

* On some operating systems with variable numbers of logical processors, the size of this array could change and * may not align with other per-processor methods. * * @return An {@code UnmodifiabeList} of logical processors. */ List getLogicalProcessors(); /** * Returns an {@code UnmodifiableList} of the CPU's physical processors. The list will be sorted in order of * increasing core ID. * * @return An {@code UnmodifiabeList} of physical processors. */ List getPhysicalProcessors(); /** * Makes a best-effort attempt to identify the CPU's processor caches. For hybrid processors, both performance and * efficiency core caches are shown. Only one instance of per-core caches is shown. *

* Values are unreliable in virtual machines and rely in information made available by the VM or hypervisor. Callers * should conduct sanity checking of the returned objects. Not all values are available on all operating systems or * architectures. *

* Not available on Solaris. * * @return An {@code UnmodifiabeList} of processor caches. */ List getProcessorCaches(); /** * Returns the "recent cpu usage" for the whole system by counting ticks from {@link #getSystemCpuLoadTicks()} * between the user-provided value from a previous call. *

* On some operating systems with variable numbers of logical processors, the size of the array returned from a * previous call to {@link #getSystemCpuLoadTicks()} could change and will throw an * {@link IllegalArgumentException}. Calling code on these operating systems should handle this exception. * * @param oldTicks A tick array from a previous call to {@link #getSystemCpuLoadTicks()} * @return CPU load between 0 and 1 (100%) * @throws IllegalArgumentException if the array sizes differ. */ double getSystemCpuLoadBetweenTicks(long[] oldTicks); /** * Get System-wide CPU Load tick counters. Returns an array with eight elements representing milliseconds spent in * User (0), Nice (1), System (2), Idle (3), IOwait (4), Hardware interrupts (IRQ) (5), Software interrupts/DPC * (SoftIRQ) (6), or Steal (7) states. Use {@link oshi.hardware.CentralProcessor.TickType#getIndex()} to retrieve * the appropriate index. By measuring the difference between ticks across a time interval, CPU load over that * interval may be calculated. *

* On some operating systems with variable numbers of logical processors, the size of this array could change and * may not align with other per-processor methods. *

* Note that while tick counters are in units of milliseconds, they may advance in larger increments along with * (platform dependent) clock ticks. For example, by default Windows clock ticks are 1/64 of a second (about 15 or * 16 milliseconds) and Linux ticks are distribution and configuration dependent but usually 1/100 of a second (10 * milliseconds). *

* Nice and IOWait information is not available on Windows, and IOwait and IRQ information is not available on * macOS, so these ticks will always be zero. *

* To calculate overall Idle time using this method, include both Idle and IOWait ticks. Similarly, IRQ, SoftIRQ, * and Steal ticks should be added to the System value to get the total. System ticks also include time executing * other virtual hosts (steal). * * @return An array of 8 long values representing time spent in User, Nice, System, Idle, IOwait, IRQ, SoftIRQ, and * Steal states. */ long[] getSystemCpuLoadTicks(); /** * Returns the system load average for the number of elements specified, up to 3, representing 1, 5, and 15 minutes. * The system load average is the sum of the number of runnable entities queued to the available processors and the * number of runnable entities running on the available processors averaged over a period of time. *

* This method is designed to provide a hint about the system load and may be queried frequently. *

* The way in which the load average is calculated is operating system specific but is typically a damped * time-dependent average. Linux includes processes waiting for system resources such as disks, while macOS and Unix * consider only processes waiting for CPU. *

* Windows does not provide a load average. Users may set the configuration property * {@code oshi.os.windows.loadaverage} to {@code true} to start a daemon thread which will provide a similar metric. *

* The load average may be unavailable on some platforms (e.g., Windows without the above configuration). If the * load average is not available, a negative value is returned. * * @param nelem Number of elements to return. * @return an array of the system load averages for 1, 5, and 15 minutes with the size of the array specified by * nelem; or negative values if not available. */ double[] getSystemLoadAverage(int nelem); /** * This is a convenience method which collects an initial set of ticks using {@link #getSystemCpuLoadTicks()} and * passes that result to {@link #getSystemCpuLoadBetweenTicks(long[])} after the specified delay. * * * @param delay Milliseconds to wait. * @return value between 0 and 1 (100%) that represents the cpu usage in the provided time period. */ default double getSystemCpuLoad(long delay) { long start = System.nanoTime(); long[] oldTicks = getSystemCpuLoadTicks(); long toWait = delay - (System.nanoTime() - start) / 1_000_000; // protect against IllegalArgumentException if (toWait > 0L) { Util.sleep(delay); } return getSystemCpuLoadBetweenTicks(oldTicks); } /** * This is a convenience method which collects an initial set of ticks using {@link #getProcessorCpuLoadTicks()} and * passes that result to {@link #getProcessorCpuLoadBetweenTicks(long[][])} after the specified delay. *

* On some operating systems with variable numbers of logical processors, the size of the array returned from the * two calls could change and will throw an {@link IllegalArgumentException}. Calling code on these operating * systems should handle this exception. * * @param delay Milliseconds to wait. * @return array of CPU load between 0 and 1 (100%) for each logical processor, for the provided time period. * @throws IllegalArgumentException if the array sizes differ between calls. */ default double[] getProcessorCpuLoad(long delay) { long start = System.nanoTime(); long[][] oldTicks = getProcessorCpuLoadTicks(); long toWait = delay - (System.nanoTime() - start) / 1_000_000; // protect against IllegalArgumentException if (toWait > 0L) { Util.sleep(delay); } return getProcessorCpuLoadBetweenTicks(oldTicks); } /** * Returns the "recent cpu usage" for all logical processors by counting ticks from * {@link #getProcessorCpuLoadTicks()} between the user-provided value from a previous call. *

* On some operating systems with variable numbers of logical processors, the size of the array returned from the * two calls could change and will throw an {@link IllegalArgumentException}. Calling code on these operating * systems should handle this exception. * * @param oldTicks A tick array from a previous call to {@link #getProcessorCpuLoadTicks()} * @return array of CPU load between 0 and 1 (100%) for each logical processor * @throws IllegalArgumentException if the array sizes differ between calls. */ double[] getProcessorCpuLoadBetweenTicks(long[][] oldTicks); /** * Get Processor CPU Load tick counters. Returns a two dimensional array, with {@link #getLogicalProcessorCount()} * arrays, each containing seven elements representing milliseconds spent in User (0), Nice (1), System (2), Idle * (3), IOwait (4), Hardware interrupts (IRQ) (5), Software interrupts/DPC (SoftIRQ) (6), or Steal (7) states. Use * {@link oshi.hardware.CentralProcessor.TickType#getIndex()} to retrieve the appropriate index. By measuring the * difference between ticks across a time interval, CPU load over that interval may be calculated. *

* Note that while tick counters are in units of milliseconds, they may advance in larger increments along with * (platform dependent) clock ticks. For example, by default Windows clock ticks are 1/64 of a second (about 15 or * 16 milliseconds) and Linux ticks are distribution and configuration dependent but usually 1/100 of a second (10 * milliseconds). *

* Nice and IOwait per processor information is not available on Windows, and IOwait and IRQ information is not * available on macOS, so these ticks will always be zero. *

* To calculate overall Idle time using this method, include both Idle and IOWait ticks. Similarly, IRQ, SoftIRQ and * Steal ticks should be added to the System value to get the total. System ticks also include time executing other * virtual hosts (steal). * * @return A 2D array of logicalProcessorCount x 7 long values representing time spent in User, Nice, System, Idle, * IOwait, IRQ, SoftIRQ, and Steal states. */ long[][] getProcessorCpuLoadTicks(); /** * Get the number of logical CPUs available for processing. This value may be higher than physical CPUs if * hyperthreading is enabled. *

* On some operating systems with variable numbers of logical processors, may return a max value. * * @return The number of logical CPUs available. */ int getLogicalProcessorCount(); /** * Get the number of physical CPUs/cores available for processing. *

* On some operating systems with variable numbers of physical processors available to the OS, may return a max * value. * * @return The number of physical CPUs available. */ int getPhysicalProcessorCount(); /** * Get the number of packages/sockets in the system. A single package may contain multiple cores. * * @return The number of physical packages available. */ int getPhysicalPackageCount(); /** * Get the number of system-wide context switches which have occurred. *

* Not available system-wide on macOS. Process- and Thread-level context switches are available from * {@link OSProcess#getContextSwitches()} and {@link OSThread#getContextSwitches()}. * * @return The number of context switches, if this information is available; 0 otherwise. */ long getContextSwitches(); /** * Get the number of system-wide interrupts which have occurred. *

* Not available system-wide on macOS. * * @return The number of interrupts, if this information is available; 0 otherwise. */ long getInterrupts(); /** * Index of CPU tick counters in the {@link #getSystemCpuLoadTicks()} and {@link #getProcessorCpuLoadTicks()} * arrays. */ enum TickType { /** * CPU utilization that occurred while executing at the user level (application). */ USER(0), /** * CPU utilization that occurred while executing at the user level with nice priority. */ NICE(1), /** * CPU utilization that occurred while executing at the system level (kernel). */ SYSTEM(2), /** * Time that the CPU or CPUs were idle and the system did not have an outstanding disk I/O request. */ IDLE(3), /** * Time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request. */ IOWAIT(4), /** * Time that the CPU used to service hardware IRQs */ IRQ(5), /** * Time that the CPU used to service soft IRQs */ SOFTIRQ(6), /** * Time which the hypervisor dedicated for other guests in the system. Only supported on Linux and AIX */ STEAL(7); private final int index; TickType(int value) { this.index = value; } /** * @return The integer index of this ENUM in the processor tick arrays, which matches the output of Linux * /proc/cpuinfo */ public int getIndex() { return index; } } /** * A class representing a Logical Processor and its replationship to physical processors, physical packages, and * logical groupings such as NUMA Nodes and Processor groups, useful for identifying processor topology. */ @Immutable class LogicalProcessor { private final int processorNumber; private final int physicalProcessorNumber; private final int physicalPackageNumber; private final int numaNode; private final int processorGroup; /** * @param processorNumber the Processor number * @param physicalProcessorNumber the core number * @param physicalPackageNumber the package/socket number */ public LogicalProcessor(int processorNumber, int physicalProcessorNumber, int physicalPackageNumber) { this(processorNumber, physicalProcessorNumber, physicalPackageNumber, 0, 0); } /** * @param processorNumber the Processor number * @param physicalProcessorNumber the core number * @param physicalPackageNumber the package/socket number * @param numaNode the NUMA node number */ public LogicalProcessor(int processorNumber, int physicalProcessorNumber, int physicalPackageNumber, int numaNode) { this(processorNumber, physicalProcessorNumber, physicalPackageNumber, numaNode, 0); } /** * @param processorNumber the Processor number * @param physicalProcessorNumber the core number * @param physicalPackageNumber the package/socket number * @param numaNode the NUMA node number * @param processorGroup the Processor Group number */ public LogicalProcessor(int processorNumber, int physicalProcessorNumber, int physicalPackageNumber, int numaNode, int processorGroup) { this.processorNumber = processorNumber; this.physicalProcessorNumber = physicalProcessorNumber; this.physicalPackageNumber = physicalPackageNumber; this.numaNode = numaNode; this.processorGroup = processorGroup; } /** * The Logical Processor number as seen by the Operating System. Used for assigning process affinity and * reporting CPU usage and other statistics. * * @return the processorNumber */ public int getProcessorNumber() { return processorNumber; } /** * The physical processor (core) id number assigned to this logical processor. Hyperthreaded logical processors * which share the same physical processor will have the same number. * * @return the physicalProcessorNumber */ public int getPhysicalProcessorNumber() { return physicalProcessorNumber; } /** * The physical package (socket) id number assigned to this logical processor. Multicore CPU packages may have * multiple physical processors which share the same number. * * @return the physicalPackageNumber */ public int getPhysicalPackageNumber() { return physicalPackageNumber; } /** * The NUMA node. If the operating system supports Non-Uniform Memory Access this identifies the node number. * Set to 0 if the operating system does not support NUMA. Not supported on macOS or FreeBSD. * * @return the NUMA Node number */ public int getNumaNode() { return numaNode; } /** * The Processor Group. Only applies to Windows systems with more than 64 logical processors. Set to 0 for other * operating systems or Windows systems with 64 or fewer logical processors. * * @return the processorGroup */ public int getProcessorGroup() { return processorGroup; } @Override public String toString() { return "LogicalProcessor [processorNumber=" + processorNumber + ", coreNumber=" + physicalProcessorNumber + ", packageNumber=" + physicalPackageNumber + ", numaNode=" + numaNode + ", processorGroup=" + processorGroup + "]"; } } /** * A class representing a Physical Processor (a core) providing per-core statistics that may vary, particularly in * hybrid/modular processors. */ @Immutable class PhysicalProcessor { private final int physicalPackageNumber; private final int physicalProcessorNumber; private final int efficiency; private final String idString; public PhysicalProcessor(int physicalPackageNumber, int physicalProcessorNumber) { this(physicalPackageNumber, physicalProcessorNumber, 0, ""); } public PhysicalProcessor(int physicalPackageNumber, int physicalProcessorNumber, int efficiency, String idString) { this.physicalPackageNumber = physicalPackageNumber; this.physicalProcessorNumber = physicalProcessorNumber; this.efficiency = efficiency; this.idString = idString; } /** * Gets the package id. This is also the physical package number which corresponds to * {@link LogicalProcessor#getPhysicalPackageNumber()}. * * @return the physicalProcessorNumber */ public int getPhysicalPackageNumber() { return physicalPackageNumber; } /** * Gets the core id. This is also the physical processor number which corresponds to * {@link LogicalProcessor#getPhysicalProcessorNumber()}. * * @return the physicalProcessorNumber */ public int getPhysicalProcessorNumber() { return physicalProcessorNumber; } /** * Gets a platform specific measure of processor performance vs. efficiency, useful for identifying cores in * hybrid/System on Chip (SoC) processors such as ARM's big.LITTLE architecture, Apple's M1, and Intel's P-core * and E-core hybrid technology. A core with a higher value for the efficiency class has intrinsically greater * performance and less efficiency than a core with a lower value for the efficiency class. * * @return On Windows 10 and higher, returns the {@code EfficiencyClass} value from the * {@code PROCESSOR_RELATIONSHIP} structure. *

* On macOS with Apple Silicon, emulates the same relative efficiency class values as Windows. *

* On Linux, returns the {@code cpu_capacity} value from sysfs. This is an optional cpu node property * representing CPU capacity expressed in normalized DMIPS/MHz. *

* On OpenBSD, FreeBSD, and Solaris with ARM big.LITTLE processors, emulates the same relative * efficiency class values as Windows. *

* For unimplemented operating systems or architectures, returns 0. * @see PROCESSOR_RELATIONSHIP * @see cpu-capacity */ public int getEfficiency() { return efficiency; } /** * Gets a platform specific identification string representing this core. This string requires user parsing to * obtain meaningful information. As this is an experimental feature, users should not rely on the format. * * @return On Windows, returns the per-core Processor ID (CPUID). *

* On macOS, returns a compatibility string from the IO Registry identifying hybrid cores. *

* On Linux, returns the {@code MODALIAS} value for the core's driver. *

* On OpenBSD, FreeBSD, and Solaris, returns a per-core CPU identification string. *

* For unimplemented operating systems, returns an empty string. */ public String getIdString() { return idString; } @Override public String toString() { return "PhysicalProcessor [package/core=" + physicalPackageNumber + "/" + physicalProcessorNumber + ", efficiency=" + efficiency + ", idString=" + idString + "]"; } } /** * A class representing CPU Cache Memory. */ @Immutable class ProcessorCache { /** * The type of cache. */ public enum Type { UNIFIED, INSTRUCTION, DATA, TRACE; @Override public String toString() { return name().substring(0, 1) + name().substring(1).toLowerCase(); } } private final byte level; private final byte associativity; private final short lineSize; private final int cacheSize; private final Type type; public ProcessorCache(byte level, byte associativity, short lineSize, int cacheSize, Type type) { this.level = level; this.associativity = associativity; this.lineSize = lineSize; this.cacheSize = cacheSize; this.type = type; } public ProcessorCache(int level, int associativity, int lineSize, long cacheSize, Type type) { this((byte) level, (byte) associativity, (short) lineSize, (int) cacheSize, type); } /** * The cache level. This member can be 1 (L1), 2 (L2), 3 (L3), or 4 (L4). * * @return the level */ public byte getLevel() { return level; } /** * The cache associativity. If this member is {@code 0xFF}, the cache is fully associative. * * @return the associativity */ public byte getAssociativity() { return associativity; } /** * The cache line size, in bytes. * * @return the line size */ public short getLineSize() { return lineSize; } /** * The cache size, in bytes. * * @return the cache size */ public int getCacheSize() { return cacheSize; } /** * The cache type. * * @return the type */ public Type getType() { return type; } @Override public String toString() { return "ProcessorCache [L" + level + " " + type + ", cacheSize=" + cacheSize + ", " + (associativity > 0 ? associativity + "-way" : "unknown") + " associativity, lineSize=" + lineSize + "]"; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || !(obj instanceof ProcessorCache)) { return false; } ProcessorCache other = (ProcessorCache) obj; return associativity == other.associativity && cacheSize == other.cacheSize && level == other.level && lineSize == other.lineSize && type == other.type; } @Override public int hashCode() { return Objects.hash(associativity, cacheSize, level, lineSize, type); } } /** * A class encapsulating ghe CPU's identifier strings ,including name, vendor, stepping, model, and family * information (also called the signature of a CPU) */ @Immutable final class ProcessorIdentifier { private static final String OSHI_ARCHITECTURE_PROPERTIES = "oshi.architecture.properties"; // Provided in constructor private final String cpuVendor; private final String cpuName; private final String cpuFamily; private final String cpuModel; private final String cpuStepping; private final String processorID; private final String cpuIdentifier; private final boolean cpu64bit; private final long cpuVendorFreq; private final Supplier microArchictecture = memoize(this::queryMicroarchitecture); public ProcessorIdentifier(String cpuVendor, String cpuName, String cpuFamily, String cpuModel, String cpuStepping, String processorID, boolean cpu64bit) { this(cpuVendor, cpuName, cpuFamily, cpuModel, cpuStepping, processorID, cpu64bit, -1L); } public ProcessorIdentifier(String cpuVendor, String cpuName, String cpuFamily, String cpuModel, String cpuStepping, String processorID, boolean cpu64bit, long vendorFreq) { this.cpuVendor = cpuVendor; this.cpuName = cpuName; this.cpuFamily = cpuFamily; this.cpuModel = cpuModel; this.cpuStepping = cpuStepping; this.processorID = processorID; this.cpu64bit = cpu64bit; // Build Identifier StringBuilder sb = new StringBuilder(); if (cpuVendor.contentEquals("GenuineIntel")) { sb.append(cpu64bit ? "Intel64" : "x86"); } else { sb.append(cpuVendor); } sb.append(" Family ").append(cpuFamily); sb.append(" Model ").append(cpuModel); sb.append(" Stepping ").append(cpuStepping); this.cpuIdentifier = sb.toString(); if (vendorFreq > 0) { this.cpuVendorFreq = vendorFreq; } else { // Parse Freq from name string Pattern pattern = Pattern.compile("@ (.*)$"); Matcher matcher = pattern.matcher(cpuName); if (matcher.find()) { String unit = matcher.group(1); this.cpuVendorFreq = ParseUtil.parseHertz(unit); } else { this.cpuVendorFreq = -1L; } } } /** * Processor vendor. * * @return vendor string. */ public String getVendor() { return cpuVendor; } /** * Name, eg. Intel(R) Core(TM)2 Duo CPU T7300 @ 2.00GHz * * @return Processor name. */ public String getName() { return cpuName; } /** * Gets the family. For non-Intel/AMD processors, returns the comparable value, such as the Architecture. * * @return the family */ public String getFamily() { return cpuFamily; } /** * Gets the model. For non-Intel/AMD processors, returns the comparable value, such as the Partnum. * * @return the model */ public String getModel() { return cpuModel; } /** * Gets the stepping. For non-Intel/AMD processors, returns the comparable value, such as the rnpn composite of * Variant and Revision. * * @return the stepping */ public String getStepping() { return cpuStepping; } /** * Gets the Processor ID. This is a hexidecimal string representing an 8-byte value, normally obtained using the * CPUID opcode with the EAX register set to 1. The first four bytes are the resulting contents of the EAX * register, which is the Processor signature, represented in human-readable form by {@link #getIdentifier()} . * The remaining four bytes are the contents of the EDX register, containing feature flags. *

* For processors that do not support the CPUID opcode this field is populated with a comparable hex string. For * example, ARM Processors will fill the first 32 bytes with the MIDR. AIX PowerPC Processors will return the * machine ID. *

* NOTE: The order of returned bytes is platform and software dependent. Values may be in either Big Endian or * Little Endian order. *

* NOTE: If OSHI is unable to determine the ProcessorID from native sources, it will attempt to reconstruct one * from available information in the processor identifier. * * @return A string representing the Processor ID */ public String getProcessorID() { return processorID; } /** * Identifier, eg. x86 Family 6 Model 15 Stepping 10. For non-Intel/AMD processors, this string is populated * with comparable values. * * @return Processor identifier. */ public String getIdentifier() { return cpuIdentifier; } /** * Is CPU 64bit? * * @return True if cpu is 64bit. */ public boolean isCpu64bit() { return cpu64bit; } /** * Vendor frequency (in Hz), eg. for processor named Intel(R) Core(TM)2 Duo CPU T7300 @ 2.00GHz the vendor * frequency is 2000000000. * * @return Processor frequency or -1 if unknown. */ public long getVendorFreq() { return cpuVendorFreq; } /** * Returns the processor's microarchitecture, if known. * * @return A string containing the microarchitecture if known. {@link Constants#UNKNOWN} otherwise. */ public String getMicroarchitecture() { return microArchictecture.get(); } private String queryMicroarchitecture() { String arch = null; Properties archProps = FileUtil.readPropertiesFromFilename(OSHI_ARCHITECTURE_PROPERTIES); // Intel is default, no prefix StringBuilder sb = new StringBuilder(); // AMD and ARM properties have prefix String ucVendor = this.cpuVendor.toUpperCase(); if (ucVendor.contains("AMD")) { sb.append("amd."); } else if (ucVendor.contains("ARM")) { sb.append("arm."); } else if (ucVendor.contains("IBM")) { // Directly parse the name to POWER# int powerIdx = this.cpuName.indexOf("_POWER"); if (powerIdx > 0) { arch = this.cpuName.substring(powerIdx + 1); } } else if (ucVendor.contains("APPLE")) { sb.append("apple."); } if (Util.isBlank(arch) && !sb.toString().equals("arm.")) { // Append family sb.append(this.cpuFamily); arch = archProps.getProperty(sb.toString()); } if (Util.isBlank(arch)) { // Append model sb.append('.').append(this.cpuModel); arch = archProps.getProperty(sb.toString()); } if (Util.isBlank(arch)) { // Append stepping sb.append('.').append(this.cpuStepping); arch = archProps.getProperty(sb.toString()); } return Util.isBlank(arch) ? Constants.UNKNOWN : arch; } @Override public String toString() { return getIdentifier(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy