Is there any equivalent of Java Runtime Class in C#? [duplicate] - java

How can I get the available RAM or memory used by the application?

You can use:
Process proc = Process.GetCurrentProcess();
To get the current process and use:
proc.PrivateMemorySize64;
To get the private memory usage. For more information look at this link.

You might want to check the GC.GetTotalMemory method.
It retrieves the number of bytes currently thought to be allocated by the garbage collector.

System.Environment has WorkingSet-
a 64-bit signed integer containing the number of bytes of physical memory mapped to the process context.
In .NET Core 3.0 and later (aka .NET 5 and later), you can use GC.GetGCMemoryInfo to get information about memory used by the GC heap and how much memory the GC thinks is available. .NET internally uses this data to calculate memory pressure. The memory pressure is used to decide when to trim the System.Buffers.ArrayPool.

In addition to #JesperFyhrKnudsen's answer and #MathiasLykkegaardLorenzen's comment, you'd better dispose the returned Process after using it.
So, In order to dispose the Process, you could wrap it in a using scope or calling Dispose on the returned process (proc variable).
using scope:
var memory = 0.0;
using (Process proc = Process.GetCurrentProcess())
{
// The proc.PrivateMemorySize64 will returns the private memory usage in byte.
// Would like to Convert it to Megabyte? divide it by 2^20
memory = proc.PrivateMemorySize64 / (1024*1024);
}
Or Dispose method:
var memory = 0.0;
Process proc = Process.GetCurrentProcess();
memory = Math.Round(proc.PrivateMemorySize64 / (1024*1024), 2);
proc.Dispose();
Now you could use the memory variable which is converted to Megabyte.

