많은 XML 처리를 수행하는 거대한 클래스 경로가있는 다소 큰 Java ee 응용 프로그램이 있습니다. 현재 샘플링 기능을 통해 일부 기능의 속도를 높이고 느린 코드 경로를 찾으려고합니다.
내가 알았던 한 가지는 특히 코드가 호출되는 코드의 일부 TransformerFactory.newInstance(...)
가 필연적으로 느리다는 것입니다. 나는 항상 새로운 인스턴스를 만드는 FactoryFinder
방법으로 이것을 추적했습니다 . 에서 의 javadoc 나는 캐싱에 대해 다음과 같은 메모를 발견 :findServiceProvider
ServiceLoader
ServiceLoader
공급자는 느리게 (즉, 요청시) 인스턴스화되고 인스턴스화됩니다. 서비스 로더는 지금까지로드 된 제공자의 캐시를 유지 보수합니다. iterator 메소드를 호출 할 때마다 먼저 캐시의 모든 요소를 인스턴스화 순서로 생성 한 다음 나머지 제공자를 느리게 찾아서 인스턴스화하여 각 제공자를 캐시에 차례로 추가합니다. 캐시는 reload 메소드를 통해 지울 수 있습니다.
여태까지는 그런대로 잘됐다. 이것은 OpenJDK FactoryFinder#findServiceProvider
메소드 의 일부입니다 :
private static <T> T findServiceProvider(final Class<T> type)
throws TransformerFactoryConfigurationError
{
try {
return AccessController.doPrivileged(new PrivilegedAction<T>() {
public T run() {
final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
final Iterator<T> iterator = serviceLoader.iterator();
if (iterator.hasNext()) {
return iterator.next();
} else {
return null;
}
}
});
} catch(ServiceConfigurationError e) {
...
}
}
모든 findServiceProvider
통화 ServiceLoader.load
. 매번 새로운 ServiceLoader 가 생성 됩니다. 이런 식으로 ServiceLoaders 캐싱 메커니즘을 전혀 사용하지 않는 것 같습니다. 모든 호출은 요청 된 ServiceProvider에 대한 클래스 경로를 스캔합니다.
내가 이미 시도한 것 :
javax.xml.transform.TransformerFactory
특정 구현을 지정하는 것과 같은 시스템 속성을 설정할 수 있다는 것을 알고 있습니다 . 이런 식으로 FactoryFinder는 ServiceLoader 프로세스와 그 초고속을 사용하지 않습니다. 슬프게도 이것은 jvm 전체 속성이며 내 jvm에서 실행되는 다른 Java 프로세스에 영향을 미칩니다. 예를 들어 내 응용 프로그램은 Saxon과 함께 제공되며 Saxon과 함께com.saxonica.config.EnterpriseTransformerFactory
제공되지 않는 다른 응용 프로그램을 사용해야합니다 . 시스템 속성을 설정하자마자com.saxonica.config.EnterpriseTransformerFactory
클래스 경로에 다른 응용 프로그램이 없기 때문에 다른 응용 프로그램이 시작되지 않습니다 . 그래서 이것은 나를위한 옵션이 아닌 것 같습니다.- 나는 이미
TransformerFactory.newInstance
호출 된 모든 장소를 리팩터링 하고 TransformerFactory를 캐시합니다. 그러나 코드를 리팩터링 할 수없는 다양한 종속성이 있습니다.
내 질문은 : FactoryFinder가 ServiceLoader를 재사용하지 않는 이유는 무엇입니까? 시스템 속성을 사용하는 것 외에이 전체 ServiceLoader 프로세스의 속도를 높일 수있는 방법이 있습니까? FactoryFinder가 ServiceLoader 인스턴스를 재사용 할 수 있도록 JDK에서이를 변경할 수 없습니까? 또한 이것은 단일 FactoryFinder에만 국한되지 않습니다. 이 bahaviour는 javax.xml
지금까지 본 패키지의 모든 FactoryFinder 클래스에 대해 동일합니다 .
OpenJDK 8/11을 사용하고 있습니다. 내 응용 프로그램은 Tomcat 9 인스턴스에 배포됩니다.
편집 : 자세한 내용 제공
단일 XMLInputFactory.newInstance 호출에 대한 호출 스택은 다음과 같습니다.
대부분의 리소스가 사용되는 위치는입니다 ServiceLoaders$LazyIterator.hasNextService
. 이 메소드 getResources
는 META-INF/services/javax.xml.stream.XMLInputFactory
파일 을 읽기 위해 ClassLoader를 호출 합니다. 그 호출만으로도 매번 약 35ms가 걸립니다.
Tomcat에게 이러한 파일을 더 잘 캐시하여 더 빠르게 제공하도록 지시하는 방법이 있습니까?
-D
플래그를 사용하여 속성을 설정하려고 했습니까 Tomcat
? 예를 들어 -Djavax.xml.transform.TransformerFactory=<factory class>.
다른 앱의 속성을 재정의해서는 안됩니다. 귀하의 게시물이 잘 설명되어 있으며 아마도 시도했지만 확인하고 싶습니다. 참조 javax.xml.transform.TransformerFactory의 시스템 속성을 설정하는 방법 , 어떻게 톰캣에 HeapMemory 또는 JVM 인수를 설정