How do I find what an object refers to? - java

I'm trying to find a way to list which objects a run-time object is referring to. I know there is a way to enquire the jvm using oql but what I'd like to do is to query it from inside a program. Is there any API I could use?

You can do it via Reflection (java.lang.reflect).
How is described in this article. Basically, given this class that has private members:
public class Secret {
private String secretCode = "It's a secret";
private String getSecretCode(){
return secretCode;
}
}
With Reflection, you can access all of its members (including the private ones), including their values. And so you look at all of its data members to see what they refer to (and of course, you can repeat the process if they also refer to other objects). Here's how to access their members (this code shows methods as well, which you probably won't need if you're just interested in data, but I didn't see any good reason to pull that part out):
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Hacker {
private static final Object[] EMPTY = {};
public void reflect(Object instance)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class secretClass = instance.getClass();
// Print all the method names & execution result
Method methods[] = secretClass.getDeclaredMethods();
System.out.println("Access all the methods");
for (int i = 0; i < methods.length; i++) {
System.out.println("Method Name: " + methods[i].getName());
System.out.println("Return type: " + methods[i].getReturnType());
methods[i].setAccessible(true);
System.out.println(methods[i].invoke(instance, EMPTY) + "\n");
}
// Print all the field names & values
Field fields[] = secretClass.getDeclaredFields();
System.out.println("Access all the fields");
for (int i = 0; i < fields.length; i++){
System.out.println("Field Name: " + fields[i].getName());
fields[i].setAccessible(true);
System.out.println(fields[i].get(instance) + "\n");
}
}
public static void main(String[] args){
Hacker newHacker = new Hacker();
try {
newHacker.reflect(new Secret());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
I've fixed a bug in their original code and made a small change to make it more clear that Hacker is not in any way tied to Secret (other than in main).
Update: Re your question below about the fields from base classes, here's an updated Hacker that does that (I've assumed you don't want to try to enumerate the fields on Object, so I've stopped there):
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Hacker {
private static final Object[] EMPTY = {};
public void reflect(Object instance)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class cls = instance.getClass();
while (cls != null && cls != Object.class) {
System.out.println("From class: " + cls.getName());
// Print all the method names & execution result
Method methods[] = cls.getDeclaredMethods();
System.out.println("Access all the methods");
for (int i = 0; i < methods.length; i++) {
System.out.println("Method Name: " + methods[i].getName());
System.out.println("Return type: " + methods[i].getReturnType());
methods[i].setAccessible(true);
System.out.println(methods[i].invoke(instance, EMPTY) + "\n");
}
// Print all the field names & values
Field fields[] = cls.getDeclaredFields();
System.out.println("Access all the fields");
for (int i = 0; i < fields.length; i++){
System.out.println("Field Name: " + fields[i].getName());
fields[i].setAccessible(true);
System.out.println(fields[i].get(instance) + "\n");
}
// Go to the base class
cls = cls.getSuperclass();
}
}
public static void main(String[] args){
Hacker newHacker = new Hacker();
try {
newHacker.reflect(new Secret());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
When combined with
public class BaseSecret {
private String baseSecretCode = "It's a base secret";
}
and
public class Secret extends BaseSecret {
private String secretCode = "It's a secret";
private String getSecretCode(){
return secretCode;
}
}
you get:
$ java Hacker
From class: Secret
Access all the methods
Method Name: getSecretCode
Return type: class java.lang.String
It's a secret
Access all the fields
Field Name: secretCode
It's a secret
From class: BaseSecret
Access all the methods
Access all the fields
Field Name: baseSecretCode
It's a base secret

You can use getClass() method of Object class to get the runtime class of an object.

Related

how to create an object from Field.getType() reflection?

I create an reflection function to create a new object and set data inside.
This is my code but, i dont know how to fill object declaration class type:
<Class-Type> newObj = f.getType().getConstructor(new Class[]{}).newInstance();
f is a java.lang.reflect.Field that i get from class.getDeclaredFields()
i already try using Object type
Object newObj = f.getType().getConstructor(new Class[]{}).newInstance();
but after i invoke data
Method setterNewObj =newObj.getClass().getDeclaredMethod("set" + Character.toUpperCase(m.getName().charAt(0))+ m.getName().substring(1), m.getType());
setterNewObj.invoke(newObj, this.typeConvert(mapOfValue.get(nameOfColumn), m.getType()));
and i print.out the result data is not set (null);
Thanks
From what we can see, your code is not wrong.
Perhaps you need to provide a more complete code sample or some extra information of what you do, so we can check.
I have created a small piece of code (complete and runnable) to show you that it works:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class Buddy {
String name;
Buddy buddy;
public Buddy() {}
public Buddy(String n) {
this();
name = n;
}
public void setBuddy(Buddy b) {
if (this.buddy != null)
this.buddy.buddy = null;
this.buddy = b;
b.buddy = this;
}
public void setName(String name) {
this.name = name;
}
private String getInfo() {
return name;
}
public void display() {
if (buddy != null)
System.out.println(this.getInfo() +" & "+ buddy.getInfo());
else
System.out.println(this.getInfo());
}
public static void main(String args[]) {
Buddy s1 = new Buddy("Rick");
s1.display();
System.out.println("\nNeeds his buddy 'Morty' :");
Buddy s2 = new Buddy("Morty");
s1.setBuddy(s2);
s1.display();
s2.display();
System.out.println("\nChange to new buddy 'Roller':");
try {
// Get the buddy field
Field f = s1.getClass().getDeclaredField("buddy");
// Create a new Buddy instance
Object newObj = f.getType().getConstructor(new Class[]{}).newInstance();
// Get the name field
Field m = newObj.getClass().getDeclaredField("name");
// Get the setter for the name field
Method setterNewObj = newObj.getClass().getDeclaredMethod("set" + Character.toUpperCase(m.getName().charAt(0))+ m.getName().substring(1), m.getType());
// Invoke the setter for the name field with a value
setterNewObj.invoke(newObj, "Roller");
// Get the setter for the buddy field
Method setterS1 = s1.getClass().getDeclaredMethod("set" + Character.toUpperCase(f.getName().charAt(0))+ f.getName().substring(1), f.getType());
// Invoke the setter for the buddy field with the new Buddy instance
setterS1.invoke(s1, newObj);
} catch (Exception e) {
e.printStackTrace();
}
s1.display();
s2.display();
}
}
Which you can see prints the newly created buddy and the old buddy still exists:
Rick
Needs his buddy 'Morty' :
Rick & Morty
Morty & Rick
Change to new buddy 'Roller':
Rick & Roller
Morty

Java: Easy way of passing a method as a parameter [duplicate]

I need to find the caller of a method. Is it possible using stacktrace or reflection?
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()
According to the Javadocs:
The last element of the array represents the bottom of the stack, which is the least recent method invocation in the sequence.
A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().
You will have to experiment to determine which index you want
(probably stackTraceElements[1] or [2]).
Note: if you are using Java 9 or later you should use StackWalker.getCallerClass() as described in Ali Dehghani's answer.
The comparison of different methods below is mostly interesting for historical reason.
An alternative solution can be found in a comment to this request for enhancement.
It uses the getClassContext() method of a custom SecurityManager and seems to be faster than the stack trace method.
The following program tests the speed of the different suggested methods (the most interesting bit is in the inner class SecurityManagerMethod):
/**
* Test the speed of various methods for getting the caller class name
*/
public class TestGetCallerClassName {
/**
* Abstract class for testing different methods of getting the caller class name
*/
private static abstract class GetCallerClassNameMethod {
public abstract String getCallerClassName(int callStackDepth);
public abstract String getMethodName();
}
/**
* Uses the internal Reflection class
*/
private static class ReflectionMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return sun.reflect.Reflection.getCallerClass(callStackDepth).getName();
}
public String getMethodName() {
return "Reflection";
}
}
/**
* Get a stack trace from the current thread
*/
private static class ThreadStackTraceMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return Thread.currentThread().getStackTrace()[callStackDepth].getClassName();
}
public String getMethodName() {
return "Current Thread StackTrace";
}
}
/**
* Get a stack trace from a new Throwable
*/
private static class ThrowableStackTraceMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return new Throwable().getStackTrace()[callStackDepth].getClassName();
}
public String getMethodName() {
return "Throwable StackTrace";
}
}
/**
* Use the SecurityManager.getClassContext()
*/
private static class SecurityManagerMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return mySecurityManager.getCallerClassName(callStackDepth);
}
public String getMethodName() {
return "SecurityManager";
}
/**
* A custom security manager that exposes the getClassContext() information
*/
static class MySecurityManager extends SecurityManager {
public String getCallerClassName(int callStackDepth) {
return getClassContext()[callStackDepth].getName();
}
}
private final static MySecurityManager mySecurityManager =
new MySecurityManager();
}
/**
* Test all four methods
*/
public static void main(String[] args) {
testMethod(new ReflectionMethod());
testMethod(new ThreadStackTraceMethod());
testMethod(new ThrowableStackTraceMethod());
testMethod(new SecurityManagerMethod());
}
private static void testMethod(GetCallerClassNameMethod method) {
long startTime = System.nanoTime();
String className = null;
for (int i = 0; i < 1000000; i++) {
className = method.getCallerClassName(2);
}
printElapsedTime(method.getMethodName(), startTime);
}
private static void printElapsedTime(String title, long startTime) {
System.out.println(title + ": " + ((double)(System.nanoTime() - startTime))/1000000 + " ms.");
}
}
An example of the output from my 2.4 GHz Intel Core 2 Duo MacBook running Java 1.6.0_17:
Reflection: 10.195 ms.
Current Thread StackTrace: 5886.964 ms.
Throwable StackTrace: 4700.073 ms.
SecurityManager: 1046.804 ms.
The internal Reflection method is much faster than the others. Getting a stack trace from a newly created Throwable is faster than getting it from the current Thread. And among the non-internal ways of finding the caller class the custom SecurityManager seems to be the fastest.
Update
As lyomi points out in this comment the sun.reflect.Reflection.getCallerClass() method has been disabled by default in Java 7 update 40 and removed completely in Java 8. Read more about this in this issue in the Java bug database.
Update 2
As zammbi has found, Oracle was forced to back out of the change that removed the sun.reflect.Reflection.getCallerClass(). It is still available in Java 8 (but it is deprecated).
Update 3
3 years after: Update on timing with current JVM.
> java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)
> java TestGetCallerClassName
Reflection: 0.194s.
Current Thread StackTrace: 3.887s.
Throwable StackTrace: 3.173s.
SecurityManager: 0.565s.
Java 9 - JEP 259: Stack-Walking API
JEP 259 provides an efficient standard API for stack walking that allows easy filtering of, and lazy access to, the information in stack traces. Before Stack-Walking API, common ways of accessing stack frames were:
Throwable::getStackTrace and Thread::getStackTrace return an array of
StackTraceElement objects, which contain the class name and method
name of each stack-trace element.
SecurityManager::getClassContext is a protected method, which allows a
SecurityManager subclass to access the class context.
JDK-internal sun.reflect.Reflection::getCallerClass method which you shouldn't use anyway
Using these APIs are usually inefficient:
These APIs require the VM to eagerly capture a snapshot of the entire
stack, and they return information representing the entire stack.
There is no way to avoid the cost of examining all the frames if the
caller is only interested in the top few frames on the stack.
In order to find the immediate caller's class, first obtain a StackWalker:
StackWalker walker = StackWalker
.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
Then either call the getCallerClass():
Class<?> callerClass = walker.getCallerClass();
or walk the StackFrames and get the first preceding StackFrame:
walker.walk(frames -> frames
.map(StackWalker.StackFrame::getDeclaringClass)
.skip(1)
.findFirst());
Sounds like you're trying to avoid passing a reference to this into the method. Passing this is way better than finding the caller through the current stack trace. Refactoring to a more OO design is even better. You shouldn't need to know the caller. Pass a callback object if necessary.
Oneliner:
Thread.currentThread().getStackTrace()[2].getMethodName()
Note that you might need to replace the 2 with 1.
This method does the same thing but a little more simply and possibly a little more performant and in the event you are using reflection, it skips those frames automatically. The only issue is it may not be present in non-Sun JVMs, although it is included in the runtime classes of JRockit 1.4-->1.6. (Point is, it is not a public class).
sun.reflect.Reflection
/** Returns the class of the method <code>realFramesToSkip</code>
frames up the stack (zero-based), ignoring frames associated
with java.lang.reflect.Method.invoke() and its implementation.
The first frame is that associated with this method, so
<code>getCallerClass(0)</code> returns the Class object for
sun.reflect.Reflection. Frames associated with
java.lang.reflect.Method.invoke() and its implementation are
completely ignored and do not count toward the number of "real"
frames skipped. */
public static native Class getCallerClass(int realFramesToSkip);
As far as what the realFramesToSkip value should be, the Sun 1.5 and 1.6 VM versions of java.lang.System, there is a package protected method called getCallerClass() which calls sun.reflect.Reflection.getCallerClass(3), but in my helper utility class I used 4 since there is the added frame of the helper class invocation.
/**
* Get the method name for a depth in call stack. <br />
* Utility function
* #param depth depth in the call stack (0 means current method, 1 means call method, ...)
* #return method name
*/
public static String getMethodName(final int depth)
{
final StackTraceElement[] ste = new Throwable().getStackTrace();
//System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
return ste[ste.length - depth].getMethodName();
}
For example, if you try to get the calling method line for debug purpose, you need to get past the Utility class in which you code those static methods:
(old java1.4 code, just to illustrate a potential StackTraceElement usage)
/**
* Returns the first "[class#method(line)]: " of the first class not equal to "StackTraceUtils". <br />
* From the Stack Trace.
* #return "[class#method(line)]: " (never empty, first class past StackTraceUtils)
*/
public static String getClassMethodLine()
{
return getClassMethodLine(null);
}
/**
* Returns the first "[class#method(line)]: " of the first class not equal to "StackTraceUtils" and aclass. <br />
* Allows to get past a certain class.
* #param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils.
* #return "[class#method(line)]: " (never empty, because if aclass is not found, returns first class past StackTraceUtils)
*/
public static String getClassMethodLine(final Class aclass)
{
final StackTraceElement st = getCallingStackTraceElement(aclass);
final String amsg = "[" + st.getClassName() + "#" + st.getMethodName() + "(" + st.getLineNumber()
+")] <" + Thread.currentThread().getName() + ">: ";
return amsg;
}
/**
* Returns the first stack trace element of the first class not equal to "StackTraceUtils" or "LogUtils" and aClass. <br />
* Stored in array of the callstack. <br />
* Allows to get past a certain class.
* #param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils.
* #return stackTraceElement (never null, because if aClass is not found, returns first class past StackTraceUtils)
* #throws AssertionFailedException if resulting statckTrace is null (RuntimeException)
*/
public static StackTraceElement getCallingStackTraceElement(final Class aclass)
{
final Throwable t = new Throwable();
final StackTraceElement[] ste = t.getStackTrace();
int index = 1;
final int limit = ste.length;
StackTraceElement st = ste[index];
String className = st.getClassName();
boolean aclassfound = false;
if(aclass == null)
{
aclassfound = true;
}
StackTraceElement resst = null;
while(index < limit)
{
if(shouldExamine(className, aclass) == true)
{
if(resst == null)
{
resst = st;
}
if(aclassfound == true)
{
final StackTraceElement ast = onClassfound(aclass, className, st);
if(ast != null)
{
resst = ast;
break;
}
}
else
{
if(aclass != null && aclass.getName().equals(className) == true)
{
aclassfound = true;
}
}
}
index = index + 1;
st = ste[index];
className = st.getClassName();
}
if(resst == null)
{
//Assert.isNotNull(resst, "stack trace should null"); //NO OTHERWISE circular dependencies
throw new AssertionFailedException(StackTraceUtils.getClassMethodLine() + " null argument:" + "stack trace should null"); //$NON-NLS-1$
}
return resst;
}
static private boolean shouldExamine(String className, Class aclass)
{
final boolean res = StackTraceUtils.class.getName().equals(className) == false && (className.endsWith("LogUtils"
) == false || (aclass !=null && aclass.getName().endsWith("LogUtils")));
return res;
}
static private StackTraceElement onClassfound(Class aclass, String className, StackTraceElement st)
{
StackTraceElement resst = null;
if(aclass != null && aclass.getName().equals(className) == false)
{
resst = st;
}
if(aclass == null)
{
resst = st;
}
return resst;
}
I've done this before. You can just create a new exception and grab the stack trace on it without throwing it, then examine the stack trace. As the other answer says though, it's extremely costly--don't do it in a tight loop.
I've done it before for a logging utility on an app where performance didn't matter much (Performance rarely matters much at all, actually--as long as you display the result to an action such as a button click quickly).
It was before you could get the stack trace, exceptions just had .printStackTrace() so I had to redirect System.out to a stream of my own creation, then (new Exception()).printStackTrace(); Redirect System.out back and parse the stream. Fun stuff.
private void parseExceptionContents(
final Exception exception,
final OutputStream out)
{
final StackTraceElement[] stackTrace = exception.getStackTrace();
int index = 0;
for (StackTraceElement element : stackTrace)
{
final String exceptionMsg =
"Exception thrown from " + element.getMethodName()
+ " in class " + element.getClassName() + " [on line number "
+ element.getLineNumber() + " of file " + element.getFileName() + "]";
try
{
out.write((headerLine + newLine).getBytes());
out.write((headerTitlePortion + index++ + newLine).getBytes() );
out.write((headerLine + newLine).getBytes());
out.write((exceptionMsg + newLine + newLine).getBytes());
out.write(
("Exception.toString: " + element.toString() + newLine).getBytes());
}
catch (IOException ioEx)
{
System.err.println(
"IOException encountered while trying to write "
+ "StackTraceElement data to provided OutputStream.\n"
+ ioEx.getMessage() );
}
}
}
Here is a part of the code that I made based in the hints showed in this topic.
Hope it helps.
(Feel free to make any suggestions to improve this code, please tell me)
The counter:
public class InstanceCount{
private static Map<Integer, CounterInstanceLog> instanceMap = new HashMap<Integer, CounterInstanceLog>();
private CounterInstanceLog counterInstanceLog;
public void count() {
counterInstanceLog= new counterInstanceLog();
if(counterInstanceLog.getIdHashCode() != 0){
try {
if (instanceMap .containsKey(counterInstanceLog.getIdHashCode())) {
counterInstanceLog= instanceMap .get(counterInstanceLog.getIdHashCode());
}
counterInstanceLog.incrementCounter();
instanceMap .put(counterInstanceLog.getIdHashCode(), counterInstanceLog);
}
(...)
}
And the object:
public class CounterInstanceLog{
private int idHashCode;
private StackTraceElement[] arrayStackTraceElements;
private int instanceCount;
private String callerClassName;
private StackTraceElement getProjectClasses(int depth) {
if(depth< 10){
getCallerClassName(sun.reflect.Reflection.getCallerClass(depth).getName());
if(getCallerClassName().startsWith("com.yourproject.model")){
setStackTraceElements(Thread.currentThread().getStackTrace());
setIdHashCode();
return arrayStackTraceElements[depth];
}
//+2 because one new item are added to the stackflow
return getProjectClasses(profundidade+2);
}else{
return null;
}
}
private void setIdHashCode() {
if(getNomeClasse() != null){
this.idHashCode = (getCallerClassName()).hashCode();
}
}
public void incrementaContador() {
this.instanceCount++;
}
//getters and setters
(...)
}
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
class DBConnection {
String createdBy = null;
DBConnection(Throwable whoCreatedMe) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(os);
whoCreatedMe.printStackTrace(pw);
try {
createdBy = os.toString();
pw.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ThrowableTest {
public static void main(String[] args) {
Throwable createdBy = new Throwable(
"Connection created from DBConnectionManager");
DBConnection conn = new DBConnection(createdBy);
System.out.println(conn.createdBy);
}
}
OR
public static interface ICallback<T> { T doOperation(); }
public class TestCallerOfMethod {
public static <T> T callTwo(final ICallback<T> c){
// Pass the object created at callee to the caller
// From the passed object we can get; what is the callee name like below.
System.out.println(c.getClass().getEnclosingMethod().getName());
return c.doOperation();
}
public static boolean callOne(){
ICallback callBackInstance = new ICallback(Boolean){
#Override
public Boolean doOperation()
{
return true;
}
};
return callTwo(callBackInstance);
}
public static void main(String[] args) {
callOne();
}
}
use this method:-
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
stackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
System.out.println(e.getMethodName());
Caller of method example Code is here:-
public class TestString {
public static void main(String[] args) {
TestString testString = new TestString();
testString.doit1();
testString.doit2();
testString.doit3();
testString.doit4();
}
public void doit() {
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
System.out.println(e.getMethodName());
}
public void doit1() {
doit();
}
public void doit2() {
doit();
}
public void doit3() {
doit();
}
public void doit4() {
doit();
}
}
Short answer ReflectionUtils.getCallingClass(0)
Long answer (code, Groovy)
package my
import org.codehaus.groovy.reflection.ReflectionUtils
import java.lang.reflect.Field
import java.lang.reflect.Method
trait Reflector {
static String[] fieldNames() {
List<String> names = []
Arrays.asList(naturalFields()).forEach { Field fl -> names.add(fl.name) }
return names.toArray() as String[]
}
static Field[] naturalFields() {
return finalClass().getDeclaredFields().findAll { Field fl -> !fl.synthetic }.collect()
}
static Method[] naturalMethods() {
return finalClass().getDeclaredMethods().findAll { Method md -> !md.synthetic }.collect()
}
static Class finalClass() {
return ReflectionUtils.getCallingClass(0)
}
}
class Demo implements Reflector {
int archived = 0
int demo = 100
static void playToo() {
println finalClass()
}
}
println Demo.finalClass() // class my.Demo
println Demo.naturalFields() // [private int my.Demo.archived, private int my.Demo.demo]
println Demo.fieldNames() // [archived, demo]

Creating a new object from method's param

Let's say you got a class x with a method copy().
This method copy() gets a class y as a param. copy(y test).
My question is, how do I make a new object out of the class that's sent as param just like this:
public void copy(y villy){
villy v = new villy();
}
You should consider that the y class is a parent one, and that I'll be passing as params its childs aswell, so what that method should do is creating a new object of the class that's sent as param!
If the parameter is a Class reference, and the class has a public constructor with no parameters:
public void copy(Class cls){
Object obj = cls.newInstance();
}
If the parameter is some object implementing the Cloneable interface, and another object of the same class is required:
public void copy(Cloneable obj1){
Object obj2 = obj1.clone();
}
EDIT 20.01.2016
So I assume that every object is a Pokemon, which has some abilities, and it has a method copy used to copy the abilities of another Pokemon. Then I would do it like this:
public class FET {
public static void main(String[] args){
Pokemon aerodactyl = new Pokemon (new Ability[]{ Ability.WALK, Ability.FLY });
Pokemon golduck = new Pokemon (new Ability[]{ Ability.WALK, Ability.SWIM });
System.out.println ("aerodactyl = " + aerodactyl);
System.out.println ("golduck = " + golduck );
System.out.println ();
golduck.copy (aerodactyl);
System.out.println ("aerodactyl = " + aerodactyl);
System.out.println ("golduck = " + golduck ); // golduck has now the same abilities as aerodactyl
System.out.println ();
aerodactyl.abilities[0] = Ability.EXPLODE; // change aerodactyl's abilities
System.out.println ("aerodactyl = " + aerodactyl);
System.out.println ("golduck = " + golduck ); // abilities of aerodactyl have changed but golduck's not
System.out.println ();
}
}
enum Ability {
WALK,
FLY,
SWIM,
TALK,
EXPLODE
}
class Pokemon {
public Ability[] abilities;
public Pokemon (Ability[] abilities) { // constructor
this.abilities = abilities;
}
public void copy (Pokemon p) { // copy abilities of another Pokemon
abilities = (Ability[]) p.abilities.clone();
}
public String toString() { // string representation of Pokemon
String str = "Pokemon";
if (abilities != null) {
for(int i = 0; i < abilities.length; i++) {
str += (i==0) ? ": " : ", ";
str += abilities[i];
}
}
return str;
}
}

How can I create a class dynamically that extends another dynamic class using reflection?

I'm fetching a class dynamically like this:
Class<?> clazz = Class.forName("com.android.systemui.quicksettings.QuickSettingsTile");
I'd like to create another class called DummyTile thats extends my previous class. It would have looked like this:
public class DummyTile extends QuickSettingsTile {
public DummyTile(Context context, QuickSettingsController qsc) {
super(context, qsc);
}
public void updateTile() {
System.out.println("Hello");
}
#Override
public void updateResources() {
updateTile();
super.updateResources();
}
}
...but I'm not sure how to do this using reflection. This is the class that I'm trying to extend. I'm also not sure as to how I would override a method and initialise the object using the constructor. I've worked with very simple things using reflection but never dealt with extending another class dynamically.
If someone could point me in the right direction with some snippets, I'm confident that I'll be able to handle it from there.
You can’t do that with reflection. You can create interface implementations dynamically using java.lang.reflect.Proxy but that’s it.
If you want more you have to use third-party libraries. But these libraries usually work on a lower level, e.g. byte code and require some experience. And they cannot be used in restricted environments.
You can't really extend a class using reflection, but you can encapsulate it.
This is of course a major security risk and you should think hard about whether you want to allow this.
See: https://web.archive.org/web/20120201052157/http://initbinder.com/articles/hack_any_java_class_using_reflection_attack.html
Something like this should do the trick.
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.ClassNotFoundException;
import java.lang.InstantiationException;
import java.lang.IllegalAccessException;
import java.lang.reflect.InvocationTargetException;
import java.lang.NoSuchMethodException;
public class Tester {
private static String CLASS_NAME = "VictimClass";
private static Class victimClass = null;
private static Object victimClassObj = null;
public static void main(String[] args) {
victimClass = loadClass(victimClass, CLASS_NAME);
printClassStructure();
attack();
}
private static Class loadClass(Class clazz, String className) {
Thread thread = Thread.currentThread();
ClassLoader classLoader =
thread.getContextClassLoader();
try {
clazz = Class.forName(className, true, classLoader);
}
catch (ClassNotFoundException e) {
System.err.println("Error: could not find class: "
+ CLASS_NAME);
}
return clazz;
}
private static void printClassStructure() {
Constructor[] constructors =
victimClass.getDeclaredConstructors();
for (Constructor c : constructors) {
int modifier = c.getModifiers();
System.out.println("Declared constructor name: "
+ c.getName() + "ntis accessible: "
+ c.isAccessible() + "ntis private: "
+ Modifier.isPrivate(modifier) + "n");
}
Method[] methods = victimClass.getDeclaredMethods();
for (Method m : methods) {
int modifier = m.getModifiers();
System.out.println("Declared method name: " + m.getName()
+ "ntis accessible: "
+ m.isAccessible()
+ "ntis private: "
+ Modifier.isPrivate(modifier)
+ "ntis static: "
+ Modifier.isStatic(modifier) + "n");
}
Field[] fields = victimClass.getDeclaredFields();
for (Field f : fields) {
int modifier = f.getModifiers();
System.out.println("Declared field name: " + f.getName()
+ "ntis accessible: "
+ f.isAccessible()
+ "ntis private: "
+ Modifier.isPrivate(modifier)
+ "ntis static: "
+ Modifier.isStatic(modifier)
+ "ntis final: "
+ Modifier.isFinal(modifier) + "n");
}
}
private static void attack() {
Field[] fields = victimClass.getDeclaredFields();
Method[] methods = victimClass.getDeclaredMethods();
Constructor[] constructors = victimClass.getDeclaredConstructors();
//make constructor accessible
constructors[0].setAccessible(true);
System.err.println("Initiating reflection attack:");
try {
//create new object by invoking private constructor
victimClassObj = constructors[0].newInstance(new Object[] {});
//make static method accessible and get its value
//please note: when invoking static method,
//object represented by this Method is null
methods[2].setAccessible(true);
Object o = methods[2].invoke(null, new Object[] {});
System.out.println("Got user ID from private static accessor: "
+ o.toString());
//make method accessible and get its value
methods[0].setAccessible(true);
o = methods[0].invoke(victimClassObj, new Object[] {});
System.out.println("Got original password from private accessor: "
+ o.toString());
//make method accessible and set to it new value
methods[1].setAccessible(true);
System.out.println("Injecting new password using private mutator");
methods[1].invoke(victimClassObj, new Object[] {"injected_password"});
//get method’s its new value
o = methods[0].invoke(victimClassObj, new Object[] {});
System.out.println("Got injected password from private accessor: "
+ o.toString());
//make field accessible and get its value
fields[2].setAccessible(true);
o = fields[2].get(victimClassObj);
System.out.println("Got private field: " + o);
//make field accessible and set to it new value
System.out.println("Injecting value to a private field:");
fields[2].set(victimClassObj, "new_default_value");
//get field’s its new value
o = fields[2].get(victimClassObj);
System.out.println("Got updated private field: " + o);
//make field accessible and get its value
fields[1].setAccessible(true);
o = fields[1].get(victimClassObj);
System.out.println("Got private static field: " + o);
//make field accessible and set to it new value
System.out.println("Injecting value to a private static final field:");
fields[1].set(null, new Integer(2));
//get field’s its new value
o = fields[1].get(victimClassObj);
System.out.println("Got updated private static final field: " + o);
}
catch (InstantiationException e) {
System.err.println("Error: could not instantiate: " + e);
}
catch (IllegalAccessException e) {
System.err.println("Error: could not access: " + e);
}
catch (InvocationTargetException e) {
System.err.println("Error: could not invoke the target: " + e);
}
}
}
You can use Duckapter which adds duck typing to Java.
DummyTile tile = ...;
QuickSettingsTile settingsTile = Duck.type(tile, QuickSettingsTile.class);

HashMap.put causing an infinite loop in Java

So I have a class named MainControl that is ran from another class (The main one) that I am certain only runs once. Inside of MainControl I have a few things that have to be loaded, one of which being a function that populates the HashMap with the key set to the keybind (int) and the values set to a class that holds the information of the specific keybinds function (KeyDetails).
So to populate the hashmap it goes through 2 loops, the first being to loop through the list of functions, the second to check if the key should be bound to the function. If the second loop finds that it should be bound it will run Keybinds.put(KeyCode, new Details(Function, KeyCode, KeyName, false); (Just ignore the false).
For some reason it ends up forcing MainControl(); to run again once it reached Keybinds.put... for no reason at all. There are no functions that should cause MainControl to run and it works when I remove the Keybinds.put line. Just by removing THAT single line it works.
public MainControl()
{
System.out.println("Starting System");
LoadSession("Default");
System.out.println("Ended System - Never Reached");
}
public static void LoadSession(String s)
{
Keybinds = new HashMap();
for (int i = 0; i < FunctionStringList.length; i++)
{
String Key = "";
int KeyVal = 0;
try
{
for (int a = 0; a < KeyBindingList.length; a++)
{
if (KeyBindingList[a].KeyName.equalsIgnoreCase(FunctionStringList[i]))
{
Key = KeyBindingList[a].KeyName
KeyVal = KeyBindingList[a].KeyCode
}
}
Keybinds.put(KeyVal, new Details(FunctionStringList[i], KeyVal, Key, false));
System.out.println("Key: " + Key + " Val: " + KeyVal + " Hack: " + FunctionStringList[i]);
}
catch (Exception E) { E.printStackTrace(); }
}
}
public static String FunctionStringList[] =
{
"Forward", "Backwards", "StrafeLeft", "StrafeRight", "Jump", "Sneak"
};
Details Class:
public class Details extends MainControl
{
public Details(String Name, int KeyCode, String KeyName2, boolean Bool)
{
FunctionName = Name;
Code = KeyCode;
KeyName = KeyName2 != null ? KeyName2 : "None";
State = Bool;
}
public boolean Toggle()
{
State = !State;
return State;
}
public void SendChat(String s)
{
Console.AddChat(s);
}
public String FunctionName;
public String KeyName;
public int Code;
public boolean State;
}
Your Details class is-a MainControl; it's a subclass.
When you extend a class, the child class' constructor is calling the parent object's no-arg constructor which is causing an infinite recursion.
Edit to add from the comment below: Your "offending line" is:
Keybinds.put(KeyVal, new Details(FunctionStringList[i], KeyVal, Key, false));
When the Details constructor executes, it then calls MainControl() ... which then calls LoadSession() ... which then creates a new Details ... which then calls MainControl() .. etc, etc. Infinite recursion until you get a Stack Overflow.

Categories