Look here for details.
private PerformanceCounter cpuCounter;
private PerformanceCounter ramCounter;
public Form1()
{
InitializeComponent();
InitialiseCPUCounter();
InitializeRAMCounter();
updateTimer.Start();
}
private void updateTimer_Tick(object sender, EventArgs e)
{
this.textBox1.Text = "CPU Usage: " +
Convert.ToInt32(cpuCounter.NextValue()).ToString() +
"%";
this.textBox2.Text = Convert.ToInt32(ramCounter.NextValue()).ToString()+"Mb";
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void InitialiseCPUCounter()
{
cpuCounter = new PerformanceCounter(
"Processor",
"% Processor Time",
"_Total",
true
);
}
private void InitializeRAMCounter()
{
ramCounter = new PerformanceCounter("Memory", "Available MBytes", true);
}
If you get value as 0 it need to call NextValue() twice. Then it gives the actual value of CPU usage. See more details here.

For the complete system you can add the Microsoft.VisualBasic Framework as a reference;
Console.WriteLine("You have {0} bytes of RAM",
new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory);
Console.ReadLine();

Related

How to pass over a value pointer via java foreign memory api

I want to call the following method in C (defined here):
heif_image_handle* handle;
heif_context_get_primary_image_handle(ctx, &handle);
The problem I have is that I have no access via the C-API to the struct heif_image_handle. It is defined as a struct without a definition:
struct heif_image_handle;
What I have tried:
try (var scope = ResourceScope.newSharedScope()) {
MemoryAddress heif_context_alloc = heif_context_alloc();
// ...
MemoryAddress primary_image_handle = MemorySegment.allocateNative(C_POINTER, scope).address();
heif_context_get_primary_image_handle(scope, primary_image_handle.address(), heif_context_alloc);
// ...
}
Can someone help me how can I use this method with Panama API. My actual workaround was to extend the C-API but original author does not want to do that.
My actual code is under: https://github.com/lanthale/LibHeifFX/blob/main/LibHeifFX/src/main/java/org/libheiffx/LibheifImage.java
Your code looks almost correct to me. You just need to keep hold of the allocated segment (which represents the heif_image_handle**), and then after calling heif_context_get_primary_image_handle, retrieve the MemoryAddress from that segment after the library sets the primary image handle into it (example using the JDK 17 API):
// allocate blob of memory the size of a pointer
MemorSegment primary_image_handle_seg = MemorySegment.allocateNative(C_POINTER);
// call library to set the handle into the allocated memory
heif_context_get_primary_image_handle(ctx, primary_image_handle_seg.address());
// retrieve pointer from allocated memory
MemoryAddress primary_image_handle = MemoryAccess.getAddress(primary_image_handle_seg);
In general, doing stack allocations and taking the address of the allocated value like in C, as in the snippet that you show, is not possible directly in Java. So, as far as the panama foreign API goes, whenever you see something like this in C code:
some_type* val;
You will need to allocate a MemorySegment for it:
// some_type** val_ptr;
MemorySegment val_ptr = MemerySegment.allocateNative(C_POINTER, scope);
// some_type** val_ptr_as_ma; (as a bare MemoryAddress)
MemoryAddress val_ptr_as_ma = val.address();
// some_type* val; (dereference/copy val, `*val_ptr`)
MemoryAddress val = MemoryAccess.getAddress(val);
Note that we have to go through the MemorySegment route in this case. Since it is not possible to take the address of a MemoryAddress.
In general, the Java API does not have an equivalent of the & ampersand operator. The .address() method is there to convert address-like things into MemoryAddress instances, not to mimic &. And for MemoryAddress itself it just return this (so your primary_image_handle.address() call has no effect).
Essentially, the C equivalent of what we do in Java, without stack allocation and &, is this:
some_type** val_ptr = malloc(sizeof *val_ptr);
func(val_ptr); // void func(some_type** v) { ... }
some_type* val = *val_ptr;

Java G1: Monitoring for memory leaks in production

For years, we've been running Java services with modest heap sizes using +UseParallelOldGC. Now, we're starting to roll out a new service using a larger heap and the G1 collector. This is going pretty well.
For our services that use +UseParallelOldGC, we monitor for memory leaks by looking at the old generation size after collection and alerting on a threshold. This works quite well, and in fact saved our bacon just two weeks ago.
Specifically, for +UseParallelOldGC, we do the following:
ManagementFactory.getMemoryPoolMXBeans()
Search for the MemoryPoolMXBean result with the name ending in "Old Gen"
Compare getCollectionUsage().getUsed() (if available) with getMax()
Unfortunately, it seems like G1 no longer has a concept of getCollectionUsage().
Fundamentally, though, we'd like to monitor the G1 heap size following the last mixed collection it chooses to do in a mixed cycle, or something similar.
For example, outside the VM I would be happy with an awk script that merely found the last '(mixed)' was that's followed by a '(young)' and look what the final heap size was (e.g., '1540.0M' 'Heap: 3694.5M(9216.0M)->1540.0M(9216.0M)')
Is there any way to do this inside the Java VM?
Yes, JVM gives you enough tools to retrieve such information for G1. For instance, you could use something like this class that prints all the details about garbage collections (just call MemoryUtil.startGCMonitor()):
public class MemoryUtil {
private static final Set<String> heapRegions;
static {
heapRegions = ManagementFactory.getMemoryPoolMXBeans().stream()
.filter(b -> b.getType() == MemoryType.HEAP)
.map(MemoryPoolMXBean::getName)
.collect(Collectors.toSet());
}
private static NotificationListener gcHandler = (notification, handback) -> {
if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
GarbageCollectionNotificationInfo gcInfo = GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData());
Map<String, MemoryUsage> memBefore = gcInfo.getGcInfo().getMemoryUsageBeforeGc();
Map<String, MemoryUsage> memAfter = gcInfo.getGcInfo().getMemoryUsageAfterGc();
StringBuilder sb = new StringBuilder(250);
sb.append("[").append(gcInfo.getGcAction()).append(" / ").append(gcInfo.getGcCause())
.append(" / ").append(gcInfo.getGcName()).append(" / (");
appendMemUsage(sb, memBefore);
sb.append(") -> (");
appendMemUsage(sb, memAfter);
sb.append("), ").append(gcInfo.getGcInfo().getDuration()).append(" ms]");
System.out.println(sb.toString());
}
};
public static void startGCMonitor() {
for(GarbageCollectorMXBean mBean: ManagementFactory.getGarbageCollectorMXBeans()) {
((NotificationEmitter) mBean).addNotificationListener(gcHandler, null, null);
}
}
public static void stopGCMonitor() {
for(GarbageCollectorMXBean mBean: ManagementFactory.getGarbageCollectorMXBeans()) {
try {
((NotificationEmitter) mBean).removeNotificationListener(gcHandler);
} catch(ListenerNotFoundException e) {
// Do nothing
}
}
}
private static void appendMemUsage(StringBuilder sb, Map<String, MemoryUsage> memUsage) {
memUsage.entrySet().forEach((entry) -> {
if (heapRegions.contains(entry.getKey())) {
sb.append(entry.getKey()).append(" used=").append(entry.getValue().getUsed() >> 10).append("K; ");
}
});
}
}
In this code, gcInfo.getGcAction() gives you enough information to separate minor collections from major/mixed ones.
But there's an important caveat to using your approach (with a threshold) to G1. A single mixed collection in G1 usually affects only several old gen regions - many enough to free sufficient amount of memory but not too many in order to keep the GC pause low. So, after a mixed collection in G1 you cannot be sure that all your garbage has gone. As a result, you need to find more sophisticated strategy to detect memory leaks (maybe based on collections frequency, gathering statistics from several collections, etc.)

