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 );
}
Related
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();
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;
public static User32 USER32_INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
user32 = USER32_INSTANCE;
user32.EnumWindows((hWnd, arg) -> {
int size = 1024 * 8;
char[] buffer = new char[size];
USER32_INSTANCE.GetWindowTextW(hWnd, buffer, size);
char[] buffer2 = new char[size];
PointerByReference pointer = new PointerByReference();
User32DLL.GetWindowThreadProcessId(hWnd, pointer);
Pointer process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pointer.getValue());
Psapi.GetModuleBaseNameW(process, null, buffer2, size);
String result = Native.toString(buffer).trim();
String proc = Native.toString(buffer2).trim();
// ... (non-JNA stuff)
}
I haven't touched C/C++ since college and I honestly have no clue how to actually free the memory here :(
I know that there's a memory leak - I did some profiling with YourKit and traced a memory leak to this block of code (specifically, it seems to be leaking in the GetWindowTextW call and the Native.toString() calls). Could someone just give me an example of how to properly free up whatever memory blocks are being used?
I see that Pointer has a clear() method, should I use that? But I don't know how to get the size (clear takes a length argument). I also see that there's a Memory type that subclasses Pointer, but according to instanceof, none of the Pointers I have right now are actually instances of that.
After opening a handle to a process with OpenProcess, you need to close the process handle with CloseHandle. Remember that OpenProcess returns a Handle, not a Pointer.
Kernel32.INSTANCE.CloseHandle(process);
Note also that JNA provides a pretty in-depth mapping of the Windows API out of the box in the net.java.dev.jna-platform package (I think?)
I'm writing GC friendly code to read and return to the user a series of byte[] messages. Internally I reuse the same ByteBuffer which means I'll repeatedly return the same byte[] instance most of the time.
I'm considering writing cautionary javadoc and exposing this to the user as a Iterator<byte[]>. AFAIK it won't violate the Iterator contract, but the user certainly could be surprised if they do Lists.newArrayList(myIterator) and get back a List populated with the same byte[] in each position!
The question: is it bad practice for a class that may mutate and return the same object to implement the Iterator interface?
If so, what is the best alternative? "Don't mutate/reuse your objects" is an easy answer. But it doesn't address the cases when reuse is very desirable.
If not, how do you justify violating the principle of least astonishment?
Two minor notes:
I'm using Guava's AbstractIterator so remove() isn't really of concern.
In my use case the user is me and the visibility of this class will be limited, but I've tried to ask this generally enough to apply more broadly.
Update: I'm accepting Louis' answer because it has 3x more votes than Keith's, but note that in my use case I'm planning to take the code that I left in a comment on Keith's answer to production.
EnumMap did essentially exactly this in its entrySet() iterator, which causes confusing, crazy, depressing bugs to this day.
If I were you, I just wouldn't use an Iterator -- I'd write a different API (possibly quite dissimilar from Iterator, even) and implement that. For example, you might write a new API that takes as input the ByteBuffer to write the message into, so users of the API could control whether or not the buffer gets reused. That seems reasonably intuitive (the user can write code that obviously and cleanly reuses the ByteBuffer), without creating unnecessarily cluttered code.
I would define an intermediate object which you can invalidate. So your function would return an Iterator<ByteArray>, and ByteArray is something like this:
class ByteArray {
private byte[] data;
ByteArray(byte[] d) { data = d; }
byte[] getData() {
if (data == null) throw new BadUseOfIteratorException();
return data;
}
void invalidate() { data = null; }
}
Then your iterator can invalidate the previously returned ByteArray so that any future access (via getData, or any other accessor you provide) will fail. Then at least if someone does something like Lists.newArrayList(myIterator), they will at least get an error (when the first invalid ByteArray is accessed) instead of silently returning the wrong data.
Of course, this won't catch all possible bad uses, but probably the common ones. If you're happy with never returning the raw byte[] and providing accessors like byte get(int idx) instead, then it should catch all cases.
You will have to allocate a new ByteArray for each iterator return, but hopefully that's a lot less expensive than copying your byte[] for each iterator return.
Just like Keith Randall I'd also create Iterator<ByteArray>, but working quite differently (the annotations below come from lombok):
#RequiredArgsConstructor
public class ByteArray {
#Getter private final byte[] data;
private final ByteArrayIterable source;
void allowReuse() {
source.allowReuse();
}
}
public class ByteArrayIterable implements Iterable<ByteArray> {
private boolean allowReuse;
public allowReuse() {
allowReuse = true;
}
public Iterator<ByteArray> iterator() {
return new AbstractIterator<ByteArray>() {
private ByteArray nextElement;
public ByteArray computeNext() {
if (noMoreElements()) return endOfData();
if (!allowReuse) nextElement =
new ByteArray(new byte[length], ByteArrayIterable.this);
allowReuse = false;
fillWithNewData(lastElement.getData());
}
}
}
}
Now in calls like Lists.newArrayList(myIterator) always a new byte array gets allocated, so everything works. In your loops like
for (ByteArray a : myByteArrayIterable) {
a.allowReuse();
process(a.getData());
}
the buffer gets reused. No harm may result, unless you call allowReuse() by mistake. If you forget to call it, then you get worse performance but correct behavior.
Now I see it could work without ByteArray, the important thing is that myByteArrayIterable.allowReuse() gets called, which could be done directly.
Most of the documentation that details how to get started with JNI described how to build a new JNI application using X-Code. Can anyone link me to a description of how to use JNI to interface with Objective-C in an existing application.
NOTE: I have completely re-written this answer from scratch, now that I know for sure it works ;-).
Use Rococoa instead of JNI.
Here is a brief sample I was able to whip up that displays the picture taker dialog (based on your comment to Stephen C's answer).
/***
* INCOMPLETE: Doesn't have imports or anything like that.
***/
public interface Quartz extends Library
{
public static Quartz instance = (Quartz)Native.loadLibrary("Quartz", Quartz.class);
}
public interface IKPictureTaker extends NSObject
{
public static final _Class CLASS = Rococoa.createClass("IKPictureTaker", _Class.class);
public interface _Class extends NSClass
{
/**
* Returns a shared {#code IKPictureTaker} instance, creating it if necessary.
* #return an {#code IKPictureTaker} object.
*/
IKPictureTaker pictureTaker();
}
NSInteger runModal();
}
public class IKPictureTakerTest extends JFrame
{
public static void main(String[] args) throws Exception
{
// You need a GUI before this will work.
new IKPictureTakerTest().setVisible(true);
NSAutoreleasePool pool = NSAutoreleasePool.new_();
// Initialize the Quartz framework.
Quartz.instance.toString();
// Display the dialog.
IKPictureTaker pictureTaker = IKPictureTaker.CLASS.pictureTaker();
NSInteger result = pictureTaker.runModal();
if (result.intValue() == 0) // NSCancelButton
{
System.out.println("User cancelled.");
}
else
{
assert result.intValue() == 1; // NSOKButton
System.out.println("User chose an image.");
}
System.out.println(pictureTaker.inputImage()); // null if the user cancelled
pool.release();
}
}
If you get lost, try the Rococoa mailing lists. The developers are very helpful.
You will still need to write a JNI library of some sort to wrap your access to the existing code (aka, shared object, DLL, service program, etc). This is because JNI requires a rather obtuse (but sensible) naming convention for the native functions invoked, because you need to move data in and out of Java memory space and because you need to have conceptual "bridging" code between Java and your native function.
For example, I wrote a JNI library to provide access to existing C functions on the iSeries. One such function to read from a data area looks as follows:
JNIEXPORT void JNICALL Java_com_xxx_jni400_DataArea_jniGetDataArea(JNIEnv *jep, jobject thsObj, jbyteArray qulnam, jint str, jint len, jbyteArray rtndta, jint rtnlen) {
jbyte *qn,*rd;
Qwc_Rdtaa_Data_Returned_t *drt;
QFBK2_T fbk;
byte nam[11],lib[11];
byte *ptr;
// SETUP
thsObj=thsObj;
qn=(*jep)->GetByteArrayElements(jep,qulnam,0);
rd=(*jep)->GetByteArrayElements(jep,rtndta,0);
fbk.pro=sizeof(fbk); fbk.avl=0;
// INVOKE
QWCRDTAA(rd,rtnlen,(byte*)qn,str,len,&fbk);
// HANDLE SUCCESSFUL INVOCATION
if(fbk.avl==0) {
drt=(Qwc_Rdtaa_Data_Returned_t*)rd;
if(drt->Length_Value_Returned>0) { /* pad with spaces until the length requested */
ptr=(byte*)(rd+sizeof(*drt)+drt->Length_Value_Returned);
for(; drt->Length_Value_Returned<len; drt->Length_Value_Returned++,ptr++) { *ptr=' '; }
}
}
// RELEASE JAVA MEMORY LOCKS
(*jep)->ReleaseByteArrayElements(jep,qulnam,qn,JNI_ABORT); /* discard array changes */
(*jep)->ReleaseByteArrayElements(jep,rtndta,rd,0 ); /* copy back changes */
// TRANSFORM NATIVE ERROR INTO AN EXCEPTION AND THROW
if(fbk.avl!=0) {
byte eid[8],dta[201];
word dtalen;
f2s(nam,sizeof(nam),(byte*)qn ,10);
f2s(lib,sizeof(lib),(byte*)(qn+10),10);
dtalen=(word)mMin( sizeof(fbk.dta),(fbk.avl-(sizeof(fbk)-sizeof(fbk.dta))) );
f2s(eid,sizeof(eid),fbk.eid,sizeof(fbk.eid));
f2s(dta,sizeof(dta),fbk.dta,dtalen);
if(mStrEquI(eid,"CPF1015") || mStrEquI(eid,"CPF1021")) {
throwEscape(jep,90301,"Could not find data area %s in library %s",nam,lib);
}
else if(mStrEquI(eid,"CPF1016") || mStrEquI(eid,"CPF1022")) {
throwEscape(jep,90301,"Not authorized to data area %s in library %s",nam,lib);
}
else if(mStrEquI(eid,"CPF1063") || mStrEquI(eid,"CPF1067")) {
throwEscape(jep,90301,"Cannot allocate data area %s in library %s",nam,lib);
}
else if(mStrEquI(eid,"CPF1088") || mStrEquI(eid,"CPF1089")) {
throwEscape(jep,90301,"Substring %i,%i for data area %s in library %s are not valid",str,len,nam,lib);
}
else {
if(strlen(dta)>0) { throwEscape(jep,90001,"System API QWCRDTAA returned error message ID %s (%s)",eid,dta);}
else { throwEscape(jep,90001,"System API QWCRDTAA returned error message ID %s",eid); }
}
}
}
Note the one-line invocation for underlying existing API, QWCRDTAA, which is provided by IBM; the rest is Java-centric wrapping which is necessary to make the call and deal with the results.
Also, be very careful that what you invoke is thread-safe, or that you protect the code from concurrent invocations globally in the Java layer, or that you protect the code with a mutex in the O/S layer.
PS: Note that non-threadsafe native code is globally non-threadsafe; you must prevent concurrent invocation with all other non-threadsafe native code, not just the one method you are invoking. This is because it might be unsafe due to an underlying call to some other function which other unsafe methods call (like strerror(), (if my C memory serves well)).
Assuming that the Object-C application can be run via the command line, a simpler (and less problematic) approach would be to launch it using one of the java.lang.Runtime.exec(...) methods.
JNI is fraught with complexity and stability issues, and it is best to avoid it if you can.
EDIT: The OP has explained that this is a "widget" not a command line application. That makes it harder to avoid using JNI. But I still think that you ought to try. For example, you could consider wrapping the Objective-C widget in an Objective-C application, that runs the widget in a new window.