ObjectReference underlying object in JDI and JPDA - java

Very specifically, in JDI and JPDA context, I have the following questions:
Why ObjectReference does not expose its underlying object? Is it based on some specification? Are all implementations such as Eclipse Debug Project the same that do not expose the underlying object?
Considering the situation that you have the uniqueID() from ObjectReference, is there any way to resolve the underlying object from JVM?
If no to the previous question, then what is the best way to resolve the underlying object? I should add that I am familiar with how Value's can be obtained from StackFrame information, but I really need the object reference not the internal values or structure of the fields.

Why ObjectReference does not expose its underlying object?
I am assuming that you are referring to the com.sun.jdi.ObjectReference interface. If so, it is a combination of two things:
On the face of it, it wouldn't make sense. The ObjectReference is in the JVM running the debugger, but the corresponding Java object exists on the target machine.
Assuming that it did make sense, then it would be a bad thing to expose the actual pbject addresses and memory contents. This would allow the debugger to do things to the target JVM that would lead to hard crashes.
Considering the situation that you have the uniqueID() from ObjectReference, is there any way to resolve the underlying object from JVM?
No.
If no to the previous question, then what is the best way to resolve the underlying object?
AFAIK, there is no way to do this, apart from writing your own debug agent in C / C++ using the JVM Tool Interface and configuring the target JVM to run it.

Related

Can I have a classloader find Java classes dynamically?