JNI and Shared memory

I use JNI to access shared memory segments previously created. I use a Java/Jni read/write function which could either take the address of the shared buffer, or the id of the mapped region.
Unfortunately, it seems like every time I call the read/write functions I have to remap the segment using the function below. Is there any way to get round this? I would like (i have tried this, but it didn't work, to only have to map the segment once, and simply use the void* addr parameter in the future, as opposed to every time I call the JNI method read or write, to have to call map_shared_memory. The current code works well, but remains relatively slow. Hence the desire to minimise seemingly unnecessary operations.
void* map_shared_memory(int id) {
void* addr;
if (id == 0)
return NULL;
addr = shmat(id, NULL, 0);
shmctl(id, IPC_RMID, NULL);
if(addr<=0)
perror("Error Mapping Shared Memory: ");
return addr;
}
I suggest a collaboration between a class ShmFactory which opens (or create) the Shared Memory and and ShmAccess which offer read/write methods.
interface ShmAccess
{
void read( shmId, byte[] bytes );
void write( shmId, byte[] bytes );
}
interface ShmFactory
{
public native ShmAccess open( int shmId );
}

How to detect PermGen free memory

What is the best way to work out the current PermGen usage in a Grails app?
I'm trying to do some graphing of
Runtime.getRuntime().freeMemory();
Runtime.getRuntime().totalMemory();
And I'd like to also measure the free PermGen space. Most of the search engine + Stack Overflow results on this matter are on handling the PermGenOutOfMemory-like errors, I'd just like to access the stats on these.
Just connect to it using JConsole or VisualVM. Theres no way for you to programmatically determine the PermGen size in your application. You can use the MemoryMXBean to do simple memory reporting, but stick to using the tools I mentioned to get a more detailed picture.
I guess you should try this
public class Main {
public static void main(final String[] args) {
final RuntimeMXBean memMXBean = ManagementFactory.getRuntimeMXBean();
final String prefix = "-XX:MaxPermSize=";
final List<String> jvmArgs = memMXBean.getInputArguments();
String maxPermSize = null;
for (final String jvmArg : jvmArgs) {
if (jvmArg.startsWith(prefix)) {
maxPermSize = jvmArg.substring(prefix.length());
break;
}
}
System.out.println("MaxPermSize is " + maxPermSize);
}
}
I think ManagementFactory could be the source, one of the pools returned from List getMemoryPoolMXBeans() should be PermGen.

Notification of memory shortage in Java

Is there any delivered feature in Java notifying a memory shortage in an application (or notifying that it has reach a predefined level)?
I was wondering whether it was possible to register a listener (or something equivalent) somewhere? I know about the memory methods in the Runtime class. I could create a scheduled task checking remaining memory myself, but I am wondering whether there is already an existing solution.
I don't think so, but I am looking for a confirmation.
FOR THE RECORDS
MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
NotificationEmitter emitter = (NotificationEmitter) mbean;
NotificationListener listener = new NotificationListener() {
#Override
public void handleNotification(Notification notif, Object handback) {
String notifType = notif.getType();
if (notifType.equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED) ||
notifType.equals(MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED)) {
// Retrieve the memory notification information
CompositeData cd = (CompositeData) notif.getUserData();
MemoryNotificationInfo info = MemoryNotificationInfo.from(cd);
MemoryUsage mu = info.getUsage();
System.out.println("Maximum memory = " + mu.getMax());
System.out.println("Used memory = " + mu.getUsed());
}
}
};
emitter.addNotificationListener(listener, null, null);
I believe you can set up a listener for a memory usage threshold using the MemoryMXBean. Sample code is provided in the javadoc link.

Categories