I have seen that when errors occur deep in different frameworks (e.g frameworks implementing the EJB specification or some JPA providers) the stacktrace contain classes like com.sun.proxy.$Proxy. I know what a Proxy is, but I am looking for a more technical and more java specific answer.
Nothing special. Just as same as common Java Class Instance.
But those class are Synthetic proxy classes created by java.lang.reflect.Proxy#newProxyInstance
Introduced in 1.3
http://docs.oracle.com/javase/1.3/docs/relnotes/features.html#reflection
It is a part of Java. so each JVM should support it.
In short : they are created using JVM ASM tech ( defining javabyte code at runtime )
something using same tech:
java.lang.reflect.Proxy#newProxyInstance getProxyClass0 to obtain a `Class   `
ProxyGenerator.generateProxyClass which return a byte[]define class to load the generated $Proxy Class (the classname you have seen)each method is build with same bytecode like
invocation handler's invoke() invocation handler's invoke() the class(bytecode) represent in form of byte[]
How to draw a class
Thinking your java codes are compiled into bytecodes, just do this at runtime
core method in sun/misc/ProxyGenerator.java
generateClassFile
/**  * Generate a class file for the proxy class.  This method drives the  * class file generation process.  */ private byte[] generateClassFile() {      /* ============================================================      * Step 1: Assemble ProxyMethod objects for all methods to      * generate proxy dispatching code for.      */      /*      * Record that proxy methods are needed for the hashCode, equals,      * and toString methods of java.lang.Object.  This is done before      * the methods from the proxy interfaces so that the methods from      * java.lang.Object take precedence over duplicate methods in the      * proxy interfaces.      */     addProxyMethod(hashCodeMethod, Object.class);     addProxyMethod(equalsMethod, Object.class);     addProxyMethod(toStringMethod, Object.class);      /*      * Now record all of the methods from the proxy interfaces, giving      * earlier interfaces precedence over later ones with duplicate      * methods.      */     for (int i = 0; i < interfaces.length; i++) {         Method[] methods = interfaces[i].getMethods();         for (int j = 0; j < methods.length; j++) {             addProxyMethod(methods[j], interfaces[i]);         }     }      /*      * For each set of proxy methods with the same signature,      * verify that the methods' return types are compatible.      */     for (List<ProxyMethod> sigmethods : proxyMethods.values()) {         checkReturnTypes(sigmethods);     }      /* ============================================================      * Step 2: Assemble FieldInfo and MethodInfo structs for all of      * fields and methods in the class we are generating.      */     try {         methods.add(generateConstructor());          for (List<ProxyMethod> sigmethods : proxyMethods.values()) {             for (ProxyMethod pm : sigmethods) {                  // add static field for method's Method object                 fields.add(new FieldInfo(pm.methodFieldName,                     "Ljava/lang/reflect/Method;",                      ACC_PRIVATE | ACC_STATIC));                  // generate code for proxy method and add it                 methods.add(pm.generateMethod());             }         }          methods.add(generateStaticInitializer());      } catch (IOException e) {         throw new InternalError("unexpected I/O Exception");     }      if (methods.size() > 65535) {         throw new IllegalArgumentException("method limit exceeded");     }     if (fields.size() > 65535) {         throw new IllegalArgumentException("field limit exceeded");     }      /* ============================================================      * Step 3: Write the final class file.      */      /*      * Make sure that constant pool indexes are reserved for the      * following items before starting to write the final class file.      */     cp.getClass(dotToSlash(className));     cp.getClass(superclassName);     for (int i = 0; i < interfaces.length; i++) {         cp.getClass(dotToSlash(interfaces[i].getName()));     }      /*      * Disallow new constant pool additions beyond this point, since      * we are about to write the final constant pool table.      */     cp.setReadOnly();      ByteArrayOutputStream bout = new ByteArrayOutputStream();     DataOutputStream dout = new DataOutputStream(bout);      try {         /*          * Write all the items of the "ClassFile" structure.          * See JVMS section 4.1.          */                                     // u4 magic;         dout.writeInt(0xCAFEBABE);                                     // u2 minor_version;         dout.writeShort(CLASSFILE_MINOR_VERSION);                                     // u2 major_version;         dout.writeShort(CLASSFILE_MAJOR_VERSION);          cp.write(dout);             // (write constant pool)                                      // u2 access_flags;         dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);                                     // u2 this_class;         dout.writeShort(cp.getClass(dotToSlash(className)));                                     // u2 super_class;         dout.writeShort(cp.getClass(superclassName));                                      // u2 interfaces_count;         dout.writeShort(interfaces.length);                                     // u2 interfaces[interfaces_count];         for (int i = 0; i < interfaces.length; i++) {             dout.writeShort(cp.getClass(                 dotToSlash(interfaces[i].getName())));         }                                      // u2 fields_count;         dout.writeShort(fields.size());                                     // field_info fields[fields_count];         for (FieldInfo f : fields) {             f.write(dout);         }                                      // u2 methods_count;         dout.writeShort(methods.size());                                     // method_info methods[methods_count];         for (MethodInfo m : methods) {             m.write(dout);         }                                       // u2 attributes_count;         dout.writeShort(0); // (no ClassFile attributes for proxy classes)      } catch (IOException e) {         throw new InternalError("unexpected I/O Exception");     }      return bout.toByteArray(); }   addProxyMethod
/**  * Add another method to be proxied, either by creating a new  * ProxyMethod object or augmenting an old one for a duplicate  * method.  *  * "fromClass" indicates the proxy interface that the method was  * found through, which may be different from (a subinterface of)  * the method's "declaring class".  Note that the first Method  * object passed for a given name and descriptor identifies the  * Method object (and thus the declaring class) that will be  * passed to the invocation handler's "invoke" method for a given  * set of duplicate methods.  */ private void addProxyMethod(Method m, Class fromClass) {     String name = m.getName();     Class[] parameterTypes = m.getParameterTypes();     Class returnType = m.getReturnType();     Class[] exceptionTypes = m.getExceptionTypes();      String sig = name + getParameterDescriptors(parameterTypes);     List<ProxyMethod> sigmethods = proxyMethods.get(sig);     if (sigmethods != null) {         for (ProxyMethod pm : sigmethods) {             if (returnType == pm.returnType) {                 /*                  * Found a match: reduce exception types to the                  * greatest set of exceptions that can thrown                  * compatibly with the throws clauses of both                  * overridden methods.                  */                 List<Class<?>> legalExceptions = new ArrayList<Class<?>>();                 collectCompatibleTypes(                     exceptionTypes, pm.exceptionTypes, legalExceptions);                 collectCompatibleTypes(                     pm.exceptionTypes, exceptionTypes, legalExceptions);                 pm.exceptionTypes = new Class[legalExceptions.size()];                 pm.exceptionTypes =                     legalExceptions.toArray(pm.exceptionTypes);                 return;             }         }     } else {         sigmethods = new ArrayList<ProxyMethod>(3);         proxyMethods.put(sig, sigmethods);     }     sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,                                    exceptionTypes, fromClass)); }   Full code about gen the proxy method
    private MethodInfo generateMethod() throws IOException {         String desc = getMethodDescriptor(parameterTypes, returnType);         MethodInfo minfo = new MethodInfo(methodName, desc,             ACC_PUBLIC | ACC_FINAL);          int[] parameterSlot = new int[parameterTypes.length];         int nextSlot = 1;         for (int i = 0; i < parameterSlot.length; i++) {             parameterSlot[i] = nextSlot;             nextSlot += getWordsPerType(parameterTypes[i]);         }         int localSlot0 = nextSlot;         short pc, tryBegin = 0, tryEnd;          DataOutputStream out = new DataOutputStream(minfo.code);          code_aload(0, out);          out.writeByte(opc_getfield);         out.writeShort(cp.getFieldRef(             superclassName,             handlerFieldName, "Ljava/lang/reflect/InvocationHandler;"));          code_aload(0, out);          out.writeByte(opc_getstatic);         out.writeShort(cp.getFieldRef(             dotToSlash(className),             methodFieldName, "Ljava/lang/reflect/Method;"));          if (parameterTypes.length > 0) {              code_ipush(parameterTypes.length, out);              out.writeByte(opc_anewarray);             out.writeShort(cp.getClass("java/lang/Object"));              for (int i = 0; i < parameterTypes.length; i++) {                  out.writeByte(opc_dup);                  code_ipush(i, out);                  codeWrapArgument(parameterTypes[i], parameterSlot[i], out);                  out.writeByte(opc_aastore);             }         } else {              out.writeByte(opc_aconst_null);         }          out.writeByte(opc_invokeinterface);         out.writeShort(cp.getInterfaceMethodRef(             "java/lang/reflect/InvocationHandler",             "invoke",             "(Ljava/lang/Object;Ljava/lang/reflect/Method;" +                 "[Ljava/lang/Object;)Ljava/lang/Object;"));         out.writeByte(4);         out.writeByte(0);          if (returnType == void.class) {              out.writeByte(opc_pop);              out.writeByte(opc_return);          } else {              codeUnwrapReturnValue(returnType, out);         }          tryEnd = pc = (short) minfo.code.size();          List<Class<?>> catchList = computeUniqueCatchList(exceptionTypes);         if (catchList.size() > 0) {              for (Class<?> ex : catchList) {                 minfo.exceptionTable.add(new ExceptionTableEntry(                     tryBegin, tryEnd, pc,                     cp.getClass(dotToSlash(ex.getName()))));             }              out.writeByte(opc_athrow);              pc = (short) minfo.code.size();              minfo.exceptionTable.add(new ExceptionTableEntry(                 tryBegin, tryEnd, pc, cp.getClass("java/lang/Throwable")));              code_astore(localSlot0, out);              out.writeByte(opc_new);             out.writeShort(cp.getClass(                 "java/lang/reflect/UndeclaredThrowableException"));              out.writeByte(opc_dup);              code_aload(localSlot0, out);              out.writeByte(opc_invokespecial);              out.writeShort(cp.getMethodRef(                 "java/lang/reflect/UndeclaredThrowableException",                 "<init>", "(Ljava/lang/Throwable;)V"));              out.writeByte(opc_athrow);         } 
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With