day1-jvm+leetcode

本文记录了作者研二期间为提升自我而进行的JVM学习,包括JVM的好处、内存结构如程序计数器、虚拟机栈、本地方法栈、堆和方法区的详解,以及垃圾回收、内存溢出诊断和LeetCode题目练习。通过实例分析了线程安全、动态拼接字符串等问题,并分享了学习过程中的挑战和经验。
摘要由CSDN通过智能技术生成
	先说一下为啥写文章吧,马上研二了,老师不管我也没好好学习,现在实习也找不到,真是干啥啥
不行,为了不做five,决定开始写文章记录学习,顺带在晚上回顾每天学习的内容,希望能做到日更。
	再简单说一下自己目前的目标吧,jvm+各种其他面经弄清楚,刷题top100,写一个网页版斗地主,优化
之前的项目,部署。先这样,希望自己能坚持。

今日总结

看了黑马jvm 1-34
leetcode 做了top 3道简单的
看了一点websocket

JVM

jvm的好处

java的(二进制字节码)运行环境

  1. 一次编写,到处运行
  2. 自动内存管理,垃圾回收功能
  3. 数组下标越界检查
  4. 底层用虚方法实现多态

image.png

内存结构

1 程序计数器

Program Counter Register
Java代码运行流程:
代码-解释器-机器码-cpu

  • 作用:记住下一条指令地址
  • 特点
    • 线程私有
    • 不会存在内存溢出

2 虚拟机栈

栈-线程运行需要的内存空间
栈桢-每个方法运行时需要的内存(存参数、局部变量、返回地址)
每个线程只有一个活动栈桢,对应当前正在执行的方法

相关面试题

  1. 垃圾回收是否设计栈内存?
    • 不需要,会自己弹出栈
  2. 栈内存分配越大越好吗?
    • 不是,物理内存时一定的,栈内存越大,线程数就会少了。
  3. 方法内的局部变量是否线程安全?
  • 局部变量是线程私有的线程安全。
  • 作为方法参数传递的时候会有线程安全问题(会被共享)。
  • 作为方法返回值也有有问题。(会被共享)
  • 结论:没有逃离方法的作用访问范围是安全的,局部变量引用对象并逃离作用范围,有线程安全问题。

栈内存溢出

错误名称:java.lang.StackOverflowError
原因:

  • 栈桢过多(递归没有结束条件,循环引用一个里面有另一个)
  • 栈桢过大

线程运行诊断

  • 案例1 : cpu占用过多
    • 定位怎么占用

(1): linux 下
top:查看系统占用,看是哪个进程占用过高
ps :看是哪个线程占用过高
ps H -eo pid,tid,%cpu | grep 进程id
(2):用jdk的方法
根据jstack找到有问题的线程,进一步定位到问题的行数

  • 案例2 :程序运行很长时间没有结果

jstack+进程id 能看见死锁

3 本地方法栈

native method stacks:用c/c++编写的api
比如: Object的clone()
wait()、hashcode()、wait()、notify()、notifyAll()

4 堆

heap堆:用new 创建的对象使用堆内存
特点:

  • 线程共享,需要考虑线程安全问题
  • 有垃圾回收机制

堆内存溢出

java.lang.OutOfMemoryError:Java heap space

堆内存诊断
  1. jps 工具
    • 查看系统中有哪些java 进程
  2. jmap工具
    • 查看堆内存占用情况
  3. jconsole工具
    • 连续监测

使用jmap的时候出现问题,image.png
经搜索可能是jdk版本问题,于是改成jdk11
image.png
image.png
image.png
搞错了…再来,要改环境里的mac版本,因为用的是命令行
mac下的操作:
先进入/Library/Java/JavaVirtualMachines找到版本号名称
vim ~/.bash_profile
修改 JAVA_HOME的版本号
source /etc/profile保存即可
参考https://www.jianshu.com/p/4fd5f6bc6dfb
然后就OK了
image.png
但是问题仍然没有解决…
image.png于是使用提示的
image.png
…??又出现了一开始的问题,人麻了
权限问题
image.png
还是不行…
https://zhuanlan.zhihu.com/p/399352540
刷到一个帖子…还是去年的,也没成功,算了放弃,麻了还是用jconsole


  • 案例:垃圾回收之后内存占用仍然很高

先装jvisualVM
https://blog.csdn.net/Tanganling/article/details/119790892


方法区

定义:是所有java虚拟机线程共享的一个区(现在在本地内存上),存储了和类的结构相关的一些信息:运行时常量池、成员变量,方法数据,成员方法,构造器方法以及一些特殊方法。虚拟机启动时创建,在逻辑上是堆的一个组成部分。永久代和元空间是方法区的一个实现。方法区也会内存溢出
image.png

内存溢出

  • 1.8之前永久代
  • 1.8之后元空间

场景:spring和mybatis用cjlib代理动态生成类生成很多运行时的类,永久代垃圾回收比 较差。

常量池

实际上就是一张表,根据这张表找到要执行的类名、方法名、参数类型、字面量等信息。
二进制字节码包括:类基本信息,常量池,类方法定义,虚拟机指令
getstatic:获取静态变量
ldc: 加载一个参数
invokevirtual:执行一次虚方法调用

运行时常量池

一个类运行时要放到内存里,放在内存中的位置就是运行时常量池

StringTable 串池

常量池中的信息都会被加载到运行时常量池,还没变成java字符串对象。
ldc的时候,会把到StringTable里面去找,没有的话会把符号变成字符串对象放进串池。用到的时候才区创建(懒加载)。
StringTable是一个hashtable的结构,不能扩容。

  • 拼接

String s3 = s1+s2 ;
创建一个新的StringBuilder并调用构造方法。
image.png
image.png
s3是串池中的,s4是new的,所以false
image.png
s5是看拼接后的值(在编译器拼接的,因为都是常量,之前的s1,s2都是常量)串池中是否有,所以是true。
image.png
动态拼接的元素不会存在串池中,像下面这种,”a“和"b"会出现在串池中,"ab"不会存在串池中(动态拼接),会放到堆里,只有常量才会放进去
image.png
调用s.intern()方法会尝试放入串池,并把串池中的对象返回
image.png
两个都是true,因为都是同一个
image.png
上ture:因为都是从常量池取出来的
下false:s那个是new出来的

Leetcode

461 汉明距离

直接用了循环,每次和1与就可以了

338 比特位计数

  1. 用循环,复杂度太高
  2. 动态规划,只有最后一位不一样,所以看 右移一位(已经存在)+最后一位是否有变化

215 数组中的第K个最大元素

是个排序题,自己看文章准备自己实现手动,结果发现还挺有难度,之前学的全忘了,而且理论和实践也是两码事,目前才写了5个简单的,明天一起总结吧。

最后想说

今天学了很长时间,可能和考研时候差不多了,因为真的突然感受到自己的无能为力,希望能坚持!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值