Skip to content

Commit e40b3de

Browse files
committed
Merge branch '7.0' into 7.1
# Conflicts: # loader/build.xml # loader/pom.xml
2 parents 18472cb + 807c447 commit e40b3de

File tree

11 files changed

+289
-101
lines changed

11 files changed

+289
-101
lines changed

core/src/main/java/lucee/commons/io/log/LogUtil.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ public static void logGlobal(Config config, String type, String msg, Throwable t
305305
logGlobal(config, Log.LEVEL_ERROR, type, msg + ";" + ExceptionUtil.getStacktrace(t, true));
306306
}
307307

308+
public static boolean does(int logLevel) {
309+
return does(ThreadLocalPageContext.getLog("application"), logLevel);
310+
}
311+
308312
public static boolean does(Log log, int logLevel) {
309313
return (log != null && log.getLogLevel() <= logLevel);
310314
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package lucee.commons.io.log;
2+
3+
import java.io.OutputStream;
4+
import java.io.PrintStream;
5+
6+
import lucee.runtime.op.Caster;
7+
8+
/**
9+
* A PrintStream that redirects all output to a Lucee Log instance.
10+
*/
11+
public class LoggingPrintStream extends PrintStream {
12+
13+
private final Log log;
14+
private final String logName;
15+
private final int logLevel;
16+
17+
public LoggingPrintStream(Log log, String logName, int logLevel) {
18+
super(new OutputStream() {
19+
@Override
20+
public void write(int b) {
21+
// Required but not used - we override the print methods
22+
}
23+
});
24+
this.log = log;
25+
this.logName = logName;
26+
this.logLevel = logLevel;
27+
}
28+
29+
@Override
30+
public void println(String x) {
31+
if (x != null && !x.trim().isEmpty()) {
32+
log.log(logLevel, logName, x);
33+
}
34+
}
35+
36+
@Override
37+
public void print(String s) {
38+
if (s != null && !s.trim().isEmpty()) {
39+
log.log(logLevel, logName, s);
40+
}
41+
}
42+
43+
@Override
44+
public void println(Object x) {
45+
if (x != null) {
46+
log.log(logLevel, logName, Caster.toString(x, null));
47+
}
48+
}
49+
50+
@Override
51+
public void print(Object obj) {
52+
if (obj != null) {
53+
log.log(logLevel, logName, Caster.toString(obj, null));
54+
}
55+
}
56+
57+
@Override
58+
public PrintStream format(String format, Object... args) {
59+
log.log(logLevel, logName, String.format(format, args));
60+
return this;
61+
}
62+
}

core/src/main/java/lucee/commons/lang/PhysicalClassLoader.java

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,18 @@ public final class PhysicalClassLoader extends URLClassLoader implements Extenda
5454
boolean res = registerAsParallelCapable();
5555
}
5656

57-
private static final double CLASSLOADER_INSPECTION_SIZE = Caster.toIntValue(SystemUtil.getSystemPropOrEnvVar("lucee.template.classloader.inspection.size", null), 2000);
57+
private static final double CLASSLOADER_INSPECTION_SIZE = Caster.toIntValue(SystemUtil.getSystemPropOrEnvVar("lucee.template.classloader.inspection.size", null), 100);
58+
private static final double CLASSLOADER_INSPECTION_SIZEBYTES = CLASSLOADER_INSPECTION_SIZE * 1024 * 1024;
59+
private static final double CLASSLOADER_INSPECTION_COUNT = Caster.toIntValue(SystemUtil.getSystemPropOrEnvVar("lucee.template.classloader.inspection.count", null), 1000);
5860
private static final double CLASSLOADER_INSPECTION_RATIO = Caster.toIntValue(SystemUtil.getSystemPropOrEnvVar("lucee.template.classloader.inspection.ratio", null), 3);
5961

6062
private final Resource directory;
6163
private ConfigPro config;
6264
private final ClassLoader addionalClassLoader;
6365
private final List<Resource> resources;
6466

65-
private Map<String, String> loadedClasses = new ConcurrentHashMap<>();
66-
private Map<String, String> allLoadedClasses = new ConcurrentHashMap<>(); // this includes all renames
67+
private Map<String, Integer> loadedClasses = new ConcurrentHashMap<>();
68+
private Map<String, Integer> allLoadedClasses = new ConcurrentHashMap<>(); // this includes all renames
6769
private Map<String, String> unavaiClasses = new ConcurrentHashMap<>();
6870

