From a8d11b5b686703acd9948831dd54df84a6099e44 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Tue, 7 May 2019 21:16:30 +0200 Subject: [PATCH] use weak cache for ClassFiles --- .../inetsoftware/classparser/ClassFile.java | 31 +++++++++- .../classparser/WeakValueCache.java | 58 +++++++++++++++++++ .../jwebassembly/module/ModuleGenerator.java | 10 ++-- 3 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 src/de/inetsoftware/classparser/WeakValueCache.java diff --git a/src/de/inetsoftware/classparser/ClassFile.java b/src/de/inetsoftware/classparser/ClassFile.java index 4be443e..8a573df 100644 --- a/src/de/inetsoftware/classparser/ClassFile.java +++ b/src/de/inetsoftware/classparser/ClassFile.java @@ -1,5 +1,5 @@ /* - Copyright 2011 - 2018 Volker Berlin (i-net software) + Copyright 2011 - 2019 Volker Berlin (i-net software) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; +import javax.annotation.Nullable; + import de.inetsoftware.classparser.Attributes.AttributeInfo; /** @@ -30,6 +32,8 @@ import de.inetsoftware.classparser.Attributes.AttributeInfo; */ public class ClassFile { + private static final WeakValueCache CACHE = new WeakValueCache<>(); + private final DataInputStream input; private final int minorVersion; @@ -56,6 +60,30 @@ public class ClassFile { private String superSignature; + /** + * Get the ClassFile from cache or load it. + * + * @param className + * the class name + * @param loader + * the ClassLoader to load + * @return the ClassFile or null + * @throws IOException + * If any I/O error occur + */ + @Nullable + public static ClassFile get( String className, ClassLoader loader ) throws IOException { + ClassFile classFile = CACHE.get( className ); + if( classFile != null ) { + return classFile; + } + InputStream stream = loader.getResourceAsStream( className + ".class" ); + if( stream != null ) { + return new ClassFile( stream ); + } + return null; + } + /** * Load a class file and create a model of the class. * @@ -109,6 +137,7 @@ public class ClassFile { } } } + CACHE.put( thisClass.getName(), this ); } /** diff --git a/src/de/inetsoftware/classparser/WeakValueCache.java b/src/de/inetsoftware/classparser/WeakValueCache.java new file mode 100644 index 0000000..3f02a7e --- /dev/null +++ b/src/de/inetsoftware/classparser/WeakValueCache.java @@ -0,0 +1,58 @@ +/* + Copyright 2019 Volker Berlin (i-net software) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +package de.inetsoftware.classparser; + +import java.lang.ref.WeakReference; +import java.util.HashMap; + +/** + * A simple cache for weak values. + * + * @param + * the key type + * @param + * the value type + * @author Volker Berlin + */ +public class WeakValueCache { + + private final HashMap> map = new HashMap<>(); + + /** + * Put a value + * + * @param key + * the key + * @param value + * the value + */ + public void put( K key, V value ) { + map.put( key, new WeakReference( value ) ); + } + + /** + * Get the value if in the cache + * + * @param key + * the key + * @return the value or null + */ + public V get( K key ) { + WeakReference valueRef = map.get( key ); + return valueRef == null ? null : valueRef.get(); + } +} diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 63b7374..7429ef1 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -162,15 +162,14 @@ public class ModuleGenerator { public void finish() throws IOException { FunctionName next; while( (next = functions.nextWriteLater()) != null ) { - InputStream stream = libraries.getResourceAsStream( next.className + ".class" ); - if( stream == null ) { + ClassFile classFile = ClassFile.get( next.className, libraries ); + if( classFile == null ) { if( next instanceof SyntheticFunctionName ) { writeMethodImpl( next, true, ((SyntheticFunctionName)next).getCodeBuilder( watParser ) ); } else { throw new WasmException( "Missing function: " + next.signatureName, -1 ); } } else { - ClassFile classFile = new ClassFile( stream ); iterateMethods( classFile, method -> { try { FunctionName name; @@ -250,11 +249,10 @@ public class ModuleGenerator { * if any I/O error occur */ private void listStructFields( String className, List list ) throws IOException { - InputStream stream = libraries.getResourceAsStream( className + ".class" ); - if( stream == null ) { + ClassFile classFile = ClassFile.get( className, libraries ); + if( classFile == null ) { throw new WasmException( "Missing class: " + className, -1 ); } - ClassFile classFile = new ClassFile( stream ); ConstantClass superClass = classFile.getSuperClass(); if( superClass != null ) {