JVMTI - how to get the value of a method parameter from callback - java

I am recording all method entries from my Java app thanks to a JVMTI Agent. For now, I am able to get the name of each method, but I'd want to be able to get the value of the parameters that method received.
This problem has already been discussed in an older topic (see How to get parameter values in a MethodEntry callback); it fits perfectly what I'm looking for, so I know I have to use GetLocalObject function, but I can't figure out how to (the example given in the topic is broken).
Can anyone help me finding out how to do this? Thanks.

I think you want to access arbitrary method parameters without foreknowledge of their content, if not could you clarify your question?
See the JVMTI docs on local variables.
First, you need to ensure you have enabled local variable access in your capabilities list. Then, find out what parameters are available using GetLocalVariableTable. The returned table will contain a description of each local variable in the method, including the parameters. Don't forget to Deallocate it when you're done.
You'll need to work out which variables are parameters. You can do that by finding the current jlocation and eliminating local variables which are not yet available. This won't tell you the parameter order, but it'll tell you which locals are parameters. You can probably assume that the slot number is the correct order.
Find the current jlocation using GetFrameLocation, iterate over the local variable table, and for each local variable whose start_location is less than or equal to your current location, add the slot number and type to your list of parameters.
For each parameter, call the appropriate GetLocal{X} method based on its type. You'll need the depth of your current frame, which you already have from GetFrameLocation.
That should get you your parameters, but it'll be slow and tricky to implement. You'd be far better off following the guide's recommendation of avoiding MethodEntry callbacks and use bytecode instrumentation (BCI) instead.

Related

Mention any member via Java DIscord Bot

So i am making a bot where the purpose of it would be to tag the user who has been reported by typing .inappropriate #discordUser.
Here is the sample:
if(message.getMessageContent().equalsIgnoreCase(main.prefix + "inappropriate"))
{
message.getChannel().sendMessage("username of <#!USER_ID> is inappropriate.");
}
However, the problem is that it is not a specified user. In other words, it won't always be the same user.
So this is how it should look on Discord:
Me: .inappropriate #discordUser
Bot: username of #discordUser is inappropriate.
So, i wanted to know, how i can make this possible?
You didn't tell which discord wrapper you are using, but from getMessageContent(), it seems to be Javacord. And if it not, note that everything that I will say are the same/have equivalent in other wrappers.
First you need to get the id or the member mentioned.
Second you have to make a mention from it.
To get the mentioned member, you can use the method Message#getMentionedUsers() which returns a List of the users mentioned in the message. This means that you can even get several users.
To get the id, either you use User#getId() or User#getIdAsString() or you can try to parse the Message#getMessageContent() by for example splitting it and then using a regex (remember that a mention is <#!id>)
How do you get a mention from user or id ? From the user, you can simply use the method User#getMentionTag​() or User#getNicknameMentionTag​​(). From the id, you can append "<#!" + id + ">".
So in short, you can either do :
message → member (method) → mention (method)
message → id (manual parsing) → mention (manual appending)
message → member (method) → id (getter method) → mention (method)
The last one may seem useless, but in the case where you store ids (you can't store entities), it can be useful.
And also, you can retrieve member from id, but it's useless here compared to the other on top of needing intents, actually you can simply do the first solution, it's just two method calls.
I gave you several ways to do it, some of them are manual, other use existing methods. You should prefer using those method unless it's not convenient for you (ie you want your own command parser so you can't use getMentionedUsers()).
Also, you can look up at the method of each classes, you may find gold, the doc is available in your ide or online here with a search bar.
I knew the wrapper JDA but I have no idea about Javacord until I answer your question.
It's my first answer, I hope I didn't mess up something.

How to set a hostname in a jsonnet file?

