18 package org.apache.log4j; 19 20 import org.apache.log4j.spi.LoggerRepository; 21 import org.apache.log4j.spi.LoggerFactory; 22 import org.apache.log4j.spi.RepositorySelector; 23 import org.apache.log4j.spi.DefaultRepositorySelector; 24 import org.apache.log4j.spi.RootLogger; 25 import org.apache.log4j.spi.NOPLoggerRepository; 26 import org.apache.log4j.helpers.Loader; 27 import org.apache.log4j.helpers.OptionConverter; 28 import org.apache.log4j.helpers.LogLog; 29 30 import java.net.URL; 31 import java.net.MalformedURLException; 32 33 34 import java.util.Enumeration; 35 45 public class LogManager { 46 47 /** 48 * @deprecated This variable is for internal use only. It will 49 * become package protected in future versions. 50 * */ 51 static public final String DEFAULT_CONFIGURATION_FILE = "log4j.properties"; 52 53 static final String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml"; 54 55 /** 56 * @deprecated This variable is for internal use only. It will 57 * become private in future versions. 58 * */ 59 static final public String DEFAULT_CONFIGURATION_KEY="log4j.configuration"; 60 61 /** 62 * @deprecated This variable is for internal use only. It will 63 * become private in future versions. 64 * */ 65 static final public String CONFIGURATOR_CLASS_KEY="log4j.configuratorClass"; 66 67 /** 68 * @deprecated This variable is for internal use only. It will 69 * become private in future versions. 70 */ 71 public static final String DEFAULT_INIT_OVERRIDE_KEY = 72 "log4j.defaultInitOverride"; 73 74 75 static private Object guard = null; 76 static private RepositorySelector repositorySelector; 77 78 static { 79 // By default we use a DefaultRepositorySelector which always returns 'h'. 80 Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG)); 81 repositorySelector = new DefaultRepositorySelector(h); 82 83 /** Search for the properties file log4j.properties in the CLASSPATH. */ 84 String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY, 85 null); 86 87 // if there is no default init override, then get the resource 88 // specified by the user or the default config file. 89 if(override == null || "false".equalsIgnoreCase(override)) { 90 91 String configurationOptionStr = OptionConverter.getSystemProperty( 92 DEFAULT_CONFIGURATION_KEY, 93 null); 94 95 String configuratorClassName = OptionConverter.getSystemProperty( 96 CONFIGURATOR_CLASS_KEY, 97 null); 98 99 URL url = null; 100 101 // if the user has not specified the log4j.configuration 102 // property, we search first for the file "log4j.xml" and then 103 // "log4j.properties" 104 if(configurationOptionStr == null) { 105 url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE); 106 if(url == null) { 107 url = Loader.getResource(DEFAULT_CONFIGURATION_FILE); 108 } 109 } else { 110 try { 111 url = new URL(configurationOptionStr); 112 } catch (MalformedURLException ex) { 113 // so, resource is not a URL: 114 // attempt to get the resource from the class path 115 url = Loader.getResource(configurationOptionStr); 116 } 117 } 118 119 // If we have a non-null url, then delegate the rest of the 120 // configuration to the OptionConverter.selectAndConfigure 121 // method. 122 if(url != null) { 123 LogLog.debug("Using URL ["+url+"] for automatic log4j configuration."); 124 try { 125 OptionConverter.selectAndConfigure(url, configuratorClassName, 126 LogManager.getLoggerRepository()); 127 } catch (NoClassDefFoundError e) { 128 LogLog.warn("Error during default initialization", e); 129 } 130 } else { 131 LogLog.debug("Could not find resource: ["+configurationOptionStr+"]."); 132 } 133 } 134 } 135 136 /** 137 Sets <code>LoggerFactory</code> but only if the correct 138 <em>guard</em> is passed as parameter. 139 140 <p>Initally the guard is null. If the guard is 141 <code>null</code>, then invoking this method sets the logger 142 factory and the guard. Following invocations will throw a {@link 143 IllegalArgumentException}, unless the previously set 144 <code>guard</code> is passed as the second parameter. 145 146 <p>This allows a high-level component to set the {@link 147 RepositorySelector} used by the <code>LogManager</code>. 148 149 <p>For example, when tomcat starts it will be able to install its 150 own repository selector. However, if and when Tomcat is embedded 151 within JBoss, then JBoss will install its own repository selector 152 and Tomcat will use the repository selector set by its container, 153 JBoss. */ 154 static 155 public 156 void setRepositorySelector(RepositorySelector selector, Object guard) 157 throws IllegalArgumentException { 158 if((LogManager.guard != null) && (LogManager.guard != guard)) { 159 throw new IllegalArgumentException( 160 "Attempted to reset the LoggerFactory without possessing the guard."); 161 } 162 163 if(selector == null) { 164 throw new IllegalArgumentException("RepositorySelector must be non-null."); 165 } 166 167 LogManager.guard = guard; 168 LogManager.repositorySelector = selector; 169 } 170 171 static 172 public 173 LoggerRepository getLoggerRepository() { 174 if (repositorySelector == null) { 175 repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository()); 176 guard = null; 177 LogLog.error("LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository."); 178 } 179 return repositorySelector.getLoggerRepository(); 180 } 181 182 /** 183 Retrieve the appropriate root logger. 184 */ 185 public 186 static 187 Logger getRootLogger() { 188 // Delegate the actual manufacturing of the logger to the logger repository. 189 return getLoggerRepository().getRootLogger(); 190 } 191 192 /** 193 Retrieve the appropriate {@link Logger} instance. 194 */ 195 public 196 static 197 Logger getLogger(final String name) { 198 // Delegate the actual manufacturing of the logger to the logger repository. 199 return getLoggerRepository().getLogger(name); 200 } 201 202 /** 203 Retrieve the appropriate {@link Logger} instance. 204 */ 205 public 206 static 207 Logger getLogger(final Class clazz) { 208 // Delegate the actual manufacturing of the logger to the logger repository. 209 return getLoggerRepository().getLogger(clazz.getName()); 210 } 211 212 213 /** 214 Retrieve the appropriate {@link Logger} instance. 215 */ 216 public 217 static 218 Logger getLogger(final String name, final LoggerFactory factory) { 219 // Delegate the actual manufacturing of the logger to the logger repository. 220 return getLoggerRepository().getLogger(name, factory); 221 } 222 223 public 224 static 225 Logger exists(final String name) { 226 return getLoggerRepository().exists(name); 227 } 228 229 public 230 static 231 Enumeration getCurrentLoggers() { 232 return getLoggerRepository().getCurrentLoggers(); 233 } 234 235 public 236 static 237 void shutdown() { 238 getLoggerRepository().shutdown(); 239 } 240 241 public 242 static 243 void resetConfiguration() { 244 getLoggerRepository().resetConfiguration(); 245 } 246 }
你这个问题和工厂模式没什么关系吧,你可以用log4j中getProperty获得logmanager的属性试试
18 package org.apache.log4j;
19
20 import org.apache.log4j.spi.LoggerRepository;
21 import org.apache.log4j.spi.LoggerFactory;
22 import org.apache.log4j.spi.RepositorySelector;
23 import org.apache.log4j.spi.DefaultRepositorySelector;
24 import org.apache.log4j.spi.RootLogger;
25 import org.apache.log4j.spi.NOPLoggerRepository;
26 import org.apache.log4j.helpers.Loader;
27 import org.apache.log4j.helpers.OptionConverter;
28 import org.apache.log4j.helpers.LogLog;
29
30 import java.net.URL;
31 import java.net.MalformedURLException;
32
33
34 import java.util.Enumeration;
35 45 public class LogManager {
46
47 /**
48 * @deprecated This variable is for internal use only. It will
49 * become package protected in future versions.
50 * */
51 static public final String DEFAULT_CONFIGURATION_FILE = "log4j.properties";
52
53 static final String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml";
54
55 /**
56 * @deprecated This variable is for internal use only. It will
57 * become private in future versions.
58 * */
59 static final public String DEFAULT_CONFIGURATION_KEY="log4j.configuration";
60
61 /**
62 * @deprecated This variable is for internal use only. It will
63 * become private in future versions.
64 * */
65 static final public String CONFIGURATOR_CLASS_KEY="log4j.configuratorClass";
66
67 /**
68 * @deprecated This variable is for internal use only. It will
69 * become private in future versions.
70 */
71 public static final String DEFAULT_INIT_OVERRIDE_KEY =
72 "log4j.defaultInitOverride";
73
74
75 static private Object guard = null;
76 static private RepositorySelector repositorySelector;
77
78 static {
79 // By default we use a DefaultRepositorySelector which always returns 'h'.
80 Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
81 repositorySelector = new DefaultRepositorySelector(h);
82
83 /** Search for the properties file log4j.properties in the CLASSPATH. */
84 String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,
85 null);
86
87 // if there is no default init override, then get the resource
88 // specified by the user or the default config file.
89 if(override == null || "false".equalsIgnoreCase(override)) {
90
91 String configurationOptionStr = OptionConverter.getSystemProperty(
92 DEFAULT_CONFIGURATION_KEY,
93 null);
94
95 String configuratorClassName = OptionConverter.getSystemProperty(
96 CONFIGURATOR_CLASS_KEY,
97 null);
98
99 URL url = null;
100
101 // if the user has not specified the log4j.configuration
102 // property, we search first for the file "log4j.xml" and then
103 // "log4j.properties"
104 if(configurationOptionStr == null) {
105 url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
106 if(url == null) {
107 url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
108 }
109 } else {
110 try {
111 url = new URL(configurationOptionStr);
112 } catch (MalformedURLException ex) {
113 // so, resource is not a URL:
114 // attempt to get the resource from the class path
115 url = Loader.getResource(configurationOptionStr);
116 }
117 }
118
119 // If we have a non-null url, then delegate the rest of the
120 // configuration to the OptionConverter.selectAndConfigure
121 // method.
122 if(url != null) {
123 LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
124 try {
125 OptionConverter.selectAndConfigure(url, configuratorClassName,
126 LogManager.getLoggerRepository());
127 } catch (NoClassDefFoundError e) {
128 LogLog.warn("Error during default initialization", e);
129 }
130 } else {
131 LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
132 }
133 }
134 }
135
136 /**
137 Sets <code>LoggerFactory</code> but only if the correct
138 <em>guard</em> is passed as parameter.
139
140 <p>Initally the guard is null. If the guard is
141 <code>null</code>, then invoking this method sets the logger
142 factory and the guard. Following invocations will throw a {@link
143 IllegalArgumentException}, unless the previously set
144 <code>guard</code> is passed as the second parameter.
145
146 <p>This allows a high-level component to set the {@link
147 RepositorySelector} used by the <code>LogManager</code>.
148
149 <p>For example, when tomcat starts it will be able to install its
150 own repository selector. However, if and when Tomcat is embedded
151 within JBoss, then JBoss will install its own repository selector
152 and Tomcat will use the repository selector set by its container,
153 JBoss. */
154 static
155 public
156 void setRepositorySelector(RepositorySelector selector, Object guard)
157 throws IllegalArgumentException {
158 if((LogManager.guard != null) && (LogManager.guard != guard)) {
159 throw new IllegalArgumentException(
160 "Attempted to reset the LoggerFactory without possessing the guard.");
161 }
162
163 if(selector == null) {
164 throw new IllegalArgumentException("RepositorySelector must be non-null.");
165 }
166
167 LogManager.guard = guard;
168 LogManager.repositorySelector = selector;
169 }
170
171 static
172 public
173 LoggerRepository getLoggerRepository() {
174 if (repositorySelector == null) {
175 repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());
176 guard = null;
177 LogLog.error("LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository.");
178 }
179 return repositorySelector.getLoggerRepository();
180 }
181
182 /**
183 Retrieve the appropriate root logger.
184 */
185 public
186 static
187 Logger getRootLogger() {
188 // Delegate the actual manufacturing of the logger to the logger repository.
189 return getLoggerRepository().getRootLogger();
190 }
191
192 /**
193 Retrieve the appropriate {@link Logger} instance.
194 */
195 public
196 static
197 Logger getLogger(final String name) {
198 // Delegate the actual manufacturing of the logger to the logger repository.
199 return getLoggerRepository().getLogger(name);
200 }
201
202 /**
203 Retrieve the appropriate {@link Logger} instance.
204 */
205 public
206 static
207 Logger getLogger(final Class clazz) {
208 // Delegate the actual manufacturing of the logger to the logger repository.
209 return getLoggerRepository().getLogger(clazz.getName());
210 }
211
212
213 /**
214 Retrieve the appropriate {@link Logger} instance.
215 */
216 public
217 static
218 Logger getLogger(final String name, final LoggerFactory factory) {
219 // Delegate the actual manufacturing of the logger to the logger repository.
220 return getLoggerRepository().getLogger(name, factory);
221 }
222
223 public
224 static
225 Logger exists(final String name) {
226 return getLoggerRepository().exists(name);
227 }
228
229 public
230 static
231 Enumeration getCurrentLoggers() {
232 return getLoggerRepository().getCurrentLoggers();
233 }
234
235 public
236 static
237 void shutdown() {
238 getLoggerRepository().shutdown();
239 }
240
241 public
242 static
243 void resetConfiguration() {
244 getLoggerRepository().resetConfiguration();
245 }
246 }
所以应该是只有一个LogManager的Class对象,LogManager的实例可能就不曾存在过
纯属个人猜测 技术有限 说不太清楚
读取class文件,载入MetaClass类
初始化类静态Field,Method
创建对象
初始对象Field,Method为null,0,flase
调用constructor
依次调用Filed的constructor即时里不产生对象,也会创建MetaClass类,它的生存期就是静态方法的生存期你可以用xxx.Class,或者class.forname之类的方法获得MetaClass类。
这样的类不至于多到JVM受不了,一般常见于Utility性质的类
当然你设计得不好就另当别论了
在jvm中,同一个类是可以有多个副本的,只要它们不是由同一个类载入器(ClassLoader)载入的。
至于已经载入的类何时释放的问题么,SUN的虚拟机是不会释放的,而其他的虚拟机有可能会释放,比如Oracle(BEA)的——只要类载入器被回收了就可以释放。