The Java reflection code in my Android application invokes a public static method in a package B, from a package A.
Recently, after some Gradle upgrades, I am unable to invoke the same method. My implementation fails with a NoSuchMethodFound exception. How can I get the implementation to be able to find this method?
I've tried printing all the available methods from the class. The result is all public non-static methods. No static methods are available to be invoked. The method I want to invoke is a static "getInstance" method which initializes the class and returns a singleton instance.
Calling Code:
implementationClass = Class.forName(CLIENT_CLASS_NAME, false, ClientProvider.class.getClassLoader());
final Method method = implementationClass.getMethod("getInstance", (Class[]) null);
result = method.invoke(null, (Object[]) null);
Called Code:
/**
* Public static method to be reflected.
*/
public static ClientImpl getInstance() {
return ClientImplHolder.INSTANCE;
}
/**
* Private class used to hold the lazily initialized singleton instance.
*/
private static class ClientImplHolder {
private static final ClientImpl INSTANCE = new ClientImpl();
}
When attempting to 'getMethod', I receive a NoSuchMethodException.
Not sure what I am doing wrong here, appreciate any help. Thanks!
Turns out Proguard was removing the method from the build since it was not being used elsewhere. Added an exception for the class and the issue went away.
If i understood correctly, you used reflection API wrong
just try this.
public class Test {
public static void main(String[] args) {
try {
ClientImpl client = (ClientImpl) Class.forName(ClientImpl.class.getCanonicalName())
.getMethod("getInstance")
.invoke(null);
System.out.println(client.toString() + " with some -> " + client.getSome());
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Public static method to be reflected.
*/
class ClientImpl {
private final int some;
public int getSome() {
return some;
}
private ClientImpl(int some) {
this.some = some;
}
public static ClientImpl getInstance() {
return ClientImplHolder.INSTANCE;
}
/**
* Private class used to hold the lazily initialized singleton instance.
*/
private static class ClientImplHolder {
private static final ClientImpl INSTANCE = new ClientImpl(123);
}
}
and it will put correctly result
ClientImpl#<hashcode> with some -> 123
When you use static methods in reflection API, you don't need to call it ClassLoader explicitly, you have to put it's canonicalName in argument, then you can call it's methods.
Try to replace it,maybe it's a parameter problem.
final Method method = implementationClass.getMethod("getInstance");
result = method.invoke(null);
Starting in Android 9 (API level 28), the platform restricts which non-SDK interfaces your app can use. These restrictions apply whenever an app references a non-SDK interface or attempts to obtain its handle using reflection.
public class test extends AbstractTableModel {
public static void main(String[] args) {
}
public String valuePass(int rowIn)
{
String value = "open";
return value;
}
test(mdpTEST parentPanel) {
m_parentPanel = parentPanel;
}
...
}
import demo.test;
public class order{
public void new()
{
test blah = new test(null);
String text = blah.valuePass(0);
}
}
In the code above, "blah" should be referencing the class "test" which is public, however I'm told to change the visibility of "test()" to public as I get an error in the line: "test blah = new test(null);". I'm confused at why "public class test" is not being referenced by "blah" and how the second instance of "test()" is being utilized here. I appreciate any help in understanding this problem!
Two issues with the code that you have shown
1) You cannot have new() as method name as new it is a keyword
2) Line test blah = new test(null); is calling a constructor of a test class which is in a different package. So default visibility is applied to test(...) constructor in test class. And as per java visibility rule, you have to make it public to access it in a different package
Do these changes and your code should work fine
I make singleton class and use this class object in different class this code work fine in eclipse
but when i make runnable jar than it take empty hashmap list i don't know why my code...
My singleton class
public class PointCalculate {
public HashMap<String, Float> calPoint;
private static PointCalculate instance;
private PointCalculate(){
calPoint = new HashMap<String, Float>();
}
public static PointCalculate getInstance(){
if(instance==null){
instance = new PointCalculate();
}
return instance;
}
public void calculatePoint(String uid ,float point){
Float ps = instance.calPoint.get(uid);
if(ps==null) {
ps = point;
instance.calPoint.put(uid, ps);
}
else {
ps = point+ps.floatValue();
instance.calPoint.put(uid, ps);
}
}
}
and i am passing value from this class below....
public class Exp {
public void setpoint(){
PointCalculate obj = PointCalculate.getInstance();
obj.calculatePoint(rowkey, point);//rowkey and point come from file.....
}
}
now i am passing hashmap....
public static void main(String args[]) throws Exception {
PointCalculate obj = PointCalculate.getInstance();
SqlInsertPoint.givePoint(obj.calPoint);
}
but in SqlInsertPoint.givePoint() hashmap list will be empty i don't know why if any body know than help me
Thanks in advance
What is wrong with this code? In main you obtain an instance of PointCalculate, do not put any points into it, and pass it over to givePoint method. Since you didn't populate the HashMap, it should be empty.
On a separate note, static Singletons are difficult to get right, and in general should be avoided (couple good reasons). In your concrete case not only PointCalculate class is not thread-safe, but it also exposes calPoint to the whole world. So, anybody can run the following code and essentially override your instance.
PointCalculate.getInstance().calPoint = new HashMap();
I have code like below sample. in that I am telling the class_name to get package name. instead of this method, i need another logic to get the package name withoud telling the class_name directly.
package smk.jsf.bean;
public class test {
public static void main(String[] args) {
System.out.println(test.class.getPackage().getName());
//Is there any option like "this.class.getPackage().getName();" bz. i don't want use class_name direclty
}
}
Output : smk.jsf.bean
Thanks to everyone.
Finally I got solution below
package smk.jsf.bean;
public class test {
public static void main(String[] args) {
String className = new Object(){}.getClass().getPackage().getName();
System.out.println(className);
}
Not sure it will suit you but try sun.reflect.Reflection.getCallerClass(). This class is present in JDK.
It will return a Class instance of method caller. Then just getPackage(). It is really dangerous stuff but it lets you not to use the class name directly.
Example usage - create a method String getPackageName() which will get caller class and return package name and call it from main.
Or you can throw any throwable, catch it and parse that throwable's stack trace to get the target package name (really sick way).
I have two approaches.
You can add a field public static final PACKAGE_INFO = "%package%"; to each file. Then traverse your source directory, read the line with the package package someName and replace the %package%
Use a dynamic approach at runtime. I wrote a little example program.
public class PackageExample {
public static void main(String[] args) throws ClassNotFoundException {
Example e = new Example();
System.out.println(e.getPackage());
}
}
interface MetaInformation {
public String getPackage() throws ClassNotFoundException;
}
class InformationGatherer implements MetaInformation {
public String getPackage() throws ClassNotFoundException {
StackTraceElement[] ste = new Exception().getStackTrace();
if (ste.length < 2)
throw new IllegalStateException("StackTrace to small to determine package!");
String clazz = ste[1].getClassName();
Class<?> c = Class.forName(clazz);
String package_ = "";
Package p = c.getPackage();
if (p != null)
package_ = c.getPackage().getName();
return package_;
}
}
class Example implements MetaInformation {
private InformationGatherer ig = new InformationGatherer();
public String getPackage() throws ClassNotFoundException {
return ig.getPackage();
}
}
Not sure if this helps but you can use reflection
http://docs.oracle.com/javase/tutorial/reflect/
Similar question :
See Can you find all classes in a package using reflection?
If it's a static method.No.
You cannot use this in a static context,since main is static method.
If it is not a static method,
String name = this.getClass().getPackage().getName();
I would like some help on this matter,
Example:
public class A {
private void foo() {
//Who invoked me?
}
}
public class B extends A {}
public class C extends A {}
public class D {
C.foo();
}
This is basically the scenario. My question is how can method foo() know who is calling it?
EDIT: Basically I am trying to do a database Layer, and in class A I will create a method that will generate SQL statements. Such statements are dynamically generated by getting the values of all the public properties of the calling class.
Easiest way is the following:
String className = new Exception().getStackTrace()[1].getClassName();
But in real there should be no need for this, unless for some logging purposes, because this is a fairly expensive task. What is it, the problem for which you think that this is the solution? We may come up with -much- better suggestions.
Edit: you commented as follows:
basically i'am trying to do a database Layer, and in Class A i will create a method that will generate sql statements, such statements are dynamically generated by getting the values of all the public properties of the calling class.
I then highly recommend to look for an existing ORM library, such as Hibernate, iBatis or any JPA implementation to your taste.
Java 9: 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. First off, you should obtain an instance of StackWalker:
import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;
// other imports
StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
After that you can call the getCallerClass() method:
Class<?> callerClass = walker.getCallerClass();
Regardless of how you configured the StackWalker instance, the getCallerClass method will ignore the reflection frames, hidden frames and those are related to MethodHandles. Also, this method shouldn't be called on the first stack frame.
Perhaps for your use case it would make sense to pass the class of the caller into the method, like:
public class A { public void foo(Class<?> c) { ... } }
And call it something like this:
public class B { new A().foo(getClass() /* or: B.class */ ); }
foo() is private, so the caller will always be in class A.
if you using slf4j as your application logging system.
you can using:
Class<?> source = org.slf4j.helpers.Util.getCallingClass();
I think it's faster than new Exception().getStackTrace(), since getStackTrace() alaways doing clone stacktrace.
I would use StackWalker
private static Class<?> getCallingClass(int skip) {
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
Optional<? extends Class<?>> caller = walker.walk(frames ->
frames.skip(skip).findFirst().map(StackWalker.StackFrame::getDeclaringClass)
);
return caller.get();
}
If you need the class of the calling method use skip=1.
From a stack trace: http://www.javaworld.com/javaworld/javatips/jw-javatip124.html
A hacky solution is sun.reflect.Reflection.getCallerClass.
public void foo() {
Class<?> caller = sun.reflect.Reflection.getCallerClass();
// ...
}
It is hacky because you have to ensure that the class that calls Reflection.getCallerClass() is loaded on the bootstrap ClassLoader for the annotation #CallerSensitive (which getCallerClass is tagged with) to work. As such, it probably isn't the best solution for a project unless your project happens to use a Java Agent to add your classes to the bootstrap ClassLoader search.
With the following code, you obtain the first class which generated the stack of calls:
public String getInvonkingClassName(boolean fullClassNameNeeded){
StackTraceElement[] stack = new Exception().getStackTrace();
String className = stack[stack.length-1].getClassName();
if(!fullClassNameNeeded){
int idx = className.lastIndexOf('.');
className = className.substring(idx+1);
}
return className;
}
Boolean argument is used to get the full name including package name, or just class name.
StackFrame
The state of one method invocation on a thread's call stack. As a thread executes, stack frames are pushed and popped from its call stack as methods are invoked and then return. A StackFrame mirrors one such frame from a target VM at some point in its thread's execution.
JVM Stack: From Frame 1 get Frame 2 details
| |
| |
| Class2.function1() [FRAME 1] |
| executing the instructions |
|-------------------------------------------|
|Class1.method1() [FRAME 2] |
| called for execution Class2.function1() |
|-------------------------------------------|
Throwable::getStackTrace and Thread::getStackTrace return an array of StackTraceElement objects, which contain the class name and method name of each stack-trace element.
Throwable::getStackTrace contains the Stack with frames as Frame1(Top Frame) Current method, Frame2 calls Frame1 method for execution.
StackTraceElement[] stackTraceElements = (new Throwable()).getStackTrace();
// Frame1:Log4J.log(), Frame2:CallerClass
Thread::getStackTrace contains the stack with Frames:
Frame1:Thread.getStackTrace(), Frame2:Current Method, Frame3:Caller Method
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); //
sun.misc.SharedSecrets.getJavaLangAccess()
sun.misc.JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
StackTraceElement frame = javaLangAccess.getStackTraceElement((new Throwable()), callerFrame-1 ); // Frame0:Log4J.log(), Frame1:CallerClass
System.out.format("SUN - Clazz:%s, Method:%s, Line:%d\n", frame.getClassName(), frame.getMethodName(), frame.getLineNumber());
Throwable throwable = new Throwable();
int depth = javaLangAccess.getStackTraceDepth(new Throwable());
System.out.println("\tsun.misc.SharedSecrets : "+javaLangAccess.getClass() + " - StackTraceDepth : "+ depth);
for (int i = 0; i < depth; i++) {
StackTraceElement frame = javaLangAccess.getStackTraceElement(throwable, i);
System.out.format("Clazz:%s, Method:%s, Line:%d\n", frame.getClassName(), frame.getMethodName(), frame.getLineNumber());
}
JDK-internal sun.reflect.Reflection::getCallerClass method. It is deprecated, removed in Java9 JDK-8021946
Any way by using Reflection API we can't find the Line Number of Function which it get called.
System.out.println("Reflection - Called from Clazz : "+ Reflection.getCallerClass( callerFrame )); // Frame1:Log4J.log(), Frame2:CallerClass
Example:
static boolean log = false;
public static void log(String msg) {
int callerFrame = 2; // Frames [Log4J.log(), CallerClass.methodCall()]
StackTraceElement callerFrameStack = null;
StackTraceElement[] stackTraceElements = (new Throwable()).getStackTrace(); // Frame1:Log4J.log(), Frame2:CallerClass
//StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();// Frame1:Thread.getStackTrace(), Frame2:Log4J.log(), Frame3:CallerClass
int callerMethodFrameDepth = callerFrame; // Caller Class Frame = Throwable:2(callerFrame), Thread.currentThread:2(callerFrame+1)
for (int i = 0; i < stackTraceElements.length; i++) {
StackTraceElement threadFrame = stackTraceElements[i];
if (i+1 == callerMethodFrameDepth) {
callerFrameStack = threadFrame;
System.out.format("Called form Clazz:%s, Method:%s, Line:%d\n", threadFrame.getClassName(), threadFrame.getMethodName(), threadFrame.getLineNumber());
}
}
System.out.println(msg);
if (!log){
Logger logger = Logger.getLogger(callerFrameStack.getClass());
logger.info(msg);
}
}
public static void main(String[] args) {
Log4J.log("Log4J, main");
Clazz1.mc1();
Clazz21.mc12();
Clazz21.mc11();
Clazz21.mc21();
}
}
class Clazz1 {
public static void mc1() {
Log4J.log("Clazz1 - mc1");
}
}
class Clazz11 {
public static void mc11() {
Log4J.log("Clazz11 - mc11");
}
public static void mc12() {
Log4J.log("Clazz11 - mc12");
Clazz1.mc1();
}
}
class Clazz21 extends Clazz11 {
public static void mc21() {
Log4J.log("Clazz21 - mc21");
}
}
For Java 9 use Stack Walking API
I'm just answering this because for some reason the above answers started referring to exception handling - the original question had nothing to do with exceptions.
So, instead of trying to determine the caller of the method in question, and specifically to give more information dealing with the creation of a base class that generates SQL statements for its derived classes, here is an OO solution...
Make the base class abstract and include abstract methods that return the data it needs to build a sql statement.
This would include methods like...
getColumnList()
getFromTable()
getJoinedTables()
getFilterColumns()
The base class then does not care who is calling it because it is going to call up to the derived class for all the details it needs to create the SQL statement.
The base class knows the derived classes are going to provide the implementation of these methods because they are abstract.
Another way to implement this would be to have a SQLGenerator class that receives an interface with the methods described above and operates on the instances passed to it via those methods. For this, you would want to have the abstract methods described above moved into the interface, which all of your SQL related classes would implement.
List item
I tried this and it works well. It is because each Java Object has access to getClass() method which returns the class caller and the method name.
public Logger logger() {
return Logger.getLogger(getClass().toString());
}
example usage:
public DBTable(String tableName) {
this.tableName = tableName;
loadTableField();
this.logger().info("done");
}
sample output log using java.util.logging.Logger
Feb 01, 2017 11:14:50 PM rmg.data.model.DBTable (init) INFO: done
Maybe an answer is
public class CallerMain {
public void foo(){
System.out.println("CallerMain - foo");
System.out.println(this.getClass()); //output- callerMain
}
public static void main(String[] args) {
A a = new A();
CallerMain cm = new CallerMain();
cm.foo();
}
}
class A{
public void foo(){
System.out.println("A - foo");
System.out.println(this.getClass());//output- A
}
}