I am trying to get the hang of jsonnet files. So far all I have is hard-coded values but what if I wanted to get the hostname for a Java application. For example in Java I would just do:
String hostName = System.getenv("HOSTNAME");
But obviously I can't just have a key-value pair like the following JSON in a jsonnet file.
{name: "hostname", value:System.getenv("HOSTNAME")}
I need a bit of help in understanding how I can do this.
I have looked up std.extvar(x) but the examples I look at just arent clear to me for whatever reason. Is this method relevant? Otherwise, I'm not really sure.
Jsonnet requires all parameters to be passed explicitly. To use a hostname in your Jsonnet code, you need to pass it to the interpreter. For example you can run it as follows:
❯ jsonnet --ext-str "HOSTNAME=$HOST" foo.jsonnet
foo.jsonnet:
std.extVar('HOSTNAME')
You can also use top-level-arguments mechanism to a similar effect (top-level-arguments are passed as function arguments to the evaluated script.
Please see: https://jsonnet.org/learning/tutorial.html#parameterize-entire-config for more in-depth explanation of these features.
FYI not being able to just grab any environment variable or access the system directly is very much by design. The result of Jsonnet evaluation depends only on the code and explicitly passed parameters. This has a lot of benefits, such as the following:
You can easily evaluate on another machine, even on a completely different platform and get exactly the same result.
You are never locked in to configuration on any particular machine – you can always pass any parameters on any machine (very useful for development and debugging).
Avoiding surprises – the evaluation won't break one day, because some random aspect of local configuration changed and some deep part of the code happens to depend on it – all parameters are accounted for.

The reference of the object changes in every debug

Doubtlessly, this question is asked already (may be many times) but I could not find the correct keywords to find them.
Basically, my question is about the object references. What I know is that the object references points the objects physical location on the memory. However, when I debug my code and every time when I debug, I get a difference object reference for the same object.
For example, when I firstly debugged my code and the reference of a button looks like
INFO [sysout] [AWT-EventQueue-0]
[Ljava.awt.event.ComponentListener;#28be012c
at the second time, it is
INFO [sysout] [AWT-EventQueue-0]
[Ljava.awt.event.ComponentListener;#31a056d8
My related questions are;
1.Is the part after (#) symbol (a.k.a #28be012c) reference to the object, if yes, it is something like ip address, which changes continiously?
2.Is there a way to obtain an address, which does not change over time (like a Mac-address)
Any answer or link related to these questions will be highly appreciated.
Edit
I am debugging in this scenario. There is a button and everytime when this button is clicked, the debugger stops at this point. That is to say, the program is not started from the beginning.
Is the part after (#) symbol (a.k.a #28be012c) reference to the object, if yes, it is something like ip address, which changes
continiously?
The part after the # is Integer.toHexString(hashCode());. The hashCodemethod is not designed to return the same value every time it is invoked for different runs (even if the object being created has the same value). It is also not mandatory that the returned value is related to the memory. JVM spec specifies that a unique value should be returned, but it doesn't specify "how".
Is there a way to obtain an address, which does not change over time
(like a Mac-adress)
No. Each run of the JVM will almost always give different hashcodes (unless you override the hashCode method to return something else.

eclipse - search variable name by it's value in debugger

I'm debugging web app, which produces very complex bean as result of form, and I'd like to know if value that I entered on some form field is present somewhere or not.
Is there any way to find if some of my variables (on debug list) has given value?
PS:
There isn't any way to search thou all variables (I have hundreds of them...) shown in debug list? Problem is that this bean is made of tens of hashmaps and lists, on different levels. And real problem is that I don't really know which variable holds this value or if it wasn't saved to any variable. And I can't write such big expression cover all of variables, structure is too complex.
Add a breakpoint at a location where you can access the variables you want, then add a watch for each variable and you can see the list of the values of the variables in the watch list
PS: In a watch you can write whatever Java code you want such as x.equals("value") and it will output true if equals or false if otherwise. Or you can just visualize the variable's value directly

How to get address of a Java Object? [duplicate]

This question already has answers here:
Is there a way to get a reference address? [duplicate]
(5 answers)
Closed 8 years ago.
Is there a way to get address of a Java object?
Where the question comes from?:
At First, I read properties file and all the data from file was placed into table. Properties file can update. So, I want to listen that file. I listen an object using PropertyChangeSupport and PropertyChangeListener.
updatedStatus = new basit.data.MyString();
updatedStatus.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
//After changes "i", we inform the table model about new value
public void propertyChange(PropertyChangeEvent evt) {
Object objec=evt.getNewValue();
tableModel.setValueAt(objec.toString(), 0, 5);
}
});
If updatedStatus changes then i update table. MyString class have private String "Value". I want to listen properties file. So, it should make updatedStatus.value and String of Properties File equal at the same address. If i can do it, so i don't need to listen properties file.
updatedStatus.setValue(resourceMap.getString("HDI.Device.1.Name"));
I tried to use StringBuffer, but i couldn't achieve it. That's why, I asked the question.
Firstly - no, you can't get the address of an object in Java; at least, not pure Java with no debugging agent etc. The address can move over time, for one thing. You don't need it.
Secondly, it's slightly hard to follow your explanation but you certainly won't be able to get away without listening for changes to the file itself. Once you've loaded the file into a Properties object, any later changes to the file on disk won't be visible in that object unless you specifically reload it.
Basically you should listen for changes to the file (or poll it) and reload the file (either into a new Properties or overwriting the existing one) at that point. Quite whether you also need to listen for updates on the string container will depend on your application.
System.identityHashCode(obj) delivers the next-best thing: a number unique for each object. It corresponds to the default Object.hashCode() implementation.
To quote the API: "As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)".
we can get address of an object in memory. Well how? it is like that;
using sun.misc.Unsafe class in java.
create new Unsafe object and use the getAddress(Object); method and it will return a long value that is address.
and also there are many methods for this class.
you can change the values in this address using putInt(Object,long offset, int value) or like this method.(getting some value getnt(Object)).
Note: this class is really UNSAFE . if you make wrong things on your project, JVM will be stopped.
Look into Apache Commons Configuration. This library has support for dynamic reloading of (for example) property files. See here.
The best way to observe if some file changes is IMHO to make a hash value with sha1 or mda5 and save the value in a cache. And you make a Thread that every minutes, seconds, depends how often you watch file changes, and make hash value over the file. So you can compare this two values and if the values are not equivalent so you can reload the new file.
Java not like C/C++. in C++, you will often work with address (that C++ programmer has a concept call pointer). But, I afraid that not in Java. Java is very safe that prevent you to touch its address.
But, there other ways maybe same with your idea is use HashCode. HashCode of an object base on their address on HEAP.

Categories

Resources