JDK-18 Foreign Functions : How to upCall non-static functions? - java

I've been playing around with the jdk.incubator.foreign stuff in JDK-18. It's pretty nice. WAY faster than JNI. An order of magnitude faster. The foreign memory stuff is better (and maybe slightly faster) than the UNSAFE stuff. Can't wait for this to ship.
One thing I can't figure out: How to upCall to a non-static JVM function?
If I can't, how do I pass some context down and back so I can cast the context into the correct instance/type in the java static function? In java how do you create a ValueLayout.ADDRESS from this? And vice-versa?
The only way I can figure out how to do it is to keep a list of instantiated classes, and round-trip the index in the list. Which seems like a hack.
Maybe the JVM reserves the right to move JVM memory around without restriction whenever it feels like it, so maybe it's not possible? If so, what is the recommended pattern for this?
--- edit - Add code example ---
public class RoundTripExample {
private String name;
RoundTripExample(String _name) {
this.name = _name;
}
public void callback() {
System.out.println("Called from native"+name);
}
public static void main(String[] args) throws Throwable {
var fName = new File("../zig/zig-out/lib/libnativeFuncs.so").getCanonicalFile();
System.load(fName.toString());
var instance =new RoundTripExample("round trip name");
CLinker link = CLinker.systemCLinker();
SymbolLookup symLook = SymbolLookup.loaderLookup();
ResourceScope scope = ResourceScope.newSharedScope();
var nativeFunc = link.downcallHandle(
symLook.lookup("zigCallTest").get(),
FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS)
);
var handle =
MethodHandles.lookup().findVirtual(
RoundTripExample.class,
"callback",
MethodType.methodType(void.class)
);
handle.bindTo(instance);
var upcall = link.upcallStub(
handle,
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS),
ZigStubs.scope
);
nativeFunc.invoke(upcall);
}
}
Assuming this is the way to do it, the problem is creating the upCall handle. You can only pass it a handle to functions that take LONG, INT, ADDRESS, etc. An instance of a class isn't any of those.

If the context you need to pass is constant for the target function, you could bind it to the target method handle using MethodHandles.insertArguments and then use the resulting method handle to create an upcall stub.
If the context is not constant for the target function, then your idea of using a list and passing around the index to the object you want is a pretty good way to go. This is essentially a way to turn an object into an integer, by inserting it into the list, and then back into an object by looking it up in the list again.
There's no safe way of turning an object into a plain native address, since, as you say, the object might be move by the JVM.
In the example, using bindTo looks feasible. In this case you've forgotten to assign the result of bindTo:
handle = handle.bindTo(instance);
Additionally, you'd have to drop the address argument passed from native code, as it looks like it's not being used by your Java code:
handle = MethodHandles.dropArguments(handle, 0, MemoryAddress.class);
var upcall = link.upcallStub(
handle,
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS),
ZigStubs.scope
);

Related

Enumerate Custom Slot Values from Speechlet

Is there any way to inspect or enumerate the Custom Slot Values that are set-up in your interaction model? For Instance, Say you have an intent schema with the following intent:
{
"intent": "MySuperCoolIntent",
"slots":
[
{
"name": "ShapesNSuch",
"type": "LIST_OF_SHAPES"
}
]
}
Furthermore, you've defined the LIST_OF_SHAPES Custom Slot to have the following Values:
SQUARE
TRIANGLE
CIRCLE
ICOSADECAHECKASPECKAHEDRON
ROUND
HUSKY
Question: is there a method I can call from my Speechlet or my RequestStreamHandler that will give me an enumeration of those Custom Slot Values??
I have looked through the Alexa Skills Kit's SDK Javadocs Located Here
And I'm not finding anything.
I know I can get the Slot's value that is sent in with the intent:
String slotValue = incomingIntentRequest.getIntent().getSlot("LIST_OF_SHAPES").getValue();
I can even enumerate ALL the incoming Slots (and with it their values):
Map<String, Slot> slotMap = IncomingIntentRequest.getIntent().getSlots();
for(Map.Entry<String, Slot> entry : slotMap.entrySet())
{
String key = entry.getKey();
Slot slot = (Slot)entry.getValue();
String slotName = slot.getName();
String slotValue = slot.getValue();
//do something nifty with the current slot info....
}
What I would really like is something like:
String myAppId = "amzn1.echo-sdk-ams.app.<TheRestOfMyID>";
List<String> posibleSlotValues = SomeMagicAlexaAPI.getAllSlotValues(myAppId, "LIST_OF_SHAPES");
With this information I wouldn't have to maintain two separate "Lists" or "Enumerations"; One within the interaction Model and another one within my Request Handler. Seems like this should be a thing right?
No, the API does not allow you to do this.
However, since your interaction model is intimately tied with your development, I would suggest you check in the model with your source code in your source control system. If you are going to do that, you might as well put it with your source. Depending on your language, that also means you can probably read it during run-time.
Using this technique, you can gain access to your interaction model at run-time. Instead of doing it automatically through an API, you do it by best practice.
You can see several examples of this in action for Java in TsaTsaTzu's examples.
No - there is nothing in the API that allows you to do that.
You can see the full extent of the Request Body structure Alexa gives you to work with. It is very simple and available here:
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#Request%20Format
Please note, the Request Body is not to be confused with the request, which is a structure in the request body, with two siblings: version and session.