6971
private PageSourcePool pageSourcePool;
@@ -109,20 +111,55 @@ public static PhysicalClassLoader flush(PhysicalClassLoader existing, Config con
109111
count += ClazzDynamic.remove(existing);
110112
int all = existing.allLoadedClasses.size();
111113
int unique = existing.loadedClasses.size();
112-
LogUtil.log(Log.LEVEL_INFO, "physical-classloader", "flush physical classloader [" + existing.getDirectory() + "] because we reached the size limit (all loaded classes: "
113-
+ all + "; unique loaded classes: " + unique + "; ratio: " + (all / unique) + "), removed " + count + " cache elements from dynamic invoker");
114+
int allClassesBytes = 0;
115+
for (Integer i: existing.allLoadedClasses.values()) {
116+
allClassesBytes += i.intValue();
117+
}
118+
LogUtil.log(Log.LEVEL_INFO, "physical-classloader",
119+
"flush physical classloader [" + existing.getDirectory() + "] because we reached the size limit (all loaded classes count/size: " + all + "/"
120+
+ StringUtil.byteFormat(allClassesBytes) + "; unique loaded classes: " + unique + "; ratio: " + (all / unique) + "), removed " + count
121+
+ " cache elements from dynamic invoker");
114122

115123
return clone;
116124
}
117125

