use weak cache for ClassFiles

This commit is contained in:
Volker Berlin 2019-05-07 21:16:30 +02:00
parent 4e98efeb5d
commit a8d11b5b68
3 changed files with 92 additions and 7 deletions

View File

@ -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<String,ClassFile> 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 );
}
/**

View File

@ -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 <K>
* the key type
* @param <V>
* the value type
* @author Volker Berlin
*/
public class WeakValueCache<K, V> {
private final HashMap<K, WeakReference<V>> 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<V>( value ) );
}
/**
* Get the value if in the cache
*
* @param key
* the key
* @return the value or null
*/
public V get( K key ) {
WeakReference<V> valueRef = map.get( key );
return valueRef == null ? null : valueRef.get();
}
}

View File

@ -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<NamedStorageType> 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 ) {