JPL textToTerm only produces anonymous variables

I'm using JPL to do some SWI-Prolog queries in a Java program. When I want to create a new Query, I would like to be able to use jpl.Util.textToTerm to directly instanciate Terms from a user input, without parsing it myself.
The problem is that this method seems to always parse variable identifiers (i.e. something that starts with a capital letter) as anonymous variables (i.e. something that starts with _).
For example, jpl.Util.textToTerm("X") returns a jpl.Variable that has name _1 instead of X, which is obviously a problem since that means I won't be able to access any bindings after querying.
Creating a jpl.Query directly from a string, like new Query("reverse([1,2],X)") has the exact same problem.
_1 it's not an anonymous variable, so the problem is less important than it appears at first glance.
Variables with the same name (actually, the same variable) will have the same representation once returned from the JPL interface. Otherwise, you should file a bug of the mailing list...
You should use read_term family of predicates passing as option variable_names(Vars). For instance, on the REPL
?- read_term_from_atom('a(X,Y,X)',T,[variable_names(L)]).
T = a(_G1434, _G1435, _G1434),
L = ['X'=_G1434, 'Y'=_G1435].
edit a quick test reusing JPL test infrastructure (I've named the file TestQuery.java)
import java.util.Map;
import org.jpl7.Query;
import org.jpl7.Term;
public class TestQuery {
public static void main(String argv[]) {
Query q = new Query("X = 1");
Map<String, Term>[] solutions = q.allSolutions();
System.out.println(solutions[0]);
}
}
outputs
./run.sh
Compiling TestQuery
JPL demo: TestQuery
{X=1}
so, maybe I don't understand your problem in first place, sorry... Are you using an up-to-date installation ?

Handling non-fatal errors in Java

I've written a program to aid the user in configuring 'mechs for a game. I'm dealing with loading the user's saved data. This data can (and some times does) become partially corrupt (either due to bugs on my side or due to changes in the game data/rules from upstream).
I need to be able to handle this corruption and load as much as possible. To be more specific, the contents of the save file are syntactically correct but semantically corrupt. I can safely parse the file and drop whatever entries that are not semantically OK.
Currently my data parser will just show a modal dialog with an appropriate warning message. However displaying the warning is not the job of the parser and I'm looking for a way of passing this information to the caller.
Some code to show approximately what is going on (in reality there is a bit more going on than this, but this highlights the problem):
class Parser{
public void parse(XMLNode aNode){
...
if(corrupted) {
JOptionPane.showMessageDialog(null, "Corrupted data found",
"error!", JOptionPane.WARNING_MESSAGE);
// Keep calm and carry on
}
}
}
class UserData{
static UserData loadFromFile(File aFile){
UserData data = new UserData();
Parser parser = new Parser();
XMLDoc doc = fromXml(aFile);
for(XMLNode entry : doc.allEntries()){
data.append(parser.parse(entry));
}
return data;
}
}
The thing here is that bar an IOException or a syntax error in the XML, loadFromFile will always succeed in loading something and this is the wanted behavior. Somehow I just need to pass the information of what (if anything) went wrong to the caller. I could return a Pair<UserData,String> but this doesn't look very pretty. Throwing an exception will not work in this case obviously.
Does any one have any ideas on how to solve this?
Depending on what you are trying to represent, you can use a class, like SQLWarning from the java.sql package. When you have a java.sql.Statement and call executeQuery you get a java.sql.ResultSet and you can then call getWarnings on the result set directly, or even on the statement itself.
You can use an enum, like RefUpdate.Result, from the JGit project. When you have a org.eclipse.jgit.api.Git you can create a FetchCommand, which will provide you with a FetchResult, which will provide you with a collection of TrackingRefUpdates, which will each contain a RefUpdate.Result enum, which can be one of:
FAST_FORWARD
FORCED
IO_FAILURE
LOCK_FAILURE
NEW
NO_CHANGE
NOT_ATTEMPTED
REJECTED
REJECTED_CURRENT_BRANCH
RENAMED
In your case, you could even use a boolean flag:
class UserData {
public boolean isCorrupt();
}
But since you mentioned there is a bit more than that going on in reality, it really depends on your model of "corrupt". However, you will probably have more options if you have a UserDataReader that you can instantiate, instead of a static utility method.

How to keep an object in memory during development

My program has the following structure:
void main (String[] args) {
Object largeObject = longInitialization();
interestingLogic(largeObject);
}
The longInitialization code never changes during development. BUt whenever I change the interestingLogic, I have to run the program again and wait for the longInitialization to complete.
Unfortunately I cannot serialize largeObject because it is not Serializable and I don't have the code to it.
Is there a trick by which I can save the initialization time? Maybe, in some way save the state of the JVM just after initialization, and then always start from that state?
You can make little modification of code:
main(){
Object largeObject = longInitialization();
boolean debug = true;
while(debug){
interestingLogic(largeObject);
}
}
now run program in debug mode. Set breakpoint at interestingLogic call and use code hotswap debug mode in IDE. read more about hotswap in Eclipe: Java Hotswap with Eclipses and Remote Debugging on Local Machine
//Edit:
One more option. Just write mock of largeObject.
You will need a new object to call interestingLogic(largeObject). You can make changes to the new object while the driver program is waiting for user input.
void main (String[] args) {
Object largeObject = longInitialization();
boolean anotherTry = true;
String answer = "";
Scanner input = new Scanner(System.in);
while (anotherTry) {
Object newobject = NewObject();
newobject.interestingLogic(largeObject).
System.out.print("Run Again Y/N");
answer = input.nextLine();
if (answer.equalsIgnoreCase("N")) {
anotherTry = false;
}
}
}
If the large object is not needed immediately, you could decorate it with a "lazy initializing" wrapper, and invoke the "longInitialization" just before you want to access it.
A second solution could be "cloning" it by marshalling/unmarshalling it to an xml file
Because you said "...cannot serialize largeObject..." there is no way to persist an object across JVM lifetimes (since you don't have the source). But, you have code that initializes/uses the largeOject. Create a serializable debugLargeObject that acts like the real largeObject and use debugLargeObject during development.
Not without a lot of work. You need a minor refactor, as shown by Guido, then you need to reload the NewObject class each time through the loop (or whatever). In other words, your VM needs to be able to remove the NewObject class, then reload it, each time you change the code.
There are commercial products which do this (see JRebel, for example). You can roll your own (see this StackOverflow topic: Unloading classes in java?). You can hotswap, if you're very careful about your interestingLogic. But ultimately, you need to swap out that class somehow.

Using Jhat heap built-in object

Can anybody show an example of how to use heap.heapForEachClass in a select statement?
It would be great if you could provide some links with different examples of queries (other than those in the oqlhelp page of course :) )
I don't believe heap.forEachClass() is meant to be used in a select statement, at least not directly. Consider the fact that it doesn't return anything:
var result=heap.forEachClass(function(it){return it;});
typeof result
//returns undefined
The OQL used in jhat and VisualVM does support plain ol' JavaScript, just like the "query" I use above. I believe that the heap.forEachClass() finds more use in either JavaScript-style queries or in JavaScript functions within select-type queries.
That said, I don't know why this function exists since the heap.classes() enumeration is much easier to use, both with with select-style queries and plain JavaScript ones.
You could even even recreate the same functionality as heap.forEachClass() with the following JavaScript function:
function heapForEachClass(func){
map(heap.classes(),func)
return undefined;
}
Any sample queries that I could provide you would likely be easier written with heap.classes(). For example, you could use heap.forEachClass() to get list of all classes:
var list=[];
heap.forEachClass(function(it){
list.push(it);
});
list
but this is more complicated than how you'd do it with heap.classes():
select heap.classes()
or just
heap.classes()
I've used this function before to look for classes that are loaded multiple times (usually, this happens when two different class loaders load the same lib taking more memory for no reason, and making the JVM serialize and deserialize objects passed from one class instance to the other -because it doesn't know that they are actually the same class-)
This is my OQL script that selects (and count) classes that has the same name:
var classes = {};
var multipleLoadedClasses = {};
heap.forEachClass(function(it) {
if (classes[it.name] != null) {
if (multipleLoadedClasses[it.name] != null) {
multipleLoadedClasses[it.name] = multipleLoadedClasses[it.name] + 1;
} else {
multipleLoadedClasses[it.name] = 1;
}
} else {
classes[it.name] = it;
}
});
multipleLoadedClasses;
hopes that this will help further visitors ;)

Categories

Resources