- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我已经看到,当不同框架(例如实现 EJB 规范的框架或某些 JPA 提供程序)中发生错误时,堆栈跟踪包含像 com.sun.proxy.$Proxy
这样的类。我知道代理是什么,但我正在寻找更技术性和更具体的 Java 答案。
最佳答案
没什么特别的。和普通的 Java Class Instance 一样。
但是这些类是由java.lang.reflect.Proxy#newProxyInstance
创建的合成代理类
在 1.3 中引入
http://docs.oracle.com/javase/1.3/docs/relnotes/features.html#reflection
它是 Java 的一部分。所以每个JVM都应该支持它。
简而言之:它们是使用 JVM ASM 技术创建的(在运行时定义 javabyte 代码)
使用相同技术的东西:
java.lang.reflect.Proxy#newProxyInstance
getProxyClass0
获取了一个`Class `
ProxyGenerator.generateProxyClass
define class
来加载生成的$Proxy
类(你见过的类名)每个方法都使用相同的字节码构建
invocation handler
的 invoke()
invocation handler
的invoke()
类(字节码)以byte[]
如何绘制类
认为您的 java 代码被编译成字节码,只需在运行时执行此操作
sun/misc/ProxyGenerator.java 中的核心方法
生成类文件
/**
* 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();
}
添加代理方法
/**
* 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));
}
关于生成代理方法的完整代码
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);
}
关于java - 什么是 com.sun.proxy.$Proxy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19633534/
COM 内存泄漏最常见的原因是什么? 我读过将初始化的 CComBSTR 的地址作为 [out] 参数传递给函数会导致泄漏。我正在寻找像这样枚举其他常见的编程错误。 最佳答案 未能为 COM 对象使用
在COM服务器执行过程中分配一 block 内存,然后通过一个输出参数将该内存块传递给客户端是很常见的。然后,客户端有义务使用 CoTaskMemFree() 等方法释放该内存。 问题是,这 bloc
我有一些 MFC 代码(自定义 CWnd 控件和一些要公开的类),我需要将它们制作成带有接口(interface)的 activex/COM 对象。使用 MFC 支持制作 ATL 项目并以这种方式制作
Devenv.com 是 visual studio 命令行界面,当您键入 devenv/? 时,devenv 的帮助会出现在控制台上。但是,如果没有任何选项,devenv.com 只会调用 deve
如何将 COM 接口(interface)的引用作为 COM 库中的参数传递? 这是示例: 1)客户端代码成功创建coclass并接收到pFunctionDiscovery中的接口(interface
我正在使用 django,我在 s3 中存储了诸如 imgs 之类的东西(为此我使用的是 boto),但最近我收到了这个错误: 'foo.bar.com.s3.amazonaws.com' doesn
我已经使用组件服务 MSC 对话框创建了一个 COM+ 应用程序。我将一个现有的 COM 对象导入到这个新的 COM+ 应用程序中。 我知道可以通过 COM+ 应用程序调用该 COM 对象。我可以简单
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
我正在使用通过 COM Interop 包装器公开的第三方 dll。但是,其中一个 COM 调用经常卡住(至少从不返回)。为了至少让我的代码更健壮一些,我异步包装了调用(_getDeviceInfoW
很多年前我读到有一个简单的 php 脚本可以将您的网站重定向到 http://example.com/google.com 到 google.com它适用于正斜杠右侧的任何域。我忘记了这个脚本是什么或
我正在实现我的第一个进程外 COM 服务器(我的第一个 COM 服务器,就此而言)。我已经按照步骤编写了一个 IDL 文件,为代理/ stub DLL 生成代码,编译 DLL,并注册它。 当我检查注册
是否可以在未知接口(interface)上增加 RCW 引用计数? (即不是底层 COM 对象的引用计数) 我有一些旧的 COM 服务器代码 int Method1(object comobject)
我注意到许多关于 COM 的书籍等都指出,在 COM 聚合中实现一个可用作内部对象的对象相对容易。但是,除非我遗漏了什么,否则聚合似乎只能在极其有限的场景中成功,因此只有在明确识别出这种场景时才应提供
假设我正在开发一个安装 COM 组件并安装程序注册它们的应用程序。这很好用。 现在该软件需要从内存棒上运行。如何注册我的库运行时并确保在运行应用程序后清理注册表? 最佳答案 您总是在 XP 或更高版本
我们已经使用Microsoft的ActiveX/COM(VB6)技术开发了一个软件系统。去年,我对自动化构建过程和整个SCM越来越感兴趣。我集中搜索了网络的大部分内容,以获取有关如何使用基于COM的软
我对 com 线程模型有点困惑。 我有一个 inproc 服务器,我想创建一个可从任何线程访问的接口(interface),而不管 CoInitializeEx 中使用的线程模型和/或标志。 当将接口
我的包以旁加载方式安装,并不断遇到特定于应用程序的权限错误。 是的,许多人建议在 regedit 和组件服务中手动更改权限和所有者。 我的应用实际上在组件服务(DCOMCNFG、DCOMCNFG -3
我正在使用第三方应用程序,并调用创建 的实例。我的 COM 对象。这个调用成功了,但是第三方应用程序上的函数没有返回指向创建对象的指针(我不知道为什么)。有没有办法获得指向我的对象的指针? 为了澄清,
我有一个用 C# 编写的托管 COM 对象和一个用 C++(MFC 和 ATL)编写的 native COM 客户端和接收器。客户端创建对象并在启动时向其事件接口(interface)提供建议,并在其
我的应用程序需要注册两个 COM DLL。如果用户有必要的访问权限,它会自动完成,否则可以使用 regsvr32 完成。 . 现在在一些工作站上会发生以下情况: 开始cmd.exe作为管理员 注册第一
我是一名优秀的程序员,十分优秀!