118126
public static PhysicalClassLoader flushIfNecessary(PhysicalClassLoader existing, Config config) {
119127
double all;
120128

129+
if (LogUtil.does(Log.LEVEL_DEBUG)) {
130+
int allClasses = existing.allLoadedClasses.size();
131+
int allClassesBytes = 0;
132+
int uniqueClasses = existing.loadedClasses.size();
133+
double ratio = uniqueClasses > 0 ? (double) allClasses / uniqueClasses : 0;
134+
135+
for (Integer i: existing.allLoadedClasses.values()) {
136+
allClassesBytes += i.intValue();
137+
}
138+
139+
LogUtil.log(Log.LEVEL_DEBUG, "physical-classloader",
140+
"checking if flush necessary for physical classloader [" + existing.getDirectory() + "]: " + "all loaded classes: " + allClasses + " ("
141+
+ StringUtil.byteFormat(allClassesBytes) + "), " + "unique loaded classes: " + uniqueClasses + ", " + "ratio: " + String.format("%.2f", ratio) + ", "
142+
+ "inspection size threshold: " + Caster.toString(CLASSLOADER_INSPECTION_COUNT) + "/" + Caster.toString(CLASSLOADER_INSPECTION_SIZE) + ", "
143+
+ "inspection ratio threshold: " + CLASSLOADER_INSPECTION_RATIO + " - "
144+
+ (allClasses > CLASSLOADER_INSPECTION_SIZE
145+
? (ratio > CLASSLOADER_INSPECTION_RATIO ? "FLUSHING (size and ratio thresholds exceeded)"
146+
: "NOT flushing (ratio " + String.format("%.2f", ratio) + " below threshold " + CLASSLOADER_INSPECTION_RATIO + ")")
147+
: "NOT flushing (size " + allClasses + " below threshold " + CLASSLOADER_INSPECTION_SIZE + ")"));
148+
}
149+
121150
// check size
122-
if ((all = existing.allLoadedClasses.size()) > CLASSLOADER_INSPECTION_SIZE) {
151+
if ((all = existing.allLoadedClasses.size()) > CLASSLOADER_INSPECTION_COUNT) {
123152
if ((all / existing.loadedClasses.size()) > CLASSLOADER_INSPECTION_RATIO) {
124153
return flush(existing, config);
125154
}
155+
156+
int allClassesBytes = 0;
157+
for (Integer i: existing.allLoadedClasses.values()) {
158+
allClassesBytes += i.intValue();
159+
}
160+
if (allClassesBytes > CLASSLOADER_INSPECTION_SIZEBYTES) {
161+
return flush(existing, config);
162+
}
126163
}
127164
return null;
128165
}
@@ -276,6 +313,13 @@ public Class<?> loadClass(String name, byte[] barr) throws UnmodifiableClassExce
276313
synchronized (getClassLoadingLock(name)) {
277314
Class<?> clazz = findLoadedClass(name);
278315
if (clazz == null) return _loadClass(name, barr, false);
316+
317+
/*
318+
* Instrumentation instr = InstrumentationFactory.getInstrumentation(config); if (instr != null) {
319+
* try { instr.redefineClasses(new ClassDefinition(clazz, barr)); return clazz; } catch (Exception
320+
* e) { LogUtil.log(InstrumentationFactory.class.getName(), e); } }
321+
*/
322+
279323
return rename(clazz, barr);
280324
}
281325
}
@@ -350,8 +394,8 @@ private Class<?> _loadClass(String name, byte[] barr, boolean rename) {
350394
Class<?> clazz = defineClass(name, barr, 0, barr.length);
351395

352396
if (clazz != null) {
353-
if (!rename) loadedClasses.put(name, name);
354-
allLoadedClasses.put(name, name);
397+
if (!rename) loadedClasses.put(name, barr.length);
398+
allLoadedClasses.put(name, barr.length);
355399

356400
resolveClass(clazz);
357401
}

core/src/main/java/lucee/commons/lang/StringUtil.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ public final class StringUtil {
103103
private static final Pattern SPACES = Pattern.compile("\\s+");
104104

105105
private static final char[] SURROGATE_CHARACTERS_RANGE = new char[] { (char) 55296, (char) 57343 };
106+
private static final Pair<Long, String>[] byteValues = new Pair[] { new Pair<Long, String>(1099511627776L, "TB"), new Pair<Long, String>(1073741824L, "GB"),
107+
new Pair<Long, String>(1048576L, "MB"), new Pair<Long, String>(1024L, "KB") };
106108

107109
/**
108110
* do first Letter Upper case
@@ -1584,4 +1586,14 @@ public static String normalize(String str) {
15841586
}
15851587
return SPACES.matcher(str).replaceAll(" ");
15861588
}
1589+
1590+
public static String byteFormat(long size) {
1591+
for (Pair<Long, String> pair: byteValues) {
1592+
if (size >= pair.getName()) {
1593+
double result = (double) size / pair.getName();
1594+
return Caster.toString(Caster.toLongValue(result)) + "" + pair.getValue();
1595+
}
1596+
}
1597+
return size + "B";
1598+
}
15871599
}

core/src/main/java/lucee/runtime/config/maven/MavenUpdateProvider.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,7 @@ public final class MavenUpdateProvider {
5656
private static final Repository DEFAULT_REPOSITORY_SONATYPE_LAST90 = new Repository("Sonatype Repositry for Snapshots (last 90 days)",
5757
"https://central.sonatype.com/repository/maven-snapshots/", Repository.TIMEOUT_15MINUTES, Repository.TIMEOUT_NEVER);
5858

59-
// old up to version 7.0.0.275-SNAPSHOT
60-
private static final Repository DEFAULT_REPOSITORY_SONATYPE_LEGACY = new Repository("Old Sonatype Repositry for Snapshots",
61-
"https://oss.sonatype.org/content/repositories/snapshots/", Repository.TIMEOUT_NEVER, Repository.TIMEOUT_NEVER);
62-
63-
private static final Repository[] DEFAULT_REPOSITORY_SNAPSHOTS_CORE = new Repository[] { DEFAULT_REPOSITORY_SONATYPE_LAST90, DEFAULT_REPOSITORY_SONATYPE_LEGACY };
59+
private static final Repository[] DEFAULT_REPOSITORY_SNAPSHOTS_CORE = new Repository[] { DEFAULT_REPOSITORY_SONATYPE_LAST90 };
6460
private static final Repository[] DEFAULT_REPOSITORY_SNAPSHOTS_EXTENSIONS = new Repository[] { DEFAULT_REPOSITORY_SONATYPE_LAST90 };
6561

6662
private static final Repository[] DEFAULT_REPOSITORY_RELEASES = new Repository[] {
@@ -396,7 +392,6 @@ private Map<String, Object> readFromCache(Repository repository, String artifact
396392
try {
397393
Resource resLastmod = repository.cacheDirectory
398394
.getRealResource("detail_" + HashUtil.create64BitHashAsString(group + "_" + artifact + "_" + version + "_lastmod", Character.MAX_RADIX));
399-
400395
if (resLastmod.isFile()) {
401396
long lastmod = repository.timeoutDetail == Repository.TIMEOUT_NEVER ? Repository.TIMEOUT_NEVER
402397
: Caster.toLongValue(IOUtil.toString(resLastmod, CharsetUtil.UTF8), 0L);

core/src/main/java/lucee/runtime/exp/TemplateException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public TemplateException(PageSource ps, int line, int column, Throwable t) {
8181
* @param message
8282
*/
8383
public TemplateException(SourceCode sc, String message) {
84-
this(getPageSource(sc), sc.getLine(), sc.getColumn(), message);
84+
this(getPageSource(sc), sc.getLine(), sc.getColumn(), message + ", at [" + sc.getLine() + ":" + sc.getColumn() + "] in [" + sc.getLineAsString() + "]");
8585
}
8686

8787
public TemplateException(SourceCode sc, int line, int column, String message) {

0 commit comments

Comments
 (0)