में जावा विधि पैरामीटर मान मैं जावा प्रोग्राम के विधि के मानकों के मान प्राप्त करने का प्रयास कर रहा हूं। मैं बाइटकोड को मापने और इन मानों को प्राप्त करने के लिए एएसएम का उपयोग कर रहा हूं। हालांकि, मैं कुछ परेशानियों में भाग रहा हूं।एएसएम
यहां विज़िट कोड() विधि कोड का उपयोग करने के लिए उपयोग की जाती है। क्या यह कर रहा है:
- एकत्र मापदंडों स्टोर करने के लिए एक खाली सरणी बनाएँ।
- प्रत्येक पैरामीटर के लिए, सरणी में अपना मान लोड करें।
- इस सरणी को मेरे एजेंट की OnMethodEntry विधि (जहां मूल्यों का उपयोग किया जाएगा) को भेजें।
।
@Override
public void visitCode() {
int paramLength = paramTypes.length;
// Create array with length equal to number of parameters
mv.visitIntInsn(Opcodes.BIPUSH, paramLength);
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
mv.visitVarInsn(Opcodes.ASTORE, paramLength);
// Fill the created array with method parameters
int i = 0;
for (Type tp : paramTypes) {
mv.visitVarInsn(Opcodes.ALOAD, paramLength);
mv.visitIntInsn(Opcodes.BIPUSH, i);
if (tp.equals(Type.BOOLEAN_TYPE) || tp.equals(Type.BYTE_TYPE) || tp.equals(Type.CHAR_TYPE) || tp.equals(Type.SHORT_TYPE) || tp.equals(Type.INT_TYPE))
mv.visitVarInsn(Opcodes.ILOAD, i);
else if (tp.equals(Type.LONG_TYPE)) {
mv.visitVarInsn(Opcodes.LLOAD, i);
i++;
}
else if (tp.equals(Type.FLOAT_TYPE))
mv.visitVarInsn(Opcodes.FLOAD, i);
else if (tp.equals(Type.DOUBLE_TYPE)) {
mv.visitVarInsn(Opcodes.DLOAD, i);
i++;
}
else
mv.visitVarInsn(Opcodes.ALOAD, i);
mv.visitInsn(Opcodes.AASTORE);
i++;
}
// Load id, class name and method name
this.visitLdcInsn(new Integer(this.methodID));
this.visitLdcInsn(this.className);
this.visitLdcInsn(this.methodName);
// Load the array of parameters that we created
this.visitVarInsn(Opcodes.ALOAD, paramLength);
mv.visitMethodInsn(Opcodes.INVOKESTATIC,
"jalen/MethodStats",
"onMethodEntry",
"(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V");
super.visitCode();
}
हालांकि, यह तब काम नहीं कर रहा है जब स्पष्ट रूप से विधि में एक से अधिक पैरामीटर हैं।
इस तरहवर्ग फ़ाइल प्राप्त शो बातें:
static void moveDisk(char arg0, char arg1, PrintStream arg2) {
Object[] arrayOfObject = new Object[3]; arrayOfObject[0] = ???; arrayOfObject[1] = ???;
Object localObject;
arrayOfObject[2] = localObject; MethodStats.onMethodEntry(5, "hanoi/TowersOfHanoi", "moveDisk", arrayOfObject);
कहाँ 2 स्थानीय वस्तुओं के बजाय मानकों को लोड करने की बनाई गई हैं।
बाईटकोड कुछ भी अजीब नहीं दिखाता है:
static void moveDisk(char, char, java.io.PrintStream);
Code:
0: bipush 3
2: anewarray #4 // class java/lang/Object
5: astore_3
6: aload_3
7: bipush 0
9: iload_0
10: aastore
11: aload_3
12: bipush 1
14: iload_1
15: aastore
16: aload_3
17: bipush 2
19: aload_2
20: aastore
21: ldc #118 // int 5
23: ldc #12 // String hanoi/TowersOfHanoi
25: ldc #119 // String moveDisk
27: aload_3
28: invokestatic #19 // Method jalen/MethodStats.onMethodEntry:(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
और अंत में, त्रुटि (जब -noverify का उपयोग कर) से पता चला:
param: [Ljava.lang.String;@420e54f3
Exception in thread "Jalen Agent" java.lang.NullPointerException
at hanoi.TowersOfHanoi.solveHanoi(TowersOfHanoi.java)
at hanoi.TowersOfHanoi.main(TowersOfHanoi.java:29)
अन्यथा, यह है:
Exception in thread "Jalen Agent" java.lang.VerifyError: (class: hanoi/TowersOfHanoi, method: moveDisk signature: (CCLjava/io/PrintStream;)V) Expecting to find object/array on stack
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
at java.lang.Class.getMethod0(Class.java:2685)
at java.lang.Class.getMethod(Class.java:1620)
at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:492)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:484)
आम तौर पर, यह काम करना चाहिए क्योंकि मैं केवल स्टैक फ्रेम से जानकारी लोड कर रहा हूं। मैंने स्थैतिक & गैर स्थैतिक तरीकों की जांच करने की कोशिश की (जैसा कि यहां समझाया गया ढेर है: http://www.artima.com/insidejvm/ed2/jvm8.html), लेकिन अभी भी कोई सफलता नहीं है।
यह क्यों हो रहा है, या संभवतः समाधान का कोई विचार है?
धन्यवाद :)
संपादित करें:
अब यह काम कर रहा है जब तक (नीचे int3 :) द्वारा सुझाव के लिए धन्यवाद) आदिम प्रकार मुक्केबाजी।
@Override
public void visitCode() {
int paramLength = paramTypes.length;
// Create array with length equal to number of parameters
mv.visitIntInsn(Opcodes.BIPUSH, paramLength);
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
mv.visitVarInsn(Opcodes.ASTORE, paramLength);
// Fill the created array with method parameters
int i = 0;
for (Type tp : paramTypes) {
mv.visitVarInsn(Opcodes.ALOAD, paramLength);
mv.visitIntInsn(Opcodes.BIPUSH, i);
if (tp.equals(Type.BOOLEAN_TYPE)) {
mv.visitVarInsn(Opcodes.ILOAD, i);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
}
else if (tp.equals(Type.BYTE_TYPE)) {
mv.visitVarInsn(Opcodes.ILOAD, i);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
}
else if (tp.equals(Type.CHAR_TYPE)) {
mv.visitVarInsn(Opcodes.ILOAD, i);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
}
else if (tp.equals(Type.SHORT_TYPE)) {
mv.visitVarInsn(Opcodes.ILOAD, i);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
}
else if (tp.equals(Type.INT_TYPE)) {
mv.visitVarInsn(Opcodes.ILOAD, i);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
else if (tp.equals(Type.LONG_TYPE)) {
mv.visitVarInsn(Opcodes.LLOAD, i);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
i++;
}
else if (tp.equals(Type.FLOAT_TYPE)) {
mv.visitVarInsn(Opcodes.FLOAD, i);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
}
else if (tp.equals(Type.DOUBLE_TYPE)) {
mv.visitVarInsn(Opcodes.DLOAD, i);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
i++;
}
else
mv.visitVarInsn(Opcodes.ALOAD, i);
mv.visitInsn(Opcodes.AASTORE);
i++;
}
// Load id, class name and method name
this.visitLdcInsn(new Integer(this.methodID));
this.visitLdcInsn(this.className);
this.visitLdcInsn(this.methodName);
// Load the array of parameters that we created
this.visitVarInsn(Opcodes.ALOAD, paramLength);
mv.visitMethodInsn(Opcodes.INVOKESTATIC,
"jalen/MethodStats",
"onMethodEntry",
"(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V");
super.visitCode();
}
मैं तर्क को वापस स्टैक पर कैसे वापस कर सकता हूं ताकि फ़ंक्शन उनका उपयोग जारी रख सके? – Shay