I want to select different implementations of classes dynamically, based on a runtime condition. Let's say I have a class with fully qualified class name C. My running system may have many definitions of class C, each of which is in its own jar. I have a runtime condition (held in a ThreadLocal) that tells which definition should be chosen.
I was asked in a comment to clarify the original requirement, so I will clarify the requirement as best I can. There are multiple teams writing software to contribute to this system - something like 4000 classes in many independent modules. What's more they can change over time. They are currently running in separate JVMs so there is no issue with classes overlapping. Now we are considering running them in the same JVM with multiple releases running simultaneously on the same JVM; which specific set of implementations used being differentiated by the ThreadLocal. So the original problem was how to allow a thread to at one time run one set of implementations and at another time run another.
I have a tomcat application that is currently using OpenJDK 8.
I believe I can write a custom ClassLoader that manipulates the classpath to choose the definition of C differently based on the ThreadLocal. But I'm afraid the results will be cached somewhere such as JVM Code Cache. Unless I can override that behavior too, the next time the class is needed, the runtime condition may have changed and the version in the cache would be wrong.
Is there any way to do what I need to do?
Well, the simple solution would be to NOT have multiple definitions of class C, but instead have 'class C1', 'class C2', etc (i.e. they don't overlap and can be simultaneously loaded) and then your runtime property just picks the right one as appropriate. That is way-way the easiest solution, so strongly consider it first. But it may not meet your needs.
If you truly need to have multiple separate implementations of a single 'class C', then what you are effectively talking about is a 'hot swap' scenario. Fortunately, Tomcat and other tools got good (with limitations) at hotswapping long-time-back. You likely already know this, but 'hot swapping' meets the need of a developer who codes 'class C', deploys it to a container, tries it out, realizes it has a glitch, makes a quick code edit and wants to run the modified code without relaunching the container. Hotswapping does this by basically overlaying the new implementation in the JVM. It only works up to a point because each 'redeploy' pollutes the 'class space' of the JVM and you eventually run of of 'class space memory' and/or the JVM starts going unstable. Depending on your needs and tolerances though, hotswapping might work.
The clean way to do what you want is to define C as an interface, then you can load and use any class that implements interface C

How to pass an object between two JVM in java?

Recently I was asked this question in an interview: how can you pass an object between two JVMs? My response was using serialization, but I don't know if it's the right answer. How else could an object be passed between two JVMs?
Serialization is the perhaps only way out. Depending on your stack you could have one of the several possibilities
serialize class and deserialize them on the other end (remember remote ejb's)
write an object to a file (json etc) and read it on the other end from shared folder
or use use mciroservices to send and receive objects
you could also try out tools like protobuf, avro as they tackle the serialization problem specifically
My personal preference would be to have a small server side component (a service) for exchanging data.
You can pass Java Objects between 2 JVMs in a distributed environment as long as both the versions of JVMs are identical. Please note, your JVM is platform dependent (Platform includes Hardware (Processor) + OS). However, you need to make sure all dependent library files are available on both JVMs. Another drawback is that even if your JVMs are the same, the object passing is of no use if you are passing Java object running in one JVM to JRuby running in receiving JVM as the data types are different between the 2.
If if JVMs are same and all libraries are available, object passing is not recommended as you might decide to upgrade on OS from 32 bit to 64 bit and in that case, you need to upgrade JVM as well.
Object passing is something i prefer only within the same JVM.
You can store the object externally. Instead of a file you can go with a fast access data structure store like redis https://redis.io/ . Both(or more) the instances can read and write data to the same data store. You can also look into JMS(Java Messaging Service)

Is it possible to redefine core JDK classes using instrumentation?

I want to redefine the bytecode of the StackOverflowError constructor so I have a "hook" for when a stack overflow occurs. All I want to do is insert a single method call to a static method of my choosing at the start of the constructor. Is it possible to do this?
You should be able to do it using one of two ways (unless something changed in the last 1-2 years, in which case I'd love some links to changelogs/docs):
Mentioned in a comment, not very feasible I guess, modify the classes you are interested in, put them in a jar and then use the -bootclasspath option to load them instead of the default ones. As was mentioned before this can have some legal issues (and is a pain to do in general).
You should be able to (or at least you used to be able to) instrument almost all core classes (iirc Class was the only exception I've seen). One of many problems you might have is the fact that many of core classes are being initialized before the agents you provide (or well their premain methods to be exact) are consulted. To overcome this you will have to add Can-Retransform-Classes property to your agent jar and then re-transform the classes you are interested in. Be aware that re-transformation is a bit less powerful and doesn't give you all the options you'd have normally with instrumentation, you can read more about it in the doc.
I am assuming you know how to do instrumentation?
There are several things to consider.
It is possible to redefine java.lang.StackOverflowError. I tried it successfully on 1.7.0_40. isModifiableClass(java.lang.StackOverflowError.class) return true and I successfully redefined it inserting a method invocation into all of its constructors
You should be aware that when you insert a method call into a class via Instrumentation you still have to obey the visibility imposed by the ClassLoader relationships. Since StackOverflowError is loaded by the bootstrap loader it can only invoke methods of classes loaded by the bootstrap loader. You would have to add the target method’s class(es) to the bootstrap loader
This works if the application’s code throws a StackOverflowError manually. However, when a real stackoverflow occurs, the last thing the JVM will do is to invoke additional methods (keep in mind what the error says, the stack is full). Consequently it creates an instance of StackOverflowError without calling its constructor (a JVM can do that). So your instrumentation is pointless in this situation.
As already pointed out by others, a “Pure Java Application” must not rely on modified JRE classes. It is only valid to use Instrumentation as add-on, i.e. development or JVM management tool. You should keep in mind that the fact that Oracle’s JVM 1.7.0_40 supports the redefinition of StackOverflowError does not imply that other versions or other JVMs do as well.

"Object Breakpoint" - How to debug acess to a specific Object in a large code base with complex dynamic behavior?

Every once in a while I'm in the Eclipse Debug mode, and wish I could simply pick the Object that I am currently inspecting/watching, put some kind of "Object Breakpoint" on it, and step to the next line of code that accesses it.
Now, I know that I can put breakpoints on Classes, but I usually have hundreds or even thousands of instances in memory, most of which have a long life time. They often go in and out of frameworks. They are wrapped into Collections, filtered and unwrapped again. In short: a regular, large application.
Usually I still find the problem by looking for rare features of that Object, using conditional method breakpoints and a lot of informed guessing. However, I think I sometimes could be much faster if I had something like the described feature.
What I found after some searching is the Debug Proxy (scroll down to examples). It is a container class that will use Javas reflection API to make itself look like the contained Object, thus you can use it instead of the contained Object in your application. Being an InvocationHandler, the DebugProxy can now "intercept" invocations of methods in the contained Object.
Using the proxy for actual debugging is as easy as adding this line to your application.
IMyObject = (IMyObject) DebugProxy.newInstance(new MyObject());
I can then set breakpoints inside the DebugProxies source code.
However, there are at least two problems with this approach.
It works but it is still a hack, and there are a lot of features missing, such as filtering options.
The Proxy-Object cannot be down-cast to the implementing class.
The 2. problem is the more serious one. I was able to use the DebugProxy with Classes generated by EMF, and there is no problem to follow the Object throughout the Framework. However, when I am trying to debug code that doesn't use interfaces for all interesting Classes, the DebugProxy will quickly fail.
Does anybody know about alternatives?
Maybe the Eclipse JDT Debugger already has such a feature and I simply don't see it!?
I know there is the Java instrumentation API, and frameworks such as AspectJ. Could these be used to get a practical solution?
I added basic filtering to the DebugProxy and modified the output so Eclipse Console View shows a link to the calling line of code:
Problem number two remains unsolved, though. I put up the source code on GitHub. Maybe somebody will come up with something.
A completely different way to approach this would be to automatically add breakpoints with conditions comparing the current hashCode() with the HashCode of the Object in question. This may not be too difficult for someone who knows more about the JDT internals.

Using System Properties in Java

I have a question on using System Properties in Java. Some classes like Authenticator require that we set the system properties regarding Proxy settings and than verify whether the Proxy was valid or not.
My question is should I remove the Set Properties after I am done using it ?
There are other parts of programs that might be using these Properties, this change will autmatically impact thier functionality.
Is there a way, I can set Properties local to a Function (some wrapper class)?
What are the good practises for setting system properties and using them ?
Things that use System.properties should have properties that have a global meaning to the running JVM, so that if, for example, you set a proxy, it should be the relevant proxy across that process.
So therefore there is no need to set them back. In fact, setting them back might make some APIs confused, as they may assume they get back the relevant value at all times, and didn't just cache it when they read it.
Of course if a given API isn't using them that way, then you might have issues, but that would really be an issue with a given API, more than a good practice issue with System properties.
In general, due to threading and synchronization issues, it is probably a good practice to set System properties only at the beginning of the JVM startup (either on the command line or in the main thread before starting other threads) with the expectation that the values remain unchanged for the remainder of the time running the JVM.
This doesn't answer your question about system properties in general, but regarding your specific problem with proxy settings properties, perhaps you can use a ProxySelector to isolate the Test Proxy you mention in the comments here?
You could create a subclass of ProxySelector that you utilize for the test. Make it such that it only applies the test settings when the test URI is attempted. This would isolate it from other requests.
This sort of global proxy setting inflexibility is what initially drove me to use HttpClient for HTTP needs instead of Sun's API.
Edit:
I'm not sure how I ever missed this method, but it is possible to get a URL connection and supply the proxy settings to that connection alone via java.net.Url.openConnection(Proxy)
.
If there is a chance that some other part of your program (or some other webapp in the container, etc) might be affected by "temporary" settings then it is a good idea to remove them.
Best practice would be to try an find some other way to do what you are trying to do. For example, consider creating your own protocol class that overrides a standard one in the area where it figures out what proxy to use.
If you cannot do that, try to structure your code so that the sequence:
change the properties,
do the operation,
restore the properties,
is done in a mutex that respected by anything that might be affected by the properties you are changing. This may be a hard ask though ...

Categories

Resources