NutzCN Logo
问答 ioc获取对象报错 Ioc depose tigger by GC!!!
发布于 2917天前 作者 ansjsun 4035 次浏览 复制 上一个帖子 下一个帖子
标签: ioc
public static <T> T instance(Class<T> c, String iocPath) throws Exception {
		Ioc ioc = new NutIoc(new JsonLoader(iocPath));

		Mirror<?> mirror = Mirror.me(c);
		T obj = c.newInstance();

		for (Field field : mirror.getFields()) {
			Inject inject = field.getAnnotation(Inject.class);
			if (inject != null) {
				if (field.getType().equals(org.apache.log4j.Logger.class)) {
					LOG.warn("org.apache.log4j.Logger Deprecated please use org.slf4j.Logger by LoggerFactory");
					mirror.setValue(obj, field, org.apache.log4j.Logger.getLogger(c));
				} else if (field.getType().equals(org.slf4j.Logger.class)) {
					mirror.setValue(obj, field, LoggerFactory.getLogger(c));
				} else {
					mirror.setValue(obj, field, ioc.get(field.getType(), StringUtil.isBlank(inject.value()) ? field.getName() : inject.value()));
				}
			}
		}

		return obj;
	}

想通过ioc文件实例化一个对象.然后调用这个对象的方法..之前都好好的升级后报如下错误

13:03:33,220 ERROR org.nutz.ioc.impl.NutIoc - Ioc depose tigger by GC!!!
Common Reason for that is YOUR code call 'new NutIoc(...)', and then get some beans(most is Dao) from it and abandon it!!!
If using nutz.mvc, call Mvcs.ctx().getDefaultIoc() to get ioc container.
org.nutz.ioc.IocException: [tokenizerService] # For object [tokenizerService] - type:[class cn.com.infcn.mss.TokenizerService]
	at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:218)
	at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:239)
	at cn.com.infcn.mss.query.parse.MethodExe.method(MethodExe.java:66)
	at cn.com.infcn.mss.query.parse.Parse.invoke(Parse.java:73)
	at cn.com.infcn.mss.query.parse.Parse.format(Parse.java:85)
	at cn.com.infcn.msp.MssSearchApi._queryParse(MssSearchApi.java:299)
	at cn.com.infcn.msp.MssSearchApi.queryParse(MssSearchApi.java:211)
	at cn.com.infcn.mss.MssSearchApiTest.queryParseTest(MssSearchApiTest.java:69)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.nutz.ioc.ObjectLoadException: Object 'tokenizerService' without define!
	at org.nutz.ioc.loader.combo.ComboIocLoader.load(ComboIocLoader.java:174)
	at org.nutz.ioc.impl.NutIoc.get(NutIoc.java:180)
	... 31 more


4 回复

第一个警告的意思是, 有一个Ioc容器, 被创建了, 在某个时间点又被GC, 然后触发自动depose.

既然是被GC,证明已经没有强引用这个Ioc容器. 注意, 引用ioc容器持有的ioc bean, 并不等于引用了ioc容器.

例如:

Ioc ioc = new NutIoc(.....);

return ioc.get(Dao.class);

上述代码中, ioc容器被创建, 然后从中取出了Dao实例

然后, 再没有对象直接/间接引用ioc, JVM会发现这个ioc已经满足GC的条件, 然后在某个时间点将其GC掉.

在GC时, 会调用对象的finalize方法, 所以, JVM调用了ioc.finalize, 而NutIoc的finalize方法,会检查自身是否已经销毁, 如果还没有, 则自行调用depose.

第二个问题,可以看到是调用ioc.get时抛出异常, 所以, 这个报错的上下文中, ioc容器是被引用状态(不然怎么调用).

既然是被引用的状态,那么, 肯定不会被GC, JVM也不会调用ioc.finalize, 所以, 唯一合理的解释就是: 这不是同一个ioc对象.

Object 'tokenizerService' without define! 的意思是本Ioc容器内没有找到名称为tokenizerService的对象

不同ioc容器之间是不会互通的.

Ioc ioc1 = new NutIoc(...); // 含ABC的配置
Ioc ioc2 = new NutIoc(...); // 不含ABC的配置

ioc1.get(ABC.class); // ABC存在于ioc1, 正常返回
ioc2.get(ABC.class); // ABC不存在于ioc2, 抛异常

兽总.我对不起你..我错了 :( 一个低级错误....错误....错误....

添加回复
请先登陆
回到顶部