I want to invoke a method from class which is inside an external jar using reflection. But I am still not able to do it. I'm using the following code
public class Test {
public static void main(String[] args) throws Exception {
try {
// File JarFile = new File("C:\\dataRetrieval.jar");
//
// URLClassLoader cl = new URLClassLoader(new
// URL[]{JarFile.toURI().toURL()});
// JarFile.getClass();
DataRetrievalManagerServiceStub stub = new DataRetrievalManagerServiceStub(
"html//...............???wsdl");
Map<String, String> requestMap = new HashMap<String, String>();
requestMap.put("TelephoneNumber", "01028824332");
Object stubInstance = Class.forName("com.test.DataRetrievalManagerServiceStub").newInstance();
Object reqInstance = Class.forName("com.test.impl.GetOllehIdsForUserDocumentImpl").newInstance();
Method[] stubMethods = stubInstance.getClass().getMethods();
Method[] reqMethods = reqInstance.getClass().getMethods();
//Method[] resMethods = resInterface.getClass().getMethods();
for (Method method : reqMethods) {
String methodName = method.getName();
System.out.println(methodName);
}
for (Method method : reqMethods) {
String methodName = method.getName();
if (methodName.startsWith("set")) {
methodName = methodName.replace("set", "");
String value = null;
if (requestMap.containsKey(methodName)) {
value = requestMap.get(methodName);
}
method.invoke(reqInstance, value);
}
}
Object resInterface = Class.forName(
"com.test.GetOllehIdsForUserResponseDocument").getInterfaces();
} catch (AxisFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I get an error message shown below:
log4j:WARN No appenders could be found for logger (org.apache.axis2.description.AxisOperation). log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" java.lang.InstantiationException: com.kt.sdp.impl.GetOllehIdsForUserDocumentImpl
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source) at sdk.kt.com.Test.main(Test.java:78)
Does anyone have any idea?
Related
I am trying to use Javassist for the first time, and I am stuck.
I am creating class at runtime and if there is any new field comes I want to change the class at runtime.
my code is below
public static Class generate(String className, Map<String, Class<?>> properties) throws NotFoundException,
CannotCompileException, ClassNotFoundException {
ClassPool pool = ClassPool.getDefault();
CtClass cc=null;
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if (contextClassLoader != null)
{
pool.insertClassPath(new LoaderClassPath(contextClassLoader));
}
try{
cc = pool.makeClass(className);
cc.defrost();
cc.addInterface(resolveCtClass(Serializable.class));
for (Entry<String, Class<?>> entry : properties.entrySet()) {
//add feilds
// add getter
// add setter
}
cc.addConstructor(generateConstructor(cc,properties,className));
CtConstructor defaultCons=new CtConstructor(NO_ARGS, cc);
defaultCons.setBody(";");
cc.addConstructor(defaultCons);
return cc.toClass();
}catch(Exception e){
cc = pool.get(className);
for (Entry<String, Class<?>> entry : properties.entrySet()) {
try{
//add feilds
// add getter
// add setter
}catch(Exception e1){
System.out.println("Fields or method already present");
}
}
try{
cc.addConstructor(generateConstructor(cc,properties,className));
}catch(Exception e1){
System.out.println("Constructor already present");
}
try {
byte[] classFile = cc.toBytecode();
HotSwapper hs = new HotSwapper(9080);
hs.reload(className, classFile);
} catch (IOException | IllegalConnectorArgumentsException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return Class.forName(className);
}
this code is not working.
I am getting below error
java.lang.ClassNotFoundException: com.sun.jdi.connect.IllegalConnectorArgumentsException
You must add following dependency to your project
<!-- https://mvnrepository.com/artifact/com.sun/tools -->
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.7.0.13</version>
<!--<scope>system</scope>-->
</dependency>
I have a JavaFX app where there is an editor. In the editor, the user will be able to write java code and I have a button to compile this code and run the main method. For example the editor will contain this code:
public class Test {
public static void main(String[] args) {
System.out.println("hello");
}
}
The button on click, will run this code:
runButton.setOnAction(e -> {
compiler.set(editor.getText());
try {
compiler.createFile();
} catch (IOException e1) {
e1.printStackTrace();
}
compiler.compile();
compiler.run();
});
In the compiler class, there is the following implementation:
public class CodeCompiler {
public String className;
public String code;
public void set(String code) {
try {
this.className = code.substring(code.indexOf(" class ") + 6, code.indexOf(" {")).trim();
} catch(StringIndexOutOfBoundsException e) {
}
this.code = code;
}
public void createFile() throws IOException {
PrintWriter pw = new PrintWriter("speech2code/src/main/java/" + className + ".java");
pw.close();
FileWriter writer = new FileWriter("speech2code/src/main/java/" + className + ".java", true);
writer.write(code);
writer.flush();
writer.close();
}
public void compile() {
File file = new File("speech2code/src/main/java/" + className + ".java");
File classFile = new File("speech2code/src/main/java/" + className + ".class");
classFile.delete(); // delete class file f it exists
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, file.getPath());
}
public void run() {
Class<?> cls = null;
try {
cls = Class.forName(className);
System.out.println(cls == null);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method meth = null;
try {
meth = cls.getMethod("main", String[].class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
String[] params = null;
try {
meth.invoke(null, (Object) params);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
Now the code above successfully creates the java file, class file and runs correctly the first time. Now when I change the editor code to print something else, it outputs the result of the first time the code was running. So, in this case, it will still print 'hello' instead of whatever it's current value.
Any problem what might be wrong?
Thanks!
You need to create a new classloader for the new class. The class does not get reloaded just because you compiled it.
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] {classFile});
Then you can ask this loader for the class:
Class<?> cls = Class.forName(className, true, classLoader);
I'm trying to load the radio version of the Android device using reflection. I need to do this because my SDK supports back to API 7, but Build.RADIO was added in API 8, and Build.getRadioVersion() was added in API 14.
// This line executes fine, but is deprecated in API 14
String radioVersion = Build.RADIO;
// This line executes fine, but is deprecated in API 14
String radioVersion = (String) Build.class.getField("RADIO").get(null);
// This line executes fine.
String radioVersion = Build.getRadioVersion();
// This line throws a MethodNotFoundException.
Method method = Build.class.getMethod("getRadioVersion", String.class);
// The rest of the attempt to call getRadioVersion().
String radioVersion = method.invoke(null).toString();
I'm probably doing something wrong here. Any ideas?
Try this:
try {
Method getRadioVersion = Build.class.getMethod("getRadioVersion");
if (getRadioVersion != null) {
try {
String version = (String) getRadioVersion.invoke(Build.class);
// Add your implementation here
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
Log.wtf(TAG, "getMethod returned null");
}
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
What Build.getRadioVersion() actually does is return the value of gsm.version.baseband system property. Check Build and TelephonyProperties sources:
static final String PROPERTY_BASEBAND_VERSION = "gsm.version.baseband";
public static String getRadioVersion() {
return SystemProperties.get(TelephonyProperties.PROPERTY_BASEBAND_VERSION, null);
}
According to AndroidXref this property is available even in API 4. Thus you may get it on any version of Android through SystemProperties using the reflection:
public static String getRadioVersion() {
return getSystemProperty("gsm.version.baseband");
}
// reflection helper methods
static String getSystemProperty(String propName) {
Class<?> clsSystemProperties = tryClassForName("android.os.SystemProperties");
Method mtdGet = tryGetMethod(clsSystemProperties, "get", String.class);
return tryInvoke(mtdGet, null, propName);
}
static Class<?> tryClassForName(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
return null;
}
}
static Method tryGetMethod(Class<?> cls, String name, Class<?>... parameterTypes) {
try {
return cls.getDeclaredMethod(name, parameterTypes);
} catch (Exception e) {
return null;
}
}
static <T> T tryInvoke(Method m, Object object, Object... args) {
try {
return (T) m.invoke(object, args);
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getTargetException());
} catch (Exception e) {
return null;
}
}
I am trying to load a class from a directory which I specify. I have done some research and made this:
ArrayList<Object> plugins = new ArrayList<Object>();
ClassLoader loader = Reflection.class.getClassLoader();
public Reflection()
{
load();
}
public void load()
{
File f = new File(Full directary);
ClassLoader loader = null;
try
{
loader = new URLClassLoader(new URL[]
{ f.toURI().toURL() }, getClass().getClassLoader());
}
catch (MalformedURLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
for (File classFile : f.listFiles(new FilenameFilter()
{
public boolean accept(File dir, String name)
{
return name.endsWith(".class");
}
}))
// Start for loop.
{
try
{
String filename = classFile.getName();
System.out.println(filename);
Class<?> cls = loader.loadClass(filename.replace(".class", ""));
System.out.println(cls.getSuperclass().getName());
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
I am getting aNoClassDefFoundError error:
Exception in thread "main" java.lang.NoClassDefFoundError: mTest123g (wrong name: net/xcaliber/reflection/Test)
It finds the class fine, but then can't load it. I have made a basic interface:
String getName();
That's all that's in it; here is the class I am loading:
public Test()
{
// TODO Auto-generated constructor stub
}
#Override
public String getName()
{
return "Test";
}
This does implement the interface.Let me know the problem with it .
Obviously you have a mess up with class and file names.
Exception in thread "main" java.lang.NoClassDefFoundError: mTest123g (wrong name: net/xcaliber/reflection/Test)
So, you loading it as java mTest123g. Class loader expects a mTest123g.class not a Test class inside some net.xcaliber.reflection package.
My QA team is doing business lifecycle testing (i.e. aging, expiring, due, past due etc) , that requires application clock to be moved. I can change all my code to refer to a adjusted clock (that I control). The issues is the (web) applications uses several 3rd party tools (e.g. Spring Batch, Activiti etc.) that relies on current time and uses System.currentTimeMillis() directly or indirectly through Date or Calendar.
Option 1 - Spring AOP. When I tried this option it seemed it only instruments Spring loaded beans only (?) Since System class was loaded outside of Spring framework it could not instrument it.
Option 2 - JMockit. Somewhat unconventional to have JMockit jar past JUnit.
Option 3 - Use Java 6 instrumentation (common piece between Option 1 and Option 2). Back to the basics... (find the relevant code below).
However, the assert in the test code always fails.
I have hit a roadblock with all the three options. Can't believe no one have done this before, but can't find an reasonable solution either.
Thanks in advance.
public class InstrumentationAgent {
private static Instrumentation instrumentation = null;
/**
* JVM hook to dynamically load InstrumentationAgent at runtime.
*
* The agent class may have an agentmain method for use when the agent is
* started after VM startup.
*
* #param agentArgument
* #param instrumentation
*/
public static void agentmain(String agentArgument, Instrumentation instrumentation) {
InstrumentationAgent.instrumentation = instrumentation;
}
/**
* Programmatic hook to dynamically load modified byte codes. This method initializes/load the agent if necessary.
*
* #param definitions
* #throws Exception
*/
public static void redefineClasses(ClassDefinition... definitions) throws Exception {
if (InstrumentationAgent.instrumentation == null) {
loadAgent();
}
InstrumentationAgent.instrumentation.redefineClasses(definitions);
}
private synchronized static void loadAgent() throws Exception {
if (InstrumentationAgent.instrumentation != null) {
return;
}
// Build the agent.jar file
final File jarFile = File.createTempFile("agent", ".jar");
jarFile.deleteOnExit();
final Manifest manifest = new Manifest();
final Attributes mainAttributes = manifest.getMainAttributes();
mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
mainAttributes.put(new Attributes.Name("Agent-Class"), InstrumentationAgent.class.getName());
mainAttributes.put(new Attributes.Name("Can-Retransform-Classes"), "true");
mainAttributes.put(new Attributes.Name("Can-Redefine-Classes"), "true");
final JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFile), manifest);
final JarEntry agent = new JarEntry(InstrumentationAgent.class.getName().replace('.', '/') + ".class");
jos.putNextEntry(agent);
final ClassPool pool = ClassPool.getDefault();
final CtClass ctClass = pool.get(InstrumentationAgent.class.getName());
jos.write(ctClass.toBytecode());
jos.closeEntry();
jos.close();
// Attach to VM and load the agent
VirtualMachine vm = VirtualMachine.attach(getPidFromRuntimeMBean());
vm.loadAgent(jarFile.getAbsolutePath());
vm.detach();
}
private static String getPidFromRuntimeMBean() throws Exception {
RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
Field jvmField = mxbean.getClass().getDeclaredField("jvm");
jvmField.setAccessible(true);
VMManagement management = (VMManagement) jvmField.get(mxbean);
Method method = management.getClass().getDeclaredMethod("getProcessId");
method.setAccessible(true);
Integer processId = (Integer) method.invoke(management);
return processId.toString();
}
}
public class SystemTimeInstrumentation {
private static long timeAdjustment = 200000L;
private static byte[] originalClassByteArray;
public static void startAdjustedClock() {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = null;
byte[] instrumentedClassByteArray = null;
try {
originalClassByteArray = pool.get(System.class.getName()).toBytecode();
ctClass = pool.makeClass(new java.io.ByteArrayInputStream(originalClassByteArray), false);
CtMethod ctMethod = ctClass.getDeclaredMethod("currentTimeMillis");
ctMethod.setBody("return 0L;");
instrumentedClassByteArray = ctClass.toBytecode();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CannotCompileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (ctClass != null) {
ctClass.detach();
}
}
try {
InstrumentationAgent.redefineClasses(new ClassDefinition[] { new ClassDefinition(System.class,
instrumentedClassByteArray) });
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void stopAdjustedClock() {
if (originalClassByteArray == null) {
throw new RuntimeException("The stopAdjustedClock() called before startAdjustedClock()");
} else {
try {
InstrumentationAgent.redefineClasses(new ClassDefinition[] { new ClassDefinition(System.class,
originalClassByteArray) });
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
originalClassByteArray = null;
}
}
public class SystemTimeInstrumentationTest extends TestCase {
#Test
public void testModifiedClock() throws Exception {
long unmodifiedTime = System.currentTimeMillis();
SystemTimeInstrumentation.startAdjustedClock();
long modifiedTime = System.currentTimeMillis();
SystemTimeInstrumentation.stopAdjustedClock();
assertTrue("The difference should me more than 200000", (modifiedTime-unmodifiedTime)>200000L